From 09494ea545738538f9db2dceeffe10d421060ee5 Mon Sep 17 00:00:00 2001 From: Vincent Quenneville-Belair Date: Thu, 16 Apr 2020 15:01:14 -0400 Subject: [PATCH 01/73] set version. --- .circleci/config.yml | 4 ++-- .circleci/config.yml.in | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index b4fd761c00..b62bb37c12 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -15,11 +15,11 @@ binary_common: &binary_common build_version: description: "version number of release binary; by default, build a nightly" type: string - default: "" + default: "0.5.0" pytorch_version: description: "PyTorch version to build against; by default, use a nightly" type: string - default: "" + default: "1.5.0" # Don't edit these python_version: description: "Python version to build against (e.g., 3.8)" diff --git a/.circleci/config.yml.in b/.circleci/config.yml.in index f5f985c982..fb3316969a 100644 --- a/.circleci/config.yml.in +++ b/.circleci/config.yml.in @@ -15,11 +15,11 @@ binary_common: &binary_common build_version: description: "version number of release binary; by default, build a nightly" type: string - default: "" + default: "0.5.0" pytorch_version: description: "PyTorch version to build against; by default, use a nightly" type: string - default: "" + default: "1.5.0" # Don't edit these python_version: description: "Python version to build against (e.g., 3.8)" From 4f76758408c346bf3f4b3f1ac606f2b75753cd7c Mon Sep 17 00:00:00 2001 From: cpuhrsch Date: Tue, 28 Apr 2020 16:58:21 -0400 Subject: [PATCH 02/73] Re-sync with internal repository (#592) --- .circleci/config.yml | 597 ------------------ .circleci/config.yml.in | 263 -------- .circleci/docker/Dockerfile | 36 -- .circleci/regenerate.py | 124 ---- .circleci/test/test_sort_yaml.py | 14 - .clang-format | 88 --- .clang-tidy | 33 - .flake8 | 4 - .github/ISSUE_TEMPLATE/bug-report.md | 53 -- .github/ISSUE_TEMPLATE/documentation.md | 9 - .github/ISSUE_TEMPLATE/feature-request.md | 24 - .../ISSUE_TEMPLATE/questions-help-support.md | 13 - .gitignore | 123 ---- .python3 | 0 .travis.yml | 36 -- 15 files changed, 1417 deletions(-) delete mode 100644 .circleci/config.yml delete mode 100644 .circleci/config.yml.in delete mode 100644 .circleci/docker/Dockerfile delete mode 100755 .circleci/regenerate.py delete mode 100755 .circleci/test/test_sort_yaml.py delete mode 100644 .clang-format delete mode 100644 .clang-tidy delete mode 100644 .flake8 delete mode 100644 .github/ISSUE_TEMPLATE/bug-report.md delete mode 100644 .github/ISSUE_TEMPLATE/documentation.md delete mode 100644 .github/ISSUE_TEMPLATE/feature-request.md delete mode 100644 .github/ISSUE_TEMPLATE/questions-help-support.md delete mode 100644 .gitignore create mode 100644 .python3 delete mode 100644 .travis.yml diff --git a/.circleci/config.yml b/.circleci/config.yml deleted file mode 100644 index b62bb37c12..0000000000 --- a/.circleci/config.yml +++ /dev/null @@ -1,597 +0,0 @@ -version: 2.1 - -# How to test the Linux jobs: -# - Install CircleCI local CLI: https://circleci.com/docs/2.0/local-cli/ -# - circleci config process .circleci/config.yml > gen.yml && circleci local execute -c gen.yml --job binary_linux_wheel_py3.8 -# - Replace binary_linux_wheel_py3.8 with the name of the job you want to test. -# Job names are 'name:' key. - -orbs: - win: circleci/windows@2.0.0 - -binary_common: &binary_common - parameters: - # Edit these defaults to do a release - build_version: - description: "version number of release binary; by default, build a nightly" - type: string - default: "0.5.0" - pytorch_version: - description: "PyTorch version to build against; by default, use a nightly" - type: string - default: "1.5.0" - # Don't edit these - python_version: - description: "Python version to build against (e.g., 3.8)" - type: string - unicode_abi: - description: "Python 2.7 wheel only: whether or not we are cp27mu (default: no)" - type: string - default: "" - environment: - PYTHON_VERSION: << parameters.python_version >> - BUILD_VERSION: << parameters.build_version >> - PYTORCH_VERSION: << parameters.pytorch_version >> - UNICODE_ABI: << parameters.unicode_abi >> - CU_VERSION: cpu - -smoke_test_common: &smoke_test_common - <<: *binary_common - docker: - - image: 308535385114.dkr.ecr.us-east-1.amazonaws.com/torchaudio/smoke_test:d26af7d0-8458-face-book-84239b5c75c0 - aws_auth: - aws_access_key_id: ${ECR_AWS_ACCESS_KEY} - aws_secret_access_key: ${ECR_AWS_SECRET_ACCESS_KEY} - -jobs: - circleci_consistency: - docker: - - image: circleci/python:3.8 - steps: - - checkout - - run: - command: | - pip install --user --progress-bar off jinja2 pyyaml - python .circleci/regenerate.py - git diff --exit-code || (echo ".circleci/config.yml not in sync with config.yml.in! Run .circleci/regenerate.py to update config"; exit 1) - - binary_linux_wheel: - <<: *binary_common - docker: - - image: "pytorch/manylinux-cuda100" - resource_class: 2xlarge+ - steps: - - checkout - - run: packaging/build_wheel.sh - - store_artifacts: - path: dist - - persist_to_workspace: - root: dist - paths: - - "*" - - binary_linux_conda: - <<: *binary_common - docker: - - image: "pytorch/conda-cuda" - resource_class: 2xlarge+ - steps: - - checkout - - run: packaging/build_conda.sh - - store_artifacts: - path: /opt/conda/conda-bld/linux-64 - - persist_to_workspace: - root: /opt/conda/conda-bld/linux-64 - paths: - - "*" - - binary_win_conda: - <<: *binary_common - executor: - name: win/default - shell: bash.exe - steps: - - checkout - - run: - command: | - choco install miniconda3 - (& "C:\tools\miniconda3\Scripts\conda.exe" "shell.powershell" "hook") | Out-String | Invoke-Expression - conda activate base - conda install -yq conda-build "conda-package-handling!=1.5.0" - bash packaging/build_conda.sh - shell: powershell.exe - - binary_macos_wheel: - <<: *binary_common - macos: - xcode: "9.0" - steps: - - checkout - - run: - # Cannot easily deduplicate this as source'ing activate - # will set environment variables which we need to propagate - # to build_wheel.sh - command: | - curl -o conda.sh https://repo.anaconda.com/miniconda/Miniconda3-latest-MacOSX-x86_64.sh - sh conda.sh -b - source $HOME/miniconda3/bin/activate - packaging/build_wheel.sh - - store_artifacts: - path: dist - - persist_to_workspace: - root: dist - paths: - - "*" - - binary_macos_conda: - <<: *binary_common - macos: - xcode: "9.0" - steps: - - checkout - - run: - command: | - curl -o conda.sh https://repo.anaconda.com/miniconda/Miniconda3-latest-MacOSX-x86_64.sh - sh conda.sh -b - source $HOME/miniconda3/bin/activate - conda install -yq conda-build - packaging/build_conda.sh - - store_artifacts: - path: /Users/distiller/miniconda3/conda-bld/osx-64 - - persist_to_workspace: - root: /Users/distiller/miniconda3/conda-bld/osx-64 - paths: - - "*" - - # Requires org-member context - binary_conda_upload: - docker: - - image: continuumio/miniconda - steps: - - attach_workspace: - at: ~/workspace - - run: - command: | - # Prevent credential from leaking - conda install -yq anaconda-client - set -x - anaconda -t "${CONDA_PYTORCHBOT_TOKEN}" upload ~/workspace/*.tar.bz2 -u pytorch-nightly --label main --no-progress --force - - # Requires org-member context - binary_wheel_upload: - docker: - - image: circleci/python:3.8 - steps: - - attach_workspace: - at: ~/workspace - - checkout - - run: - command: | - pip install --user awscli - export PATH="$HOME/.local/bin:$PATH" - # Prevent credential from leaking - set +x - export AWS_ACCESS_KEY_ID="${PYTORCH_BINARY_AWS_ACCESS_KEY_ID}" - export AWS_SECRET_ACCESS_KEY="${PYTORCH_BINARY_AWS_SECRET_ACCESS_KEY}" - set -x - for pkg in ~/workspace/*.whl; do - aws s3 cp "$pkg" "s3://pytorch/whl/nightly/" --acl public-read - done - - smoke_test_linux_conda: - <<: *smoke_test_common - steps: - - attach_workspace: - at: ~/workspace - - run: - name: install binaries - command: | - set -x - source /usr/local/etc/profile.d/conda.sh && conda activate python${PYTHON_VERSION} - conda install -v -y -c pytorch-nightly pytorch - conda install -v -y $(ls ~/workspace/torchaudio*.tar.bz2) - - run: - name: smoke test - command: | - source /usr/local/etc/profile.d/conda.sh && conda activate python${PYTHON_VERSION} - python -c "import torchaudio" - - smoke_test_linux_pip: - <<: *smoke_test_common - steps: - - attach_workspace: - at: ~/workspace - - run: - name: install binaries - command: | - set -x - source /usr/local/etc/profile.d/conda.sh && conda activate python${PYTHON_VERSION} - pip install $(ls ~/workspace/torchaudio*.whl) -f https://download.pytorch.org/whl/nightly/torch_nightly.html - - run: - name: smoke test - command: | - source /usr/local/etc/profile.d/conda.sh && conda activate python${PYTHON_VERSION} - python -c "import torchaudio" - - docker_image_build: - machine: - image: ubuntu-1604:201903-01 - resource_class: large - environment: - image_name: torchaudio/smoke_test - steps: - - checkout - - run: - name: build_docker image - no_output_timeout: "1h" - command: | - cd .circleci/docker && docker build . -t ${image_name}:${CIRCLE_WORKFLOW_ID} - - run: - name: upload docker image - no_output_timeout: "1h" - command: | - set +x - export AWS_ACCESS_KEY_ID=${ECR_AWS_ACCESS_KEY} - export AWS_SECRET_ACCESS_KEY=${ECR_AWS_SECRET_ACCESS_KEY} - eval $(aws ecr get-login --region us-east-1 --no-include-email) - set -x - docker tag ${image_name}:${CIRCLE_WORKFLOW_ID} 308535385114.dkr.ecr.us-east-1.amazonaws.com/${image_name}:${CIRCLE_WORKFLOW_ID} - docker push 308535385114.dkr.ecr.us-east-1.amazonaws.com/${image_name}:${CIRCLE_WORKFLOW_ID} - -workflows: - build: - jobs: - - circleci_consistency - - binary_linux_wheel: - name: binary_linux_wheel_py3.5 - python_version: '3.5' - - binary_linux_wheel: - name: binary_linux_wheel_py3.6 - python_version: '3.6' - - binary_linux_wheel: - name: binary_linux_wheel_py3.7 - python_version: '3.7' - - binary_linux_wheel: - name: binary_linux_wheel_py3.8 - python_version: '3.8' - - binary_macos_wheel: - name: binary_macos_wheel_py3.5 - python_version: '3.5' - - binary_macos_wheel: - name: binary_macos_wheel_py3.6 - python_version: '3.6' - - binary_macos_wheel: - name: binary_macos_wheel_py3.7 - python_version: '3.7' - - binary_macos_wheel: - name: binary_macos_wheel_py3.8 - python_version: '3.8' - - binary_linux_conda: - name: binary_linux_conda_py3.5 - python_version: '3.5' - - binary_linux_conda: - name: binary_linux_conda_py3.6 - python_version: '3.6' - - binary_linux_conda: - name: binary_linux_conda_py3.7 - python_version: '3.7' - - binary_linux_conda: - name: binary_linux_conda_py3.8 - python_version: '3.8' - - binary_macos_conda: - name: binary_macos_conda_py3.5 - python_version: '3.5' - - binary_macos_conda: - name: binary_macos_conda_py3.6 - python_version: '3.6' - - binary_macos_conda: - name: binary_macos_conda_py3.7 - python_version: '3.7' - - binary_macos_conda: - name: binary_macos_conda_py3.8 - python_version: '3.8' - - binary_win_conda: - name: torchaudio_win_py3.6 - python_version: "3.6" - - nightly: - jobs: - - circleci_consistency - - binary_linux_wheel: - filters: - branches: - only: nightly - name: nightly_binary_linux_wheel_py3.5 - python_version: '3.5' - - binary_wheel_upload: - context: org-member - filters: - branches: - only: nightly - name: nightly_binary_linux_wheel_py3.5_upload - requires: - - nightly_binary_linux_wheel_py3.5 - - smoke_test_linux_pip: - filters: - branches: - only: nightly - name: nightly_binary_linux_wheel_py3.5_smoke_test_pip - python_version: '3.5' - requires: - - nightly_binary_linux_wheel_py3.5_upload - - binary_linux_wheel: - filters: - branches: - only: nightly - name: nightly_binary_linux_wheel_py3.6 - python_version: '3.6' - - binary_wheel_upload: - context: org-member - filters: - branches: - only: nightly - name: nightly_binary_linux_wheel_py3.6_upload - requires: - - nightly_binary_linux_wheel_py3.6 - - smoke_test_linux_pip: - filters: - branches: - only: nightly - name: nightly_binary_linux_wheel_py3.6_smoke_test_pip - python_version: '3.6' - requires: - - nightly_binary_linux_wheel_py3.6_upload - - binary_linux_wheel: - filters: - branches: - only: nightly - name: nightly_binary_linux_wheel_py3.7 - python_version: '3.7' - - binary_wheel_upload: - context: org-member - filters: - branches: - only: nightly - name: nightly_binary_linux_wheel_py3.7_upload - requires: - - nightly_binary_linux_wheel_py3.7 - - smoke_test_linux_pip: - filters: - branches: - only: nightly - name: nightly_binary_linux_wheel_py3.7_smoke_test_pip - python_version: '3.7' - requires: - - nightly_binary_linux_wheel_py3.7_upload - - binary_linux_wheel: - filters: - branches: - only: nightly - name: nightly_binary_linux_wheel_py3.8 - python_version: '3.8' - - binary_wheel_upload: - context: org-member - filters: - branches: - only: nightly - name: nightly_binary_linux_wheel_py3.8_upload - requires: - - nightly_binary_linux_wheel_py3.8 - - smoke_test_linux_pip: - filters: - branches: - only: nightly - name: nightly_binary_linux_wheel_py3.8_smoke_test_pip - python_version: '3.8' - requires: - - nightly_binary_linux_wheel_py3.8_upload - - binary_macos_wheel: - filters: - branches: - only: nightly - name: nightly_binary_macos_wheel_py3.5 - python_version: '3.5' - - binary_wheel_upload: - context: org-member - filters: - branches: - only: nightly - name: nightly_binary_macos_wheel_py3.5_upload - requires: - - nightly_binary_macos_wheel_py3.5 - - binary_macos_wheel: - filters: - branches: - only: nightly - name: nightly_binary_macos_wheel_py3.6 - python_version: '3.6' - - binary_wheel_upload: - context: org-member - filters: - branches: - only: nightly - name: nightly_binary_macos_wheel_py3.6_upload - requires: - - nightly_binary_macos_wheel_py3.6 - - binary_macos_wheel: - filters: - branches: - only: nightly - name: nightly_binary_macos_wheel_py3.7 - python_version: '3.7' - - binary_wheel_upload: - context: org-member - filters: - branches: - only: nightly - name: nightly_binary_macos_wheel_py3.7_upload - requires: - - nightly_binary_macos_wheel_py3.7 - - binary_macos_wheel: - filters: - branches: - only: nightly - name: nightly_binary_macos_wheel_py3.8 - python_version: '3.8' - - binary_wheel_upload: - context: org-member - filters: - branches: - only: nightly - name: nightly_binary_macos_wheel_py3.8_upload - requires: - - nightly_binary_macos_wheel_py3.8 - - binary_linux_conda: - filters: - branches: - only: nightly - name: nightly_binary_linux_conda_py3.5 - python_version: '3.5' - - binary_conda_upload: - context: org-member - filters: - branches: - only: nightly - name: nightly_binary_linux_conda_py3.5_upload - requires: - - nightly_binary_linux_conda_py3.5 - - smoke_test_linux_conda: - filters: - branches: - only: nightly - name: nightly_binary_linux_conda_py3.5_smoke_test_conda - python_version: '3.5' - requires: - - nightly_binary_linux_conda_py3.5_upload - - binary_linux_conda: - filters: - branches: - only: nightly - name: nightly_binary_linux_conda_py3.6 - python_version: '3.6' - - binary_conda_upload: - context: org-member - filters: - branches: - only: nightly - name: nightly_binary_linux_conda_py3.6_upload - requires: - - nightly_binary_linux_conda_py3.6 - - smoke_test_linux_conda: - filters: - branches: - only: nightly - name: nightly_binary_linux_conda_py3.6_smoke_test_conda - python_version: '3.6' - requires: - - nightly_binary_linux_conda_py3.6_upload - - binary_linux_conda: - filters: - branches: - only: nightly - name: nightly_binary_linux_conda_py3.7 - python_version: '3.7' - - binary_conda_upload: - context: org-member - filters: - branches: - only: nightly - name: nightly_binary_linux_conda_py3.7_upload - requires: - - nightly_binary_linux_conda_py3.7 - - smoke_test_linux_conda: - filters: - branches: - only: nightly - name: nightly_binary_linux_conda_py3.7_smoke_test_conda - python_version: '3.7' - requires: - - nightly_binary_linux_conda_py3.7_upload - - binary_linux_conda: - filters: - branches: - only: nightly - name: nightly_binary_linux_conda_py3.8 - python_version: '3.8' - - binary_conda_upload: - context: org-member - filters: - branches: - only: nightly - name: nightly_binary_linux_conda_py3.8_upload - requires: - - nightly_binary_linux_conda_py3.8 - - smoke_test_linux_conda: - filters: - branches: - only: nightly - name: nightly_binary_linux_conda_py3.8_smoke_test_conda - python_version: '3.8' - requires: - - nightly_binary_linux_conda_py3.8_upload - - binary_macos_conda: - filters: - branches: - only: nightly - name: nightly_binary_macos_conda_py3.5 - python_version: '3.5' - - binary_conda_upload: - context: org-member - filters: - branches: - only: nightly - name: nightly_binary_macos_conda_py3.5_upload - requires: - - nightly_binary_macos_conda_py3.5 - - binary_macos_conda: - filters: - branches: - only: nightly - name: nightly_binary_macos_conda_py3.6 - python_version: '3.6' - - binary_conda_upload: - context: org-member - filters: - branches: - only: nightly - name: nightly_binary_macos_conda_py3.6_upload - requires: - - nightly_binary_macos_conda_py3.6 - - binary_macos_conda: - filters: - branches: - only: nightly - name: nightly_binary_macos_conda_py3.7 - python_version: '3.7' - - binary_conda_upload: - context: org-member - filters: - branches: - only: nightly - name: nightly_binary_macos_conda_py3.7_upload - requires: - - nightly_binary_macos_conda_py3.7 - - binary_macos_conda: - filters: - branches: - only: nightly - name: nightly_binary_macos_conda_py3.8 - python_version: '3.8' - - binary_conda_upload: - context: org-member - filters: - branches: - only: nightly - name: nightly_binary_macos_conda_py3.8_upload - requires: - - nightly_binary_macos_conda_py3.8 - docker_build: - triggers: - - schedule: - cron: "0 10 * * 0" - filters: - branches: - only: - - master - jobs: - - docker_image_build \ No newline at end of file diff --git a/.circleci/config.yml.in b/.circleci/config.yml.in deleted file mode 100644 index fb3316969a..0000000000 --- a/.circleci/config.yml.in +++ /dev/null @@ -1,263 +0,0 @@ -version: 2.1 - -# How to test the Linux jobs: -# - Install CircleCI local CLI: https://circleci.com/docs/2.0/local-cli/ -# - circleci config process .circleci/config.yml > gen.yml && circleci local execute -c gen.yml --job binary_linux_wheel_py3.8 -# - Replace binary_linux_wheel_py3.8 with the name of the job you want to test. -# Job names are 'name:' key. - -orbs: - win: circleci/windows@2.0.0 - -binary_common: &binary_common - parameters: - # Edit these defaults to do a release - build_version: - description: "version number of release binary; by default, build a nightly" - type: string - default: "0.5.0" - pytorch_version: - description: "PyTorch version to build against; by default, use a nightly" - type: string - default: "1.5.0" - # Don't edit these - python_version: - description: "Python version to build against (e.g., 3.8)" - type: string - unicode_abi: - description: "Python 2.7 wheel only: whether or not we are cp27mu (default: no)" - type: string - default: "" - environment: - PYTHON_VERSION: << parameters.python_version >> - BUILD_VERSION: << parameters.build_version >> - PYTORCH_VERSION: << parameters.pytorch_version >> - UNICODE_ABI: << parameters.unicode_abi >> - CU_VERSION: cpu - -smoke_test_common: &smoke_test_common - <<: *binary_common - docker: - - image: 308535385114.dkr.ecr.us-east-1.amazonaws.com/torchaudio/smoke_test:d26af7d0-8458-face-book-84239b5c75c0 - aws_auth: - aws_access_key_id: ${ECR_AWS_ACCESS_KEY} - aws_secret_access_key: ${ECR_AWS_SECRET_ACCESS_KEY} - -jobs: - circleci_consistency: - docker: - - image: circleci/python:3.8 - steps: - - checkout - - run: - command: | - pip install --user --progress-bar off jinja2 pyyaml - python .circleci/regenerate.py - git diff --exit-code || (echo ".circleci/config.yml not in sync with config.yml.in! Run .circleci/regenerate.py to update config"; exit 1) - - binary_linux_wheel: - <<: *binary_common - docker: - - image: "pytorch/manylinux-cuda100" - resource_class: 2xlarge+ - steps: - - checkout - - run: packaging/build_wheel.sh - - store_artifacts: - path: dist - - persist_to_workspace: - root: dist - paths: - - "*" - - binary_linux_conda: - <<: *binary_common - docker: - - image: "pytorch/conda-cuda" - resource_class: 2xlarge+ - steps: - - checkout - - run: packaging/build_conda.sh - - store_artifacts: - path: /opt/conda/conda-bld/linux-64 - - persist_to_workspace: - root: /opt/conda/conda-bld/linux-64 - paths: - - "*" - - binary_win_conda: - <<: *binary_common - executor: - name: win/default - shell: bash.exe - steps: - - checkout - - run: - command: | - choco install miniconda3 - (& "C:\tools\miniconda3\Scripts\conda.exe" "shell.powershell" "hook") | Out-String | Invoke-Expression - conda activate base - conda install -yq conda-build "conda-package-handling!=1.5.0" - bash packaging/build_conda.sh - shell: powershell.exe - - binary_macos_wheel: - <<: *binary_common - macos: - xcode: "9.0" - steps: - - checkout - - run: - # Cannot easily deduplicate this as source'ing activate - # will set environment variables which we need to propagate - # to build_wheel.sh - command: | - curl -o conda.sh https://repo.anaconda.com/miniconda/Miniconda3-latest-MacOSX-x86_64.sh - sh conda.sh -b - source $HOME/miniconda3/bin/activate - packaging/build_wheel.sh - - store_artifacts: - path: dist - - persist_to_workspace: - root: dist - paths: - - "*" - - binary_macos_conda: - <<: *binary_common - macos: - xcode: "9.0" - steps: - - checkout - - run: - command: | - curl -o conda.sh https://repo.anaconda.com/miniconda/Miniconda3-latest-MacOSX-x86_64.sh - sh conda.sh -b - source $HOME/miniconda3/bin/activate - conda install -yq conda-build - packaging/build_conda.sh - - store_artifacts: - path: /Users/distiller/miniconda3/conda-bld/osx-64 - - persist_to_workspace: - root: /Users/distiller/miniconda3/conda-bld/osx-64 - paths: - - "*" - - # Requires org-member context - binary_conda_upload: - docker: - - image: continuumio/miniconda - steps: - - attach_workspace: - at: ~/workspace - - run: - command: | - # Prevent credential from leaking - conda install -yq anaconda-client - set -x - anaconda -t "${CONDA_PYTORCHBOT_TOKEN}" upload ~/workspace/*.tar.bz2 -u pytorch-nightly --label main --no-progress --force - - # Requires org-member context - binary_wheel_upload: - docker: - - image: circleci/python:3.8 - steps: - - attach_workspace: - at: ~/workspace - - checkout - - run: - command: | - pip install --user awscli - export PATH="$HOME/.local/bin:$PATH" - # Prevent credential from leaking - set +x - export AWS_ACCESS_KEY_ID="${PYTORCH_BINARY_AWS_ACCESS_KEY_ID}" - export AWS_SECRET_ACCESS_KEY="${PYTORCH_BINARY_AWS_SECRET_ACCESS_KEY}" - set -x - for pkg in ~/workspace/*.whl; do - aws s3 cp "$pkg" "s3://pytorch/whl/nightly/" --acl public-read - done - - smoke_test_linux_conda: - <<: *smoke_test_common - steps: - - attach_workspace: - at: ~/workspace - - run: - name: install binaries - command: | - set -x - source /usr/local/etc/profile.d/conda.sh && conda activate python${PYTHON_VERSION} - conda install -v -y -c pytorch-nightly pytorch - conda install -v -y $(ls ~/workspace/torchaudio*.tar.bz2) - - run: - name: smoke test - command: | - source /usr/local/etc/profile.d/conda.sh && conda activate python${PYTHON_VERSION} - python -c "import torchaudio" - - smoke_test_linux_pip: - <<: *smoke_test_common - steps: - - attach_workspace: - at: ~/workspace - - run: - name: install binaries - command: | - set -x - source /usr/local/etc/profile.d/conda.sh && conda activate python${PYTHON_VERSION} - pip install $(ls ~/workspace/torchaudio*.whl) -f https://download.pytorch.org/whl/nightly/torch_nightly.html - - run: - name: smoke test - command: | - source /usr/local/etc/profile.d/conda.sh && conda activate python${PYTHON_VERSION} - python -c "import torchaudio" - - docker_image_build: - machine: - image: ubuntu-1604:201903-01 - resource_class: large - environment: - image_name: torchaudio/smoke_test - steps: - - checkout - - run: - name: build_docker image - no_output_timeout: "1h" - command: | - cd .circleci/docker && docker build . -t ${image_name}:${CIRCLE_WORKFLOW_ID} - - run: - name: upload docker image - no_output_timeout: "1h" - command: | - set +x - export AWS_ACCESS_KEY_ID=${ECR_AWS_ACCESS_KEY} - export AWS_SECRET_ACCESS_KEY=${ECR_AWS_SECRET_ACCESS_KEY} - eval $(aws ecr get-login --region us-east-1 --no-include-email) - set -x - docker tag ${image_name}:${CIRCLE_WORKFLOW_ID} 308535385114.dkr.ecr.us-east-1.amazonaws.com/${image_name}:${CIRCLE_WORKFLOW_ID} - docker push 308535385114.dkr.ecr.us-east-1.amazonaws.com/${image_name}:${CIRCLE_WORKFLOW_ID} - -workflows: - build: - jobs: - - circleci_consistency - {{ workflows() }} - - binary_win_conda: - name: torchaudio_win_py3.6 - python_version: "3.6" - - nightly: - jobs: - - circleci_consistency - {{ workflows(prefix="nightly_", filter_branch="nightly", upload=True) }} - docker_build: - triggers: - - schedule: - cron: "0 10 * * 0" - filters: - branches: - only: - - master - jobs: - - docker_image_build diff --git a/.circleci/docker/Dockerfile b/.circleci/docker/Dockerfile deleted file mode 100644 index 6066668694..0000000000 --- a/.circleci/docker/Dockerfile +++ /dev/null @@ -1,36 +0,0 @@ -# this Dockerfile is for torchaudio smoke test, it will be created periodically via CI system -# if you need to do it locally, follow below steps once you have Docker installed -# assuming you're within the directory where this Dockerfile located -# $ docker build . -t torchaudio/smoketest - -# if you want to push to aws ecr, make sure you have the rights to write to ECR, then run -# $ eval $(aws ecr get-login --region us-east-1 --no-include-email) -# $ export MYTAG=localbuild ## you can choose whatever tag you like -# $ docker tag torchaudio/smoketest 308535385114.dkr.ecr.us-east-1.amazonaws.com/torchaudio/smoke_test:${MYTAG} -# $ docker push 308535385114.dkr.ecr.us-east-1.amazonaws.com/torchaudio/smoke_test:${MYTAG} - -FROM ubuntu:latest - -RUN apt-get -qq update && apt-get -qq -y install curl bzip2 sox libsox-dev libsox-fmt-all \ - && curl -sSL https://repo.continuum.io/miniconda/Miniconda3-latest-Linux-x86_64.sh -o /tmp/miniconda.sh \ - && bash /tmp/miniconda.sh -bfp /usr/local \ - && rm -rf /tmp/miniconda.sh \ - && conda install -y python=3 \ - && conda update conda \ - && apt-get -qq -y remove curl bzip2 \ - && apt-get -qq -y autoremove \ - && apt-get autoclean \ - && rm -rf /var/lib/apt/lists/* /var/log/dpkg.log \ - && conda clean --all --yes - -ENV PATH /opt/conda/bin:$PATH - -RUN conda create -y --name python3.5 python=3.5 -RUN conda create -y --name python3.6 python=3.6 -RUN conda create -y --name python3.7 python=3.7 -SHELL [ "/bin/bash", "-c" ] -RUN echo "source /usr/local/etc/profile.d/conda.sh" >> ~/.bashrc -RUN source /usr/local/etc/profile.d/conda.sh && conda activate python3.5 && conda install -y -c conda-forge sox && conda install -y numpy -RUN source /usr/local/etc/profile.d/conda.sh && conda activate python3.6 && conda install -y -c conda-forge sox && conda install -y numpy -RUN source /usr/local/etc/profile.d/conda.sh && conda activate python3.7 && conda install -y -c conda-forge sox && conda install -y numpy -CMD [ "/bin/bash"] diff --git a/.circleci/regenerate.py b/.circleci/regenerate.py deleted file mode 100755 index 19f52be756..0000000000 --- a/.circleci/regenerate.py +++ /dev/null @@ -1,124 +0,0 @@ -#!/usr/bin/env python3 - -""" -This script should use a very simple, functional programming style. -Avoid Jinja macros in favor of native Python functions. - -Don't go overboard on code generation; use Python only to generate -content that can't be easily declared statically using CircleCI's YAML API. - -Data declarations (e.g. the nested loops for defining the configuration matrix) -should be at the top of the file for easy updating. - -See this comment for design rationale: -https://github.com/pytorch/vision/pull/1321#issuecomment-531033978 -""" - -import jinja2 -import yaml -import os.path - - -def workflows(prefix='', upload=False, filter_branch=None, indentation=6): - w = [] - for btype in ["wheel", "conda"]: - for os_type in ["linux", "macos"]: - for python_version in ["3.5", "3.6", "3.7", "3.8"]: - for unicode in ([False, True] if btype == "wheel" and python_version == "2.7" else [False]): - w += workflow_pair(btype, os_type, python_version, unicode, filter_branch, prefix, upload) - - return indent(indentation, w) - - -def workflow_pair(btype, os_type, python_version, unicode, filter_branch, prefix='', upload=False): - - w = [] - unicode_suffix = "_unicode" if unicode else "" - base_workflow_name = "{prefix}binary_{os_type}_{btype}_py{python_version}{unicode_suffix}".format( - prefix=prefix, - os_type=os_type, - btype=btype, - python_version=python_version, - unicode_suffix=unicode_suffix) - - w.append(generate_base_workflow(base_workflow_name, python_version, unicode, filter_branch, os_type, btype)) - - if upload: - - is_py3_linux = os_type == 'linux' and not python_version.startswith("2.") - - w.append(generate_upload_workflow(base_workflow_name, filter_branch, btype)) - - if filter_branch == 'nightly' and is_py3_linux: - pydistro = 'pip' if btype == 'wheel' else 'conda' - w.append(generate_smoketest_workflow(pydistro, base_workflow_name, filter_branch, python_version)) - - return w - - -def generate_base_workflow(base_workflow_name, python_version, unicode, filter_branch, os_type, btype): - - d = { - "name": base_workflow_name, - "python_version": python_version, - } - - if unicode: - d["unicode_abi"] = '1' - - if filter_branch: - d["filters"] = gen_filter_branch_tree(filter_branch) - - return {"binary_{os_type}_{btype}".format(os_type=os_type, btype=btype): d} - - -def gen_filter_branch_tree(branch_name): - return {"branches": {"only": branch_name}} - - -def generate_upload_workflow(base_workflow_name, filter_branch, btype): - d = { - "name": "{base_workflow_name}_upload".format(base_workflow_name=base_workflow_name), - "context": "org-member", - "requires": [base_workflow_name], - } - - if filter_branch: - d["filters"] = gen_filter_branch_tree(filter_branch) - - return {"binary_{btype}_upload".format(btype=btype): d} - - -def generate_smoketest_workflow(pydistro, base_workflow_name, filter_branch, python_version): - - required_build_suffix = "_upload" - required_build_name = base_workflow_name + required_build_suffix - - smoke_suffix = "smoke_test_{pydistro}".format(pydistro=pydistro) - d = { - "name": "{base_workflow_name}_{smoke_suffix}".format( - base_workflow_name=base_workflow_name, smoke_suffix=smoke_suffix), - "requires": [required_build_name], - "python_version": python_version, - } - - if filter_branch: - d["filters"] = gen_filter_branch_tree(filter_branch) - - return {"smoke_test_linux_{pydistro}".format(pydistro=pydistro): d} - - -def indent(indentation, data_list): - return ("\n" + " " * indentation).join(yaml.dump(data_list).splitlines()) - - -if __name__ == "__main__": - d = os.path.dirname(__file__) - env = jinja2.Environment( - loader=jinja2.FileSystemLoader(d), - lstrip_blocks=True, - autoescape=False, - ) - - with open(os.path.join(d, 'config.yml'), 'w') as f: - f.write(env.get_template('config.yml.in').render(workflows=workflows)) diff --git a/.circleci/test/test_sort_yaml.py b/.circleci/test/test_sort_yaml.py deleted file mode 100755 index dc6db481dd..0000000000 --- a/.circleci/test/test_sort_yaml.py +++ /dev/null @@ -1,14 +0,0 @@ -#!/usr/bin/env python3 - -""" -To compare new version with previous: - - ./regenerate.sh - meld <(git show HEAD:./config.yml | ./sort-yaml.py) <(cat config.yml | ./sort-yaml.py) -""" - - -import sys -import yaml - -sys.stdout.write(yaml.dump(yaml.load(sys.stdin, Loader=yaml.FullLoader), sort_keys=True)) diff --git a/.clang-format b/.clang-format deleted file mode 100644 index 73304266bd..0000000000 --- a/.clang-format +++ /dev/null @@ -1,88 +0,0 @@ ---- -AccessModifierOffset: -1 -AlignAfterOpenBracket: AlwaysBreak -AlignConsecutiveAssignments: false -AlignConsecutiveDeclarations: false -AlignEscapedNewlinesLeft: true -AlignOperands: false -AlignTrailingComments: false -AllowAllParametersOfDeclarationOnNextLine: false -AllowShortBlocksOnASingleLine: false -AllowShortCaseLabelsOnASingleLine: false -AllowShortFunctionsOnASingleLine: Empty -AllowShortIfStatementsOnASingleLine: false -AllowShortLoopsOnASingleLine: false -AlwaysBreakAfterReturnType: None -AlwaysBreakBeforeMultilineStrings: true -AlwaysBreakTemplateDeclarations: true -BinPackArguments: false -BinPackParameters: false -BraceWrapping: - AfterClass: false - AfterControlStatement: false - AfterEnum: false - AfterFunction: false - AfterNamespace: false - AfterObjCDeclaration: false - AfterStruct: false - AfterUnion: false - BeforeCatch: false - BeforeElse: false - IndentBraces: false -BreakBeforeBinaryOperators: None -BreakBeforeBraces: Attach -BreakBeforeTernaryOperators: true -BreakConstructorInitializersBeforeComma: false -BreakAfterJavaFieldAnnotations: false -BreakStringLiterals: false -ColumnLimit: 80 -CommentPragmas: '^ IWYU pragma:' -CompactNamespaces: false -ConstructorInitializerAllOnOneLineOrOnePerLine: true -ConstructorInitializerIndentWidth: 4 -ContinuationIndentWidth: 4 -Cpp11BracedListStyle: true -DerivePointerAlignment: false -DisableFormat: false -ForEachMacros: [ FOR_EACH_RANGE, FOR_EACH, ] -IncludeCategories: - - Regex: '^<.*\.h(pp)?>' - Priority: 1 - - Regex: '^<.*' - Priority: 2 - - Regex: '.*' - Priority: 3 -IndentCaseLabels: true -IndentWidth: 2 -IndentWrappedFunctionNames: false -KeepEmptyLinesAtTheStartOfBlocks: false -MacroBlockBegin: '' -MacroBlockEnd: '' -MaxEmptyLinesToKeep: 1 -NamespaceIndentation: None -ObjCBlockIndentWidth: 2 -ObjCSpaceAfterProperty: false -ObjCSpaceBeforeProtocolList: false -PenaltyBreakBeforeFirstCallParameter: 1 -PenaltyBreakComment: 300 -PenaltyBreakFirstLessLess: 120 -PenaltyBreakString: 1000 -PenaltyExcessCharacter: 1000000 -PenaltyReturnTypeOnItsOwnLine: 2000000 -PointerAlignment: Left -ReflowComments: true -SortIncludes: true -SpaceAfterCStyleCast: false -SpaceBeforeAssignmentOperators: true -SpaceBeforeParens: ControlStatements -SpaceInEmptyParentheses: false -SpacesBeforeTrailingComments: 1 -SpacesInAngles: false -SpacesInContainerLiterals: true -SpacesInCStyleCastParentheses: false -SpacesInParentheses: false -SpacesInSquareBrackets: false -Standard: Cpp11 -TabWidth: 8 -UseTab: Never -... diff --git a/.clang-tidy b/.clang-tidy deleted file mode 100644 index a3a40b5907..0000000000 --- a/.clang-tidy +++ /dev/null @@ -1,33 +0,0 @@ ---- -# NOTE there must be no spaces before the '-', so put the comma first. -Checks: ' - -* - ,bugprone-* - ,-bugprone-forward-declaration-namespace - ,-bugprone-macro-parentheses - ,cppcoreguidelines-* - ,-cppcoreguidelines-interfaces-global-init - ,-cppcoreguidelines-owning-memory - ,-cppcoreguidelines-pro-bounds-array-to-pointer-decay - ,-cppcoreguidelines-pro-bounds-constant-array-index - ,-cppcoreguidelines-pro-bounds-pointer-arithmetic - ,-cppcoreguidelines-pro-type-cstyle-cast - ,-cppcoreguidelines-pro-type-reinterpret-cast - ,-cppcoreguidelines-pro-type-static-cast-downcast - ,-cppcoreguidelines-pro-type-union-access - ,-cppcoreguidelines-pro-type-vararg - ,-cppcoreguidelines-special-member-functions - ,hicpp-exception-baseclass - ,hicpp-avoid-goto - ,modernize-* - ,-modernize-return-braced-init-list - ,-modernize-use-auto - ,-modernize-use-default-member-init - ,-modernize-use-using - ,performance-unnecessary-value-param - ' -WarningsAsErrors: '*' -HeaderFilterRegex: 'torchaudio/.*' -AnalyzeTemporaryDtors: false -CheckOptions: -... diff --git a/.flake8 b/.flake8 deleted file mode 100644 index 388d81d723..0000000000 --- a/.flake8 +++ /dev/null @@ -1,4 +0,0 @@ -[flake8] -max-line-length = 120 -ignore = E305,E402,E721,E741,F401,F403,F405,F999,W503,W504 -exclude = build,docs/source,_ext diff --git a/.github/ISSUE_TEMPLATE/bug-report.md b/.github/ISSUE_TEMPLATE/bug-report.md deleted file mode 100644 index fb50bd8504..0000000000 --- a/.github/ISSUE_TEMPLATE/bug-report.md +++ /dev/null @@ -1,53 +0,0 @@ ---- -name: "\U0001F41B Bug Report" -about: Submit a bug report to help us improve Torchaudio - ---- - -## ๐Ÿ› Bug - - - -## To Reproduce - -Steps to reproduce the behavior: - -1. -1. -1. - - - -## Expected behavior - - - -## Environment - - - What commands did you used to install torchaudio (conda/pip/build from source)? - - If you are building from source, which commit is it? - - What does `torchaudio.__version__` print? (If applicable) - -Please copy and paste the output from our -[environment collection script](https://raw.githubusercontent.com/pytorch/pytorch/master/torch/utils/collect_env.py) -(or fill out the checklist below manually). - -You can get the script and run it with: -``` -wget https://raw.githubusercontent.com/pytorch/pytorch/master/torch/utils/collect_env.py -# For security purposes, please check the contents of collect_env.py before running it. -python collect_env.py -``` - - - PyTorch Version (e.g., 1.0): - - OS (e.g., Linux): - - How you installed PyTorch (`conda`, `pip`, source): - - Build command you used (if compiling from source): - - Python version: - - CUDA/cuDNN version: - - GPU models and configuration: - - Any other relevant information: - -## Additional context - - diff --git a/.github/ISSUE_TEMPLATE/documentation.md b/.github/ISSUE_TEMPLATE/documentation.md deleted file mode 100644 index ae745121c5..0000000000 --- a/.github/ISSUE_TEMPLATE/documentation.md +++ /dev/null @@ -1,9 +0,0 @@ ---- -name: "\U0001F4DA Documentation" -about: Report an issue related to https://pytorch.org/audio - ---- - -## ๐Ÿ“š Documentation - - diff --git a/.github/ISSUE_TEMPLATE/feature-request.md b/.github/ISSUE_TEMPLATE/feature-request.md deleted file mode 100644 index f3896e5368..0000000000 --- a/.github/ISSUE_TEMPLATE/feature-request.md +++ /dev/null @@ -1,24 +0,0 @@ ---- -name: "\U0001F680Feature Request" -about: Submit a proposal/request for a new Torchaudio feature - ---- - -## ๐Ÿš€ Feature - - -## Motivation - - - -## Pitch - - - -## Alternatives - - - -## Additional context - - diff --git a/.github/ISSUE_TEMPLATE/questions-help-support.md b/.github/ISSUE_TEMPLATE/questions-help-support.md deleted file mode 100644 index 77bfb55b9a..0000000000 --- a/.github/ISSUE_TEMPLATE/questions-help-support.md +++ /dev/null @@ -1,13 +0,0 @@ ---- -name: "โ“Questions/Help/Support" -about: Do you need support? We have resources. - ---- - -## โ“ Questions and Help - -### Please note that this issue tracker is not a help form and this issue will be closed. - -We have a set of [listed resources available on the website](https://pytorch.org/resources). Our primary means of support is our discussion forum: - -- [Discussion Forum](https://discuss.pytorch.org/) diff --git a/.gitignore b/.gitignore deleted file mode 100644 index 41a434acb2..0000000000 --- a/.gitignore +++ /dev/null @@ -1,123 +0,0 @@ -# Byte-compiled / optimized / DLL files -__pycache__/ -*.py[cod] -*$py.class - -# temp files -~* -*.swp - -# C extensions / folders -*.so -_ext/ - -# Distribution / packaging -.Python -env/ -build/ -develop-eggs/ -dist/ -downloads/ -eggs/ -.eggs/ -lib/ -lib64/ -parts/ -sdist/ -var/ -wheels/ -*.egg-info/ -.installed.cfg -*.egg - -# PyInstaller -# Usually these files are written by a python script from a template -# before PyInstaller builds the exe, so as to inject date/other infos into it. -*.manifest -*.spec - -# Installer logs -pip-log.txt -pip-delete-this-directory.txt - -# Unit test / coverage reports -htmlcov/ -.tox/ -.coverage -.coverage.* -.cache -nosetests.xml -coverage.xml -*.cover -.hypothesis/ - -# Translations -*.mo -*.pot - -# Django stuff: -*.log -local_settings.py - -# Flask stuff: -instance/ -.webassets-cache - -# Scrapy stuff: -.scrapy - -# Sphinx documentation -docs/_build/ -docs/src/ - -# PyBuilder -target/ - -# Jupyter Notebook -.ipynb_checkpoints/ - -# pyenv -.python-version - -# celery beat schedule file -celerybeat-schedule - -# SageMath parsed files -*.sage.py - -# dotenv -.env - -# virtualenv -.venv -venv/ -ENV/ - -# Spyder project settings -.spyderproject -.spyproject - -# Rope project settings -.ropeproject - -# PyCharm project settings -.idea - -# OSX dir files -.DS_Store - -# mkdocs documentation -/site - -# mypy -.mypy_cache/ - -# Generated Files -test/assets/sinewave.wav -torchaudio/version.py -gen.yml - -# Examples -examples/interactive_asr/data/*.txt -examples/interactive_asr/data/*.model -examples/interactive_asr/data/*.pt diff --git a/.python3 b/.python3 new file mode 100644 index 0000000000..e69de29bb2 diff --git a/.travis.yml b/.travis.yml deleted file mode 100644 index 1fd00c3e96..0000000000 --- a/.travis.yml +++ /dev/null @@ -1,36 +0,0 @@ -# note dist: 'trusty' does not work here -dist: xenial - -language: python - -# cache miniconda installer and similar files -cache: - directories: - - /home/travis/download - -# This matrix tests that the code works on Python 3.5, 3.6, 3.7, passes -# lint and example tests. -matrix: - fast_finish: true - include: - - env: PYTHON_VERSION="3.5" - - env: PYTHON_VERSION="3.6" - - env: PYTHON_VERSION="3.7" - - env: PYTHON_VERSION="3.5" RUN_FLAKE8="true" SKIP_INSTALL="true" SKIP_TESTS="true" - - env: PYTHON_VERSION="3.5" RUN_EXAMPLE_TESTS="true" SKIP_TESTS="true" - allow_failures: - - env: PYTHON_VERSION="3.5" RUN_EXAMPLE_TESTS="true" SKIP_TESTS="true" - -addons: - apt: - packages: - sox - libsox-dev - libsox-fmt-all - portaudio19-dev - -notifications: - email: false - -install: source build_tools/travis/install.sh -script: bash build_tools/travis/test_script.sh From e2430778611a4ea26a1913e327525901953c5d11 Mon Sep 17 00:00:00 2001 From: Christian Puhrsch Date: Wed, 29 Apr 2020 00:29:57 -0400 Subject: [PATCH 03/73] Set up ShipIt fbshipit-source-id: 4fb853c391900d3070b936e5a3e4609eb78a780d From 0d99b9d0a4e8d994ddd881feebff4857e3206efd Mon Sep 17 00:00:00 2001 From: Christian Puhrsch Date: Tue, 28 Apr 2020 19:16:39 -0700 Subject: [PATCH 04/73] 20200428 pytorch/audio import Summary: [10:30:47: cpuhrsch@devvm3140 pytorch]$ ./fb_build/import_audio.sh Reviewed By: vincentqb Differential Revision: D21282421 fbshipit-source-id: 9bde1455ca6a19defbf33dbbfc5f0d49a8e4dc6a --- CODE_OF_CONDUCT.md | 76 ++ README.md | 2 +- build_tools/travis/install.sh | 1 + build_tools/travis/test_script.sh | 1 + docs/source/datasets.rst | 36 +- docs/source/functional.rst | 99 ++- docs/source/transforms.rst | 16 +- mypy.ini | 3 + packaging/build_conda.sh | 2 +- packaging/build_wheel.sh | 2 +- requirements.txt | 5 +- setup.py | 2 +- test/assets/vad-hello-mono-32000.wav | Bin 0 -> 275106 bytes test/assets/vad-hello-stereo-44100.wav | Bin 0 -> 937862 bytes test/common_utils.py | 23 +- test/test_batch_consistency.py | 156 ++-- test/test_compliance_kaldi.py | 25 +- test/test_dataloader.py | 29 +- test/test_datasets.py | 4 +- test/test_functional.py | 70 +- test/{test.py => test_io.py} | 0 test/test_kaldi_io.py | 8 +- test/test_librosa_compatibility.py | 43 +- ...filtering.py => test_sox_compatibility.py} | 321 ++++----- test/test_sox_effects.py | 36 +- test/test_torchscript_consistency.py | 671 +++++++++++------- test/test_transforms.py | 25 +- torchaudio/__init__.py | 184 +++-- torchaudio/_backend.py | 22 +- torchaudio/_soundfile_backend.py | 52 +- torchaudio/_sox_backend.py | 32 +- torchaudio/common_utils.py | 2 +- torchaudio/datasets/commonvoice.py | 96 ++- torchaudio/datasets/librispeech.py | 44 +- torchaudio/datasets/ljspeech.py | 23 +- torchaudio/datasets/speechcommands.py | 29 +- torchaudio/datasets/utils.py | 105 +-- torchaudio/datasets/vctk.py | 53 +- torchaudio/datasets/yesno.py | 37 +- torchaudio/functional.py | 582 +++++++++++++-- torchaudio/kaldi_io.py | 38 +- torchaudio/sox_effects.py | 9 +- torchaudio/transforms.py | 166 ++++- 43 files changed, 2145 insertions(+), 985 deletions(-) create mode 100644 CODE_OF_CONDUCT.md create mode 100644 mypy.ini create mode 100644 test/assets/vad-hello-mono-32000.wav create mode 100644 test/assets/vad-hello-stereo-44100.wav rename test/{test.py => test_io.py} (100%) rename test/{test_functional_filtering.py => test_sox_compatibility.py} (54%) diff --git a/CODE_OF_CONDUCT.md b/CODE_OF_CONDUCT.md new file mode 100644 index 0000000000..b91e23b17c --- /dev/null +++ b/CODE_OF_CONDUCT.md @@ -0,0 +1,76 @@ +# Code of Conduct + +## Our Pledge + +In the interest of fostering an open and welcoming environment, we as +contributors and maintainers pledge to make participation in our project and +our community a harassment-free experience for everyone, regardless of age, body +size, disability, ethnicity, sex characteristics, gender identity and expression, +level of experience, education, socio-economic status, nationality, personal +appearance, race, religion, or sexual identity and orientation. + +## Our Standards + +Examples of behavior that contributes to creating a positive environment +include: + +* Using welcoming and inclusive language +* Being respectful of differing viewpoints and experiences +* Gracefully accepting constructive criticism +* Focusing on what is best for the community +* Showing empathy towards other community members + +Examples of unacceptable behavior by participants include: + +* The use of sexualized language or imagery and unwelcome sexual attention or +advances +* Trolling, insulting/derogatory comments, and personal or political attacks +* Public or private harassment +* Publishing others' private information, such as a physical or electronic +address, without explicit permission +* Other conduct which could reasonably be considered inappropriate in a +professional setting + +## Our Responsibilities + +Project maintainers are responsible for clarifying the standards of acceptable +behavior and are expected to take appropriate and fair corrective action in +response to any instances of unacceptable behavior. + +Project maintainers have the right and responsibility to remove, edit, or +reject comments, commits, code, wiki edits, issues, and other contributions +that are not aligned to this Code of Conduct, or to ban temporarily or +permanently any contributor for other behaviors that they deem inappropriate, +threatening, offensive, or harmful. + +## Scope + +This Code of Conduct applies within all project spaces, and it also applies when +an individual is representing the project or its community in public spaces. +Examples of representing a project or community include using an official +project e-mail address, posting via an official social media account, or acting +as an appointed representative at an online or offline event. Representation of +a project may be further defined and clarified by project maintainers. + +## Enforcement + +Instances of abusive, harassing, or otherwise unacceptable behavior may be +reported by contacting the project team at . All +complaints will be reviewed and investigated and will result in a response that +is deemed necessary and appropriate to the circumstances. The project team is +obligated to maintain confidentiality with regard to the reporter of an incident. +Further details of specific enforcement policies may be posted separately. + +Project maintainers who do not follow or enforce the Code of Conduct in good +faith may face temporary or permanent repercussions as determined by other +members of the project's leadership. + +## Attribution + +This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4, +available at https://www.contributor-covenant.org/version/1/4/code-of-conduct.html + +[homepage]: https://www.contributor-covenant.org + +For answers to common questions about this code of conduct, see +https://www.contributor-covenant.org/faq diff --git a/README.md b/README.md index f36f19db36..816fd75f6c 100644 --- a/README.md +++ b/README.md @@ -70,7 +70,7 @@ build nightlies based on PyTorch nightlies by hand following the instructions in ``` pip install numpy -pip install torchaudio_nightly -f https://download.pytorch.org/whl/nightly/torch_nightly.html +pip install --pre torchaudio -f https://download.pytorch.org/whl/nightly/torch_nightly.html ``` To install the latest nightly via conda, run: diff --git a/build_tools/travis/install.sh b/build_tools/travis/install.sh index 61c564a5bf..3586d5bd08 100644 --- a/build_tools/travis/install.sh +++ b/build_tools/travis/install.sh @@ -48,6 +48,7 @@ popd source activate testenv # Install requirements via pip in our conda environment +conda install -y pytorch cpuonly -c pytorch-nightly pip install -r requirements.txt # Install the following only if running tests diff --git a/build_tools/travis/test_script.sh b/build_tools/travis/test_script.sh index 06d70956b8..e854a211b3 100755 --- a/build_tools/travis/test_script.sh +++ b/build_tools/travis/test_script.sh @@ -6,6 +6,7 @@ set -e python --version +python -c 'import torch;print("torch:", torch.__version__)' run_tests() { # find all the test files that match "test*.py" diff --git a/docs/source/datasets.rst b/docs/source/datasets.rst index eef25da616..27d4b20a34 100644 --- a/docs/source/datasets.rst +++ b/docs/source/datasets.rst @@ -25,15 +25,47 @@ All the datasets have almost similar API. They all have two common arguments: .. currentmodule:: torchaudio.datasets +COMMONVOICE +~~~~~~~~~~~ + +.. autoclass:: COMMONVOICE + :members: __getitem__ + :special-members: + + +LIBRISPEECH +~~~~~~~~~~~ + +.. autoclass:: LIBRISPEECH + :members: __getitem__ + :special-members: + + +LJSPEECH +~~~~~~~~ + +.. autoclass:: LJSPEECH + :members: __getitem__ + :special-members: + + +SPEECHCOMMANDS +~~~~~~~~~~~~~~ + +.. autoclass:: SPEECHCOMMANDS + :members: __getitem__ + :special-members: + + VCTK -~~~~~ +~~~~ .. autoclass:: VCTK :members: __getitem__ :special-members: YESNO -~~~~~~~~~~~~~ +~~~~~ .. autoclass:: YESNO :members: __getitem__ diff --git a/docs/source/functional.rst b/docs/source/functional.rst index a76bf4dc4c..d8f318ea18 100644 --- a/docs/source/functional.rst +++ b/docs/source/functional.rst @@ -2,113 +2,168 @@ :class: hidden-section torchaudio.functional -====================== +===================== .. currentmodule:: torchaudio.functional Functions to perform common audio operations. :hidden:`istft` -~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +~~~~~~~~~~~~~~~ .. autofunction:: istft :hidden:`spectrogram` -~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +~~~~~~~~~~~~~~~~~~~~~ .. autofunction:: spectrogram :hidden:`amplitude_to_DB` -~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +~~~~~~~~~~~~~~~~~~~~~~~~~ .. autofunction:: amplitude_to_DB :hidden:`create_fb_matrix` -~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +~~~~~~~~~~~~~~~~~~~~~~~~~~ .. autofunction:: create_fb_matrix :hidden:`create_dct` -~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +~~~~~~~~~~~~~~~~~~~~ .. autofunction:: create_dct :hidden:`mu_law_encoding` -~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +~~~~~~~~~~~~~~~~~~~~~~~~~ .. autofunction:: mu_law_encoding :hidden:`mu_law_decoding` -~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +~~~~~~~~~~~~~~~~~~~~~~~~~ .. autofunction:: mu_law_decoding :hidden:`complex_norm` -~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +~~~~~~~~~~~~~~~~~~~~~~ .. autofunction:: complex_norm :hidden:`angle` -~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +~~~~~~~~~~~~~~~ .. autofunction:: angle :hidden:`magphase` -~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +~~~~~~~~~~~~~~~~~~ .. autofunction:: magphase :hidden:`phase_vocoder` -~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +~~~~~~~~~~~~~~~~~~~~~~~ .. autofunction:: phase_vocoder :hidden:`lfilter` -~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +~~~~~~~~~~~~~~~~~ .. autofunction:: lfilter :hidden:`biquad` -~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +~~~~~~~~~~~~~~~~ .. autofunction:: biquad :hidden:`lowpass_biquad` -~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +~~~~~~~~~~~~~~~~~~~~~~~~ .. autofunction:: lowpass_biquad :hidden:`highpass_biquad` -~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +~~~~~~~~~~~~~~~~~~~~~~~~~ .. autofunction:: highpass_biquad :hidden:`allpass_biquad` -~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +~~~~~~~~~~~~~~~~~~~~~~~~ .. autofunction:: allpass_biquad :hidden:`equalizer_biquad` -~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +~~~~~~~~~~~~~~~~~~~~~~~~~~ .. autofunction:: equalizer_biquad -:hidden:`mask_along_axis` +:hidden:`bandpass_biquad` +~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +.. autofunction:: bandpass_biquad + +:hidden:`bandreject_biquad` +~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +.. autofunction:: bandreject_biquad + +:hidden:`band_biquad` +~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +.. autofunction:: band_biquad + +:hidden:`treble_biquad` ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +.. autofunction:: treble_biquad + +:hidden:`deemph_biquad` +~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +.. autofunction:: deemph_biquad + +:hidden:`riaa_biquad` +~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +.. autofunction:: riaa_biquad + +:hidden:`contrast` +~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +.. autofunction:: contrast + +:hidden:`dcshift` +~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +.. autofunction:: dcshift + +:hidden:`overdrive` +~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +.. autofunction:: overdrive + +:hidden:`mask_along_axis` +~~~~~~~~~~~~~~~~~~~~~~~~~ + .. autofunction:: mask_along_axis :hidden:`mask_along_axis_iid` -~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ .. autofunction:: mask_along_axis_iid :hidden:`compute_deltas` -~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +~~~~~~~~~~~~~~~~~~~~~~~~ .. autofunction:: compute_deltas :hidden:`detect_pitch_frequency` -~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ .. autofunction:: detect_pitch_frequency + +:hidden:`sliding_window_cmn` +~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +.. autofunction:: sliding_window_cmn + +:hidden:`vad` +~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +.. autofunction:: vad diff --git a/docs/source/transforms.rst b/docs/source/transforms.rst index aa50b33714..fc6a4d4a9f 100644 --- a/docs/source/transforms.rst +++ b/docs/source/transforms.rst @@ -19,7 +19,7 @@ Transforms are common audio transforms. They can be chained together using :clas :hidden:`GriffinLim` ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -.. autoclass:: GriffinLim +.. autoclass:: GriffinLim .. automethod:: forward @@ -128,3 +128,17 @@ Transforms are common audio transforms. They can be chained together using :clas .. autoclass:: Vol .. automethod:: forward + +:hidden:`SlidingWindowCmn` +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +.. autoclass:: SlidingWindowCmn + + .. automethod:: forward + +:hidden:`Vad` +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +.. autoclass:: Vad + + .. automethod:: forward diff --git a/mypy.ini b/mypy.ini new file mode 100644 index 0000000000..068f0918a3 --- /dev/null +++ b/mypy.ini @@ -0,0 +1,3 @@ +[mypy] +allow_redefinition = True +ignore_missing_imports = True diff --git a/packaging/build_conda.sh b/packaging/build_conda.sh index b75bbf8a13..3e011d312f 100755 --- a/packaging/build_conda.sh +++ b/packaging/build_conda.sh @@ -6,7 +6,7 @@ script_dir="$( cd "$( dirname "${BASH_SOURCE[0]}" )" >/dev/null 2>&1 && pwd )" export BUILD_TYPE="conda" export NO_CUDA_PACKAGE=1 -setup_env 0.5.0 +setup_env 0.6.0 export SOURCE_ROOT_DIR="$PWD" setup_conda_pytorch_constraint conda build $CONDA_CHANNEL_FLAGS --no-anaconda-upload --python "$PYTHON_VERSION" packaging/torchaudio diff --git a/packaging/build_wheel.sh b/packaging/build_wheel.sh index 1e4f927ef5..fc0742ece1 100755 --- a/packaging/build_wheel.sh +++ b/packaging/build_wheel.sh @@ -6,7 +6,7 @@ script_dir="$( cd "$( dirname "${BASH_SOURCE[0]}" )" >/dev/null 2>&1 && pwd )" export BUILD_TYPE="wheel" export NO_CUDA_PACKAGE=1 -setup_env 0.5.0 +setup_env 0.6.0 setup_wheel_python "$script_dir/build_from_source.sh" "$(pwd)" # Build static dependencies pip_install numpy future diff --git a/requirements.txt b/requirements.txt index c67dd4627a..316bd5c7fd 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,4 +1,4 @@ -torch>=1.2.0 +torch>=1.4.0 # Required for Windows because it's the only available backend SoundFile; sys_platform == 'win32' @@ -18,6 +18,3 @@ scipy # Unit tests with pytest pytest - -# Testing only Py3 compat -backports.tempfile diff --git a/setup.py b/setup.py index 8382c1114c..0128a2fe61 100644 --- a/setup.py +++ b/setup.py @@ -55,7 +55,7 @@ def check_env_flag(name, default=''): # Creating the version file cwd = os.path.dirname(os.path.abspath(__file__)) -version = '0.5.0a0' +version = '0.6.0a0' sha = 'Unknown' try: diff --git a/test/assets/vad-hello-mono-32000.wav b/test/assets/vad-hello-mono-32000.wav new file mode 100644 index 0000000000000000000000000000000000000000..1822c3196c5e1b744d07c20bfe65035b76c4db7a GIT binary patch literal 275106 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ë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 literal 0 HcmV?d00001 diff --git a/test/assets/vad-hello-stereo-44100.wav b/test/assets/vad-hello-stereo-44100.wav new file mode 100644 index 0000000000000000000000000000000000000000..bd130372e7a7e0e14f2cbbad144aaebfb52e297f GIT binary patch literal 937862 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 >wnL+hCp{S~~<@=?_x-ph=zaf^Fdb<8aR9 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

mD3;xa^0U+#m?53R(qjU^+OYr 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

O#Ks156 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

t+2>(v1jgwu?**SzP@v-yxZLj-r(m^Z4|ZH$(h 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

gn=dmp@zLdFY*ImOd%fI}f7!oTm_SEp$HI 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≻IX@_PO(op58Sh;{9!oASziw;vah! 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

-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 z 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 literal 0 HcmV?d00001 diff --git a/test/common_utils.py b/test/common_utils.py index 8c14fe25b6..d3ef58a51f 100644 --- a/test/common_utils.py +++ b/test/common_utils.py @@ -6,10 +6,15 @@ import torch import torchaudio -TEST_DIR_PATH = os.path.dirname(os.path.realpath(__file__)) +_TEST_DIR_PATH = os.path.dirname(os.path.realpath(__file__)) BACKENDS = torchaudio._backend._audio_backends +def get_asset_path(*paths): + """Return full path of a test asset""" + return os.path.join(_TEST_DIR_PATH, 'assets', *paths) + + def create_temp_assets_dir(): """ Creates a temporary directory and moves all files from test/assets there. @@ -17,7 +22,7 @@ def create_temp_assets_dir(): and object. """ tmp_dir = tempfile.TemporaryDirectory() - copytree(os.path.join(TEST_DIR_PATH, "assets"), + copytree(os.path.join(_TEST_DIR_PATH, "assets"), os.path.join(tmp_dir.name, "assets")) return tmp_dir.name, tmp_dir @@ -47,12 +52,6 @@ def random_float_tensor(seed, size, a=22695477, c=1, m=2 ** 32): return torch.tensor(arr).float().view(size) / m -def random_int_tensor(seed, size, low=0, high=2 ** 32, a=22695477, c=1, m=2 ** 32): - """ Same as random_float_tensor but integers between [low, high) - """ - return torch.floor(random_float_tensor(seed, size, a, c, m) * (high - low)) + low - - @contextmanager def AudioBackendScope(new_backend): previous_backend = torchaudio.get_audio_backend() @@ -65,18 +64,14 @@ def AudioBackendScope(new_backend): def filter_backends_with_mp3(backends): # Filter out backends that do not support mp3 - - test_dirpath, _ = create_temp_assets_dir() - test_filepath = os.path.join( - test_dirpath, "assets", "steam-train-whistle-daniel_simon.mp3" - ) + test_filepath = get_asset_path('steam-train-whistle-daniel_simon.mp3') def supports_mp3(backend): try: with AudioBackendScope(backend): torchaudio.load(test_filepath) return True - except RuntimeError: + except (RuntimeError, ImportError): return False return [backend for backend in backends if supports_mp3(backend)] diff --git a/test/test_batch_consistency.py b/test/test_batch_consistency.py index 69c398bfb6..675a21e029 100644 --- a/test/test_batch_consistency.py +++ b/test/test_batch_consistency.py @@ -1,5 +1,4 @@ """Test numerical consistency among single input and batched input.""" -import os import unittest import torch @@ -7,67 +6,25 @@ import torchaudio.functional as F import common_utils -from common_utils import AudioBackendScope, BACKENDS -def _test_batch_shape(functional, tensor, *args, **kwargs): - - kwargs_compare = {} - if 'atol' in kwargs: - atol = kwargs['atol'] - del kwargs['atol'] - kwargs_compare['atol'] = atol - - if 'rtol' in kwargs: - rtol = kwargs['rtol'] - del kwargs['rtol'] - kwargs_compare['rtol'] = rtol - - # Single then transform then batch - +def _test_batch_consistency(functional, tensor, *args, batch_size=1, atol=1e-8, rtol=1e-5, **kwargs): + # run then batch the result torch.random.manual_seed(42) expected = functional(tensor.clone(), *args, **kwargs) - expected = expected.unsqueeze(0).unsqueeze(0) - - # 1-Batch then transform - tensors = tensor.unsqueeze(0).unsqueeze(0) + expected = expected.repeat([batch_size] + [1] * expected.dim()) + # batch the input and run torch.random.manual_seed(42) - computed = functional(tensors.clone(), *args, **kwargs) - - assert expected.shape == computed.shape, (expected.shape, computed.shape) - assert torch.allclose(expected, computed, **kwargs_compare) - - return tensors, expected - - -def _test_batch(functional, tensor, *args, **kwargs): - tensors, expected = _test_batch_shape(functional, tensor, *args, **kwargs) - - kwargs_compare = {} - if 'atol' in kwargs: - atol = kwargs['atol'] - del kwargs['atol'] - kwargs_compare['atol'] = atol - - if 'rtol' in kwargs: - rtol = kwargs['rtol'] - del kwargs['rtol'] - kwargs_compare['rtol'] = rtol - - # 3-Batch then transform + pattern = [batch_size] + [1] * tensor.dim() + computed = functional(tensor.repeat(pattern), *args, **kwargs) - ind = [3] + [1] * (int(tensors.dim()) - 1) - tensors = tensor.repeat(*ind) + torch.testing.assert_allclose(computed, expected, rtol=rtol, atol=atol) - ind = [3] + [1] * (int(expected.dim()) - 1) - expected = expected.repeat(*ind) - torch.random.manual_seed(42) - computed = functional(tensors.clone(), *args, **kwargs) - - assert expected.shape == computed.shape, (expected.shape, computed.shape) - assert torch.allclose(expected, computed, **kwargs_compare) +def _test_batch(functional, tensor, *args, atol=1e-8, rtol=1e-5, **kwargs): + _test_batch_consistency(functional, tensor, *args, batch_size=1, atol=atol, rtol=rtol, **kwargs) + _test_batch_consistency(functional, tensor, *args, batch_size=3, atol=atol, rtol=rtol, **kwargs) class TestFunctional(unittest.TestCase): @@ -95,7 +52,7 @@ def test_detect_pitch_frequency(self): '440Hz_44100Hz_16bit_05sec.wav', # 1ch ] for filename in filenames: - filepath = os.path.join(common_utils.TEST_DIR_PATH, 'assets', filename) + filepath = common_utils.get_asset_path(filename) waveform, sample_rate = torchaudio.load(filepath) _test_batch(F.detect_pitch_frequency, waveform, sample_rate) @@ -107,6 +64,30 @@ def test_istft(self): ]) _test_batch(F.istft, stft, n_fft=4, length=4) + def test_contrast(self): + waveform = torch.rand(2, 100) - 0.5 + _test_batch(F.contrast, waveform, enhancement_amount=80.) + + def test_dcshift(self): + waveform = torch.rand(2, 100) - 0.5 + _test_batch(F.dcshift, waveform, shift=0.5, limiter_gain=0.05) + + def test_overdrive(self): + waveform = torch.rand(2, 100) - 0.5 + _test_batch(F.overdrive, waveform, gain=45, colour=30) + + def test_sliding_window_cmn(self): + waveform = torch.randn(2, 1024) - 0.5 + _test_batch(F.sliding_window_cmn, waveform, center=True, norm_vars=True) + _test_batch(F.sliding_window_cmn, waveform, center=True, norm_vars=False) + _test_batch(F.sliding_window_cmn, waveform, center=False, norm_vars=True) + _test_batch(F.sliding_window_cmn, waveform, center=False, norm_vars=False) + + def test_vad(self): + filepath = common_utils.get_asset_path("vad-hello-mono-32000.wav") + waveform, sample_rate = torchaudio.load(filepath) + _test_batch(F.vad, waveform, sample_rate=sample_rate) + class TestTransforms(unittest.TestCase): """Test suite for classes defined in `transforms` module""" @@ -119,8 +100,7 @@ def test_batch_AmplitudeToDB(self): # Batch then transform computed = torchaudio.transforms.AmplitudeToDB()(spec.repeat(3, 1, 1)) - assert computed.shape == expected.shape, (computed.shape, expected.shape) - assert torch.allclose(computed, expected) + torch.testing.assert_allclose(computed, expected) def test_batch_Resample(self): waveform = torch.randn(2, 2786) @@ -131,8 +111,7 @@ def test_batch_Resample(self): # Batch then transform computed = torchaudio.transforms.Resample()(waveform.repeat(3, 1, 1)) - assert computed.shape == expected.shape, (computed.shape, expected.shape) - assert torch.allclose(computed, expected) + torch.testing.assert_allclose(computed, expected) def test_batch_MelScale(self): specgram = torch.randn(2, 31, 2786) @@ -144,8 +123,7 @@ def test_batch_MelScale(self): computed = torchaudio.transforms.MelScale()(specgram.repeat(3, 1, 1, 1)) # shape = (3, 2, 201, 1394) - assert computed.shape == expected.shape, (computed.shape, expected.shape) - assert torch.allclose(computed, expected) + torch.testing.assert_allclose(computed, expected) def test_batch_InverseMelScale(self): n_mels = 32 @@ -159,11 +137,10 @@ def test_batch_InverseMelScale(self): computed = torchaudio.transforms.InverseMelScale(n_stft, n_mels)(mel_spec.repeat(3, 1, 1, 1)) # shape = (3, 2, n_mels, 32) - assert computed.shape == expected.shape, (computed.shape, expected.shape) # Because InverseMelScale runs SGD on randomly initialized values so they do not yield # exactly same result. For this reason, tolerance is very relaxed here. - assert torch.allclose(computed, expected, atol=1.0) + torch.testing.assert_allclose(computed, expected, atol=1.0, rtol=1e-5) def test_batch_compute_deltas(self): specgram = torch.randn(2, 31, 2786) @@ -175,12 +152,10 @@ def test_batch_compute_deltas(self): computed = torchaudio.transforms.ComputeDeltas()(specgram.repeat(3, 1, 1, 1)) # shape = (3, 2, 201, 1394) - assert computed.shape == expected.shape, (computed.shape, expected.shape) - assert torch.allclose(computed, expected) + torch.testing.assert_allclose(computed, expected) def test_batch_mulaw(self): - test_filepath = os.path.join( - common_utils.TEST_DIR_PATH, 'assets', 'steam-train-whistle-daniel_simon.wav') + test_filepath = common_utils.get_asset_path('steam-train-whistle-daniel_simon.wav') waveform, _ = torchaudio.load(test_filepath) # (2, 278756), 44100 # Single then transform then batch @@ -192,8 +167,7 @@ def test_batch_mulaw(self): computed = torchaudio.transforms.MuLawEncoding()(waveform_batched) # shape = (3, 2, 201, 1394) - assert computed.shape == expected.shape, (computed.shape, expected.shape) - assert torch.allclose(computed, expected) + torch.testing.assert_allclose(computed, expected) # Single then transform then batch waveform_decoded = torchaudio.transforms.MuLawDecoding()(waveform_encoded) @@ -203,12 +177,10 @@ def test_batch_mulaw(self): computed = torchaudio.transforms.MuLawDecoding()(computed) # shape = (3, 2, 201, 1394) - assert computed.shape == expected.shape, (computed.shape, expected.shape) - assert torch.allclose(computed, expected) + torch.testing.assert_allclose(computed, expected) def test_batch_spectrogram(self): - test_filepath = os.path.join( - common_utils.TEST_DIR_PATH, 'assets', 'steam-train-whistle-daniel_simon.wav') + test_filepath = common_utils.get_asset_path('steam-train-whistle-daniel_simon.wav') waveform, _ = torchaudio.load(test_filepath) # (2, 278756), 44100 # Single then transform then batch @@ -216,13 +188,10 @@ def test_batch_spectrogram(self): # Batch then transform computed = torchaudio.transforms.Spectrogram()(waveform.repeat(3, 1, 1)) - - assert computed.shape == expected.shape, (computed.shape, expected.shape) - assert torch.allclose(computed, expected) + torch.testing.assert_allclose(computed, expected) def test_batch_melspectrogram(self): - test_filepath = os.path.join( - common_utils.TEST_DIR_PATH, 'assets', 'steam-train-whistle-daniel_simon.wav') + test_filepath = common_utils.get_asset_path('steam-train-whistle-daniel_simon.wav') waveform, _ = torchaudio.load(test_filepath) # (2, 278756), 44100 # Single then transform then batch @@ -230,15 +199,10 @@ def test_batch_melspectrogram(self): # Batch then transform computed = torchaudio.transforms.MelSpectrogram()(waveform.repeat(3, 1, 1)) + torch.testing.assert_allclose(computed, expected) - assert computed.shape == expected.shape, (computed.shape, expected.shape) - assert torch.allclose(computed, expected) - - @unittest.skipIf("sox" not in BACKENDS, "sox not available") - @AudioBackendScope("sox") def test_batch_mfcc(self): - test_filepath = os.path.join( - common_utils.TEST_DIR_PATH, 'assets', 'steam-train-whistle-daniel_simon.mp3') + test_filepath = common_utils.get_asset_path('steam-train-whistle-daniel_simon.wav') waveform, _ = torchaudio.load(test_filepath) # Single then transform then batch @@ -246,13 +210,10 @@ def test_batch_mfcc(self): # Batch then transform computed = torchaudio.transforms.MFCC()(waveform.repeat(3, 1, 1)) - - assert computed.shape == expected.shape, (computed.shape, expected.shape) - assert torch.allclose(computed, expected, atol=1e-5) + torch.testing.assert_allclose(computed, expected, atol=1e-5, rtol=1e-5) def test_batch_TimeStretch(self): - test_filepath = os.path.join( - common_utils.TEST_DIR_PATH, 'assets', 'steam-train-whistle-daniel_simon.wav') + test_filepath = common_utils.get_asset_path('steam-train-whistle-daniel_simon.wav') waveform, _ = torchaudio.load(test_filepath) # (2, 278756), 44100 kwargs = { @@ -283,12 +244,10 @@ def test_batch_TimeStretch(self): hop_length=512, )(complex_specgrams.repeat(3, 1, 1, 1, 1)) - assert computed.shape == expected.shape, (computed.shape, expected.shape) - assert torch.allclose(computed, expected, atol=1e-5) + torch.testing.assert_allclose(computed, expected, atol=1e-5, rtol=1e-5) def test_batch_Fade(self): - test_filepath = os.path.join( - common_utils.TEST_DIR_PATH, 'assets', 'steam-train-whistle-daniel_simon.wav') + test_filepath = common_utils.get_asset_path('steam-train-whistle-daniel_simon.wav') waveform, _ = torchaudio.load(test_filepath) # (2, 278756), 44100 fade_in_len = 3000 fade_out_len = 3000 @@ -298,13 +257,10 @@ def test_batch_Fade(self): # Batch then transform computed = torchaudio.transforms.Fade(fade_in_len, fade_out_len)(waveform.repeat(3, 1, 1)) - - assert computed.shape == expected.shape, (computed.shape, expected.shape) - assert torch.allclose(computed, expected) + torch.testing.assert_allclose(computed, expected) def test_batch_Vol(self): - test_filepath = os.path.join( - common_utils.TEST_DIR_PATH, 'assets', 'steam-train-whistle-daniel_simon.wav') + test_filepath = common_utils.get_asset_path('steam-train-whistle-daniel_simon.wav') waveform, _ = torchaudio.load(test_filepath) # (2, 278756), 44100 # Single then transform then batch @@ -312,9 +268,7 @@ def test_batch_Vol(self): # Batch then transform computed = torchaudio.transforms.Vol(gain=1.1)(waveform.repeat(3, 1, 1)) - - assert computed.shape == expected.shape, (computed.shape, expected.shape) - assert torch.allclose(computed, expected) + torch.testing.assert_allclose(computed, expected) if __name__ == '__main__': diff --git a/test/test_compliance_kaldi.py b/test/test_compliance_kaldi.py index 83751e3e0e..6951ccf59b 100644 --- a/test/test_compliance_kaldi.py +++ b/test/test_compliance_kaldi.py @@ -5,7 +5,9 @@ import torchaudio import torchaudio.compliance.kaldi as kaldi import unittest -from common_utils import AudioBackendScope, BACKENDS, create_temp_assets_dir + +import common_utils +from common_utils import AudioBackendScope, BACKENDS def extract_window(window, wave, f, frame_length, frame_shift, snip_edges): @@ -45,10 +47,9 @@ def first_sample_of_frame(frame, window_size, window_shift, snip_edges): class Test_Kaldi(unittest.TestCase): - test_dirpath, test_dir = create_temp_assets_dir() - test_filepath = os.path.join(test_dirpath, 'assets', 'kaldi_file.wav') - test_8000_filepath = os.path.join(test_dirpath, 'assets', 'kaldi_file_8000.wav') - kaldi_output_dir = os.path.join(test_dirpath, 'assets', 'kaldi') + test_filepath = common_utils.get_asset_path('kaldi_file.wav') + test_8000_filepath = common_utils.get_asset_path('kaldi_file_8000.wav') + kaldi_output_dir = common_utils.get_asset_path('kaldi') test_filepaths = {prefix: [] for prefix in compliance.utils.TEST_PREFIX} # separating test files by their types (e.g 'spec', 'fbank', etc.) @@ -77,7 +78,7 @@ def _test_get_strided_helper(self, num_samples, window_size, window_shift, snip_ for r in range(m): extract_window(window, waveform, r, window_size, window_shift, snip_edges) - self.assertTrue(torch.allclose(window, output)) + torch.testing.assert_allclose(window, output) def test_get_strided(self): # generate any combination where 0 < window_size <= num_samples and @@ -90,8 +91,7 @@ def test_get_strided(self): def _create_data_set(self): # used to generate the dataset to test on. this is not used in testing (offline procedure) - test_dirpath = os.path.dirname(os.path.dirname(os.path.realpath(__file__))) - test_filepath = os.path.join(test_dirpath, 'assets', 'kaldi_file.wav') + test_filepath = common_utils.get_asset_path('kaldi_file.wav') sr = 16000 x = torch.arange(0, 20).float() # between [-6,6] @@ -104,7 +104,7 @@ def _create_data_set(self): sound, sample_rate = torchaudio.load(test_filepath, normalization=False) print(y >> 16) self.assertTrue(sample_rate == sr) - self.assertTrue(torch.allclose(y, sound)) + torch.testing.assert_allclose(y, sound) def _print_diagnostic(self, output, expect_output): # given an output and expected output, it will print the absolute/relative errors (max and mean squared) @@ -156,8 +156,7 @@ def _compliance_test_helper(self, sound_filepath, filepath_key, expected_num_fil output = get_output_fn(sound, args) self._print_diagnostic(output, kaldi_output) - self.assertTrue(output.shape, kaldi_output.shape) - self.assertTrue(torch.allclose(output, kaldi_output, atol=atol, rtol=rtol)) + torch.testing.assert_allclose(output, kaldi_output, atol=atol, rtol=rtol) @unittest.skipIf("sox" not in BACKENDS, "sox not available") @AudioBackendScope("sox") @@ -299,7 +298,7 @@ def _test_resample_waveform_accuracy(self, up_scale_factor=None, down_scale_fact ground_truth = ground_truth[..., n_to_trim:-n_to_trim] estimate = estimate[..., n_to_trim:-n_to_trim] - self.assertTrue(torch.allclose(ground_truth, estimate, atol=atol, rtol=rtol)) + torch.testing.assert_allclose(estimate, ground_truth, atol=atol, rtol=rtol) def test_resample_waveform_downsample_accuracy(self): for i in range(1, 20): @@ -324,7 +323,7 @@ def test_resample_waveform_multi_channel(self): for i in range(num_channels): single_channel = sound * (i + 1) * 1.5 single_channel_sampled = kaldi.resample_waveform(single_channel, sample_rate, sample_rate // 2) - self.assertTrue(torch.allclose(multi_sound_sampled[i, :], single_channel_sampled, rtol=1e-4)) + torch.testing.assert_allclose(multi_sound_sampled[i, :], single_channel_sampled[0], rtol=1e-4, atol=1e-8) if __name__ == '__main__': diff --git a/test/test_dataloader.py b/test/test_dataloader.py index 10f861c8b8..602491ee21 100644 --- a/test/test_dataloader.py +++ b/test/test_dataloader.py @@ -1,23 +1,17 @@ import unittest -import torch -import torch.nn as nn -from torch.utils.data import Dataset, DataLoader -import torchaudio -import math -import os -from common_utils import AudioBackendScope, BACKENDS, create_temp_assets_dir +import torchaudio +from torch.utils.data import Dataset, DataLoader -@unittest.skipIf("sox" not in BACKENDS, "sox not available") -class TORCHAUDIODS(Dataset): +import common_utils +from common_utils import AudioBackendScope, BACKENDS - test_dirpath, test_dir = create_temp_assets_dir() +class TORCHAUDIODS(Dataset): def __init__(self): - self.asset_dirpath = os.path.join(self.test_dirpath, "assets") sound_files = ["sinewave.wav", "steam-train-whistle-daniel_simon.mp3"] - self.data = [os.path.join(self.asset_dirpath, fn) for fn in sound_files] - self.si, self.ei = torchaudio.info(os.path.join(self.asset_dirpath, "sinewave.wav")) + self.data = [common_utils.get_asset_path(fn) for fn in sound_files] + self.si, self.ei = torchaudio.info(common_utils.get_asset_path("sinewave.wav")) self.si.precision = 16 self.E = torchaudio.sox_effects.SoxEffectsChain() self.E.append_effect_to_chain("rate", [self.si.rate]) # resample to 16000hz @@ -36,14 +30,6 @@ def __len__(self): @unittest.skipIf("sox" not in BACKENDS, "sox not available") class Test_DataLoader(unittest.TestCase): - @classmethod - def setUpClass(cls): - torchaudio.initialize_sox() - - @classmethod - def tearDownClass(cls): - torchaudio.shutdown_sox() - def test_1(self): expected_size = (2, 1, 16000) ds = TORCHAUDIODS() @@ -51,6 +37,7 @@ def test_1(self): for x in dl: self.assertTrue(x.size() == expected_size) + if __name__ == '__main__': with AudioBackendScope("sox"): unittest.main() diff --git a/test/test_datasets.py b/test/test_datasets.py index 4aa35b2063..e42e21e999 100644 --- a/test/test_datasets.py +++ b/test/test_datasets.py @@ -1,4 +1,3 @@ -import os import unittest from torchaudio.datasets.commonvoice import COMMONVOICE @@ -13,8 +12,7 @@ class TestDatasets(unittest.TestCase): - test_dirpath, test_dir = common_utils.create_temp_assets_dir() - path = os.path.join(test_dirpath, "assets") + path = common_utils.get_asset_path() def test_yesno(self): data = YESNO(self.path) diff --git a/test/test_functional.py b/test/test_functional.py index f779d8988d..a126bd9581 100644 --- a/test/test_functional.py +++ b/test/test_functional.py @@ -1,5 +1,4 @@ import math -import os import unittest import torch @@ -10,14 +9,49 @@ import common_utils +class _LfilterMixin: + device = None + dtype = None + + def test_simple(self): + """ + Create a very basic signal, + Then make a simple 4th order delay + The output should be same as the input but shifted + """ + + torch.random.manual_seed(42) + waveform = torch.rand(2, 44100 * 1, dtype=self.dtype, device=self.device) + b_coeffs = torch.tensor([0, 0, 0, 1], dtype=self.dtype, device=self.device) + a_coeffs = torch.tensor([1, 0, 0, 0], dtype=self.dtype, device=self.device) + output_waveform = F.lfilter(waveform, a_coeffs, b_coeffs) + + torch.testing.assert_allclose(output_waveform[:, 3:], waveform[:, 0:-3], atol=1e-5, rtol=1e-5) + + +class TestLfilterFloat32CPU(_LfilterMixin, unittest.TestCase): + device = torch.device('cpu') + dtype = torch.float32 + + +class TestLfilterFloat64CPU(_LfilterMixin, unittest.TestCase): + device = torch.device('cpu') + dtype = torch.float64 + + +@unittest.skipIf(not torch.cuda.is_available(), "CUDA not available") +class TestLfilterFloat32CUDA(_LfilterMixin, unittest.TestCase): + device = torch.device('cuda') + dtype = torch.float32 + + class TestComputeDeltas(unittest.TestCase): """Test suite for correctness of compute_deltas""" def test_one_channel(self): specgram = torch.tensor([[[1.0, 2.0, 3.0, 4.0]]]) expected = torch.tensor([[[0.5, 1.0, 1.0, 0.5]]]) computed = F.compute_deltas(specgram, win_length=3) - assert computed.shape == expected.shape, (computed.shape, expected.shape) - assert torch.allclose(computed, expected) + torch.testing.assert_allclose(computed, expected) def test_two_channels(self): specgram = torch.tensor([[[1.0, 2.0, 3.0, 4.0], @@ -25,16 +59,13 @@ def test_two_channels(self): expected = torch.tensor([[[0.5, 1.0, 1.0, 0.5], [0.5, 1.0, 1.0, 0.5]]]) computed = F.compute_deltas(specgram, win_length=3) - assert computed.shape == expected.shape, (computed.shape, expected.shape) - assert torch.allclose(computed, expected) + torch.testing.assert_allclose(computed, expected) def _compare_estimate(sound, estimate, atol=1e-6, rtol=1e-8): # trim sound for case when constructed signal is shorter than original sound = sound[..., :estimate.size(-1)] - - assert sound.shape == estimate.shape, (sound.shape, estimate.shape) - assert torch.allclose(sound, estimate, atol=atol, rtol=rtol) + torch.testing.assert_allclose(estimate, sound, atol=atol, rtol=rtol) def _test_istft_is_inverse_of_stft(kwargs): @@ -269,10 +300,8 @@ def test_linearity_of_istft4(self): class TestDetectPitchFrequency(unittest.TestCase): def test_pitch(self): - test_filepath_100 = os.path.join( - common_utils.TEST_DIR_PATH, 'assets', "100Hz_44100Hz_16bit_05sec.wav") - test_filepath_440 = os.path.join( - common_utils.TEST_DIR_PATH, 'assets', "440Hz_44100Hz_16bit_05sec.wav") + test_filepath_100 = common_utils.get_asset_path("100Hz_44100Hz_16bit_05sec.wav") + test_filepath_440 = common_utils.get_asset_path("440Hz_44100Hz_16bit_05sec.wav") # Files from https://www.mediacollege.com/audio/tone/download/ tests = [ @@ -308,13 +337,13 @@ def test_DB_to_amplitude(self): db = F.amplitude_to_DB(torch.abs(x), multiplier, amin, db_multiplier, top_db=None) x2 = F.DB_to_amplitude(db, ref, power) - self.assertTrue(torch.allclose(torch.abs(x), x2, atol=5e-5)) + torch.testing.assert_allclose(x2, torch.abs(x), atol=5e-5, rtol=1e-5) # Spectrogram amplitude -> DB -> amplitude db = F.amplitude_to_DB(spec, multiplier, amin, db_multiplier, top_db=None) x2 = F.DB_to_amplitude(db, ref, power) - self.assertTrue(torch.allclose(spec, x2, atol=5e-5)) + torch.testing.assert_allclose(x2, spec, atol=5e-5, rtol=1e-5) # Waveform power -> DB -> power multiplier = 10. @@ -323,13 +352,13 @@ def test_DB_to_amplitude(self): db = F.amplitude_to_DB(x, multiplier, amin, db_multiplier, top_db=None) x2 = F.DB_to_amplitude(db, ref, power) - self.assertTrue(torch.allclose(torch.abs(x), x2, atol=5e-5)) + torch.testing.assert_allclose(x2, torch.abs(x), atol=5e-5, rtol=1e-5) # Spectrogram power -> DB -> power db = F.amplitude_to_DB(spec, multiplier, amin, db_multiplier, top_db=None) x2 = F.DB_to_amplitude(db, ref, power) - self.assertTrue(torch.allclose(spec, x2, atol=5e-5)) + torch.testing.assert_allclose(x2, spec, atol=5e-5, rtol=1e-5) @pytest.mark.parametrize('complex_tensor', [ @@ -341,7 +370,7 @@ def test_complex_norm(complex_tensor, power): expected_norm_tensor = complex_tensor.pow(2).sum(-1).pow(power / 2) norm_tensor = F.complex_norm(complex_tensor, power) - assert torch.allclose(expected_norm_tensor, norm_tensor, atol=1e-5) + torch.testing.assert_allclose(norm_tensor, expected_norm_tensor, atol=1e-5, rtol=1e-5) @pytest.mark.parametrize('specgram', [ @@ -365,13 +394,12 @@ def test_mask_along_axis(specgram, mask_param, mask_value, axis): assert num_masked_columns < mask_param -@pytest.mark.parametrize('specgrams', [ - torch.randn(4, 2, 1025, 400), -]) @pytest.mark.parametrize('mask_param', [100]) @pytest.mark.parametrize('mask_value', [0., 30.]) @pytest.mark.parametrize('axis', [2, 3]) -def test_mask_along_axis_iid(specgrams, mask_param, mask_value, axis): +def test_mask_along_axis_iid(mask_param, mask_value, axis): + torch.random.manual_seed(42) + specgrams = torch.randn(4, 2, 1025, 400) mask_specgrams = F.mask_along_axis_iid(specgrams, mask_param, mask_value, axis) diff --git a/test/test.py b/test/test_io.py similarity index 100% rename from test/test.py rename to test/test_io.py diff --git a/test/test_kaldi_io.py b/test/test_kaldi_io.py index f4ff557e56..bc9903a3ef 100644 --- a/test/test_kaldi_io.py +++ b/test/test_kaldi_io.py @@ -1,21 +1,21 @@ -import os +import unittest + import torch import torchaudio.kaldi_io as kio -import unittest + import common_utils class Test_KaldiIO(unittest.TestCase): data1 = [[1, 2, 3], [11, 12, 13], [21, 22, 23]] data2 = [[31, 32, 33], [41, 42, 43], [51, 52, 53]] - test_dirpath, test_dir = common_utils.create_temp_assets_dir() def _test_helper(self, file_name, expected_data, fn, expected_dtype): """ Takes a file_name to the input data and a function fn to extract the data. It compares the extracted data to the expected_data. The expected_dtype will be used to check that the extracted data is of the right type. """ - test_filepath = os.path.join(self.test_dirpath, "assets", file_name) + test_filepath = common_utils.get_asset_path(file_name) expected_output = {'key' + str(idx + 1): torch.tensor(val, dtype=expected_dtype) for idx, val in enumerate(expected_data)} diff --git a/test/test_librosa_compatibility.py b/test/test_librosa_compatibility.py index 36bdb7a195..460f379ce9 100644 --- a/test/test_librosa_compatibility.py +++ b/test/test_librosa_compatibility.py @@ -51,7 +51,7 @@ def test_griffinlim(self): momentum=momentum, init=init, length=length) lr_out = torch.from_numpy(lr_out).unsqueeze(0) - assert torch.allclose(ta_out, lr_out, atol=5e-5) + torch.testing.assert_allclose(ta_out, lr_out, atol=5e-5, rtol=1e-5) def _test_create_fb(self, n_mels=40, sample_rate=22050, n_fft=2048, fmin=0.0, fmax=8000.0): librosa_fb = librosa.filters.mel(sr=sample_rate, @@ -68,7 +68,8 @@ def _test_create_fb(self, n_mels=40, sample_rate=22050, n_fft=2048, fmin=0.0, fm n_freqs=(n_fft // 2 + 1)) for i_mel_bank in range(n_mels): - assert torch.allclose(fb[:, i_mel_bank], torch.tensor(librosa_fb[i_mel_bank]), atol=1e-4) + torch.testing.assert_allclose(fb[:, i_mel_bank], torch.tensor(librosa_fb[i_mel_bank]), + atol=1e-4, rtol=1e-5) def test_create_fb(self): self._test_create_fb() @@ -91,18 +92,18 @@ def test_amplitude_to_DB(self): ta_out = F.amplitude_to_DB(spec, multiplier, amin, db_multiplier, top_db) lr_out = librosa.core.power_to_db(spec.numpy()) - lr_out = torch.from_numpy(lr_out).unsqueeze(0) + lr_out = torch.from_numpy(lr_out) - assert torch.allclose(ta_out, lr_out, atol=5e-5) + torch.testing.assert_allclose(ta_out, lr_out, atol=5e-5, rtol=1e-5) # Amplitude to DB multiplier = 20.0 ta_out = F.amplitude_to_DB(spec, multiplier, amin, db_multiplier, top_db) lr_out = librosa.core.amplitude_to_db(spec.numpy()) - lr_out = torch.from_numpy(lr_out).unsqueeze(0) + lr_out = torch.from_numpy(lr_out) - assert torch.allclose(ta_out, lr_out, atol=5e-5) + torch.testing.assert_allclose(ta_out, lr_out, atol=5e-5, rtol=1e-5) @pytest.mark.parametrize('complex_specgrams', [ @@ -148,7 +149,7 @@ def test_phase_vocoder(complex_specgrams, rate, hop_length): def _load_audio_asset(*asset_paths, **kwargs): - file_path = os.path.join(common_utils.TEST_DIR_PATH, 'assets', *asset_paths) + file_path = common_utils.get_asset_path(*asset_paths) sound, sample_rate = torchaudio.load(file_path, **kwargs) return sound, sample_rate @@ -164,7 +165,7 @@ def _test_compatibilities(n_fft, hop_length, power, n_mels, n_mfcc, sample_rate) y=sound_librosa, n_fft=n_fft, hop_length=hop_length, power=power) out_torch = spect_transform(sound).squeeze().cpu() - assert torch.allclose(out_torch, torch.from_numpy(out_librosa), atol=1e-5) + torch.testing.assert_allclose(out_torch, torch.from_numpy(out_librosa), atol=1e-5, rtol=1e-5) # test mel spectrogram melspect_transform = torchaudio.transforms.MelSpectrogram( @@ -175,25 +176,25 @@ def _test_compatibilities(n_fft, hop_length, power, n_mels, n_mfcc, sample_rate) hop_length=hop_length, n_mels=n_mels, htk=True, norm=None) librosa_mel_tensor = torch.from_numpy(librosa_mel) torch_mel = melspect_transform(sound).squeeze().cpu() - assert torch.allclose( - torch_mel.type(librosa_mel_tensor.dtype), librosa_mel_tensor, atol=5e-3) + torch.testing.assert_allclose( + torch_mel.type(librosa_mel_tensor.dtype), librosa_mel_tensor, atol=5e-3, rtol=1e-5) # test s2db power_to_db_transform = torchaudio.transforms.AmplitudeToDB('power', 80.) power_to_db_torch = power_to_db_transform(spect_transform(sound)).squeeze().cpu() power_to_db_librosa = librosa.core.spectrum.power_to_db(out_librosa) - assert torch.allclose(power_to_db_torch, torch.from_numpy(power_to_db_librosa), atol=5e-3) + torch.testing.assert_allclose(power_to_db_torch, torch.from_numpy(power_to_db_librosa), atol=5e-3, rtol=1e-5) mag_to_db_transform = torchaudio.transforms.AmplitudeToDB('magnitude', 80.) mag_to_db_torch = mag_to_db_transform(torch.abs(sound)).squeeze().cpu() mag_to_db_librosa = librosa.core.spectrum.amplitude_to_db(sound_librosa) - assert torch.allclose(mag_to_db_torch, torch.from_numpy(mag_to_db_librosa), atol=5e-3) + torch.testing.assert_allclose(mag_to_db_torch, torch.from_numpy(mag_to_db_librosa), atol=5e-3, rtol=1e-5) power_to_db_torch = power_to_db_transform(melspect_transform(sound)).squeeze().cpu() db_librosa = librosa.core.spectrum.power_to_db(librosa_mel) db_librosa_tensor = torch.from_numpy(db_librosa) - assert torch.allclose( - power_to_db_torch.type(db_librosa_tensor.dtype), db_librosa_tensor, atol=5e-3) + torch.testing.assert_allclose( + power_to_db_torch.type(db_librosa_tensor.dtype), db_librosa_tensor, atol=5e-3, rtol=1e-5) # test MFCC melkwargs = {'hop_length': hop_length, 'n_fft': n_fft} @@ -214,8 +215,8 @@ def _test_compatibilities(n_fft, hop_length, power, n_mels, n_mfcc, sample_rate) librosa_mfcc_tensor = torch.from_numpy(librosa_mfcc) torch_mfcc = mfcc_transform(sound).squeeze().cpu() - assert torch.allclose( - torch_mfcc.type(librosa_mfcc_tensor.dtype), librosa_mfcc_tensor, atol=5e-3) + torch.testing.assert_allclose( + torch_mfcc.type(librosa_mfcc_tensor.dtype), librosa_mfcc_tensor, atol=5e-3, rtol=1e-5) class TestTransforms(_LibrosaMixin, unittest.TestCase): @@ -242,10 +243,8 @@ def test_basics2(self): } _test_compatibilities(**kwargs) - # NOTE: Test passes offline, but fails on TravisCI, see #372. - @unittest.skipIf( - os.environ.get('CI') == 'true' and os.environ.get('TRAVIS') == 'true', - 'Test is known to fail on TravisCI') + # NOTE: Test passes offline, but fails on TravisCI (and CircleCI), see #372. + @unittest.skipIf('CI' in os.environ, 'Test is known to fail on CI') def test_basics3(self): kwargs = { 'n_fft': 200, @@ -289,7 +288,7 @@ def test_MelScale(self): S=spec_lr, sr=sample_rate, n_fft=n_fft, hop_length=hop_length, win_length=n_fft, center=True, window='hann', n_mels=n_mels, htk=True, norm=None) # Note: Using relaxed rtol instead of atol - assert torch.allclose(melspec_ta, torch.from_numpy(melspec_lr[None, ...]), rtol=1e-3) + torch.testing.assert_allclose(melspec_ta, torch.from_numpy(melspec_lr[None, ...]), atol=1e-8, rtol=1e-3) def test_InverseMelScale(self): """InverseMelScale transform is comparable to that of librosa""" @@ -332,7 +331,7 @@ def test_InverseMelScale(self): # https://github.com/pytorch/audio/pull/366 for the discussion of the choice of algorithm # https://github.com/pytorch/audio/pull/448/files#r385747021 for the distribution of P-inf # distance over frequencies. - assert torch.allclose(spec_ta, spec_lr, atol=threshold) + torch.testing.assert_allclose(spec_ta, spec_lr, atol=threshold, rtol=1e-5) threshold = 1700.0 # This threshold was choosen empirically, based on the following observations diff --git a/test/test_functional_filtering.py b/test/test_sox_compatibility.py similarity index 54% rename from test/test_functional_filtering.py rename to test/test_sox_compatibility.py index c02abbd8d2..508ec7abfa 100644 --- a/test/test_functional_filtering.py +++ b/test/test_sox_compatibility.py @@ -1,4 +1,3 @@ -import os import unittest import torch @@ -6,102 +5,15 @@ import torchaudio.functional as F import torchaudio.transforms as T -from common_utils import AudioBackendScope, BACKENDS, create_temp_assets_dir +import common_utils +from common_utils import AudioBackendScope, BACKENDS class TestFunctionalFiltering(unittest.TestCase): - test_dirpath, test_dir = create_temp_assets_dir() - - def _test_lfilter_basic(self, dtype, device): - """ - Create a very basic signal, - Then make a simple 4th order delay - The output should be same as the input but shifted - """ - - torch.random.manual_seed(42) - waveform = torch.rand(2, 44100 * 1, dtype=dtype, device=device) - b_coeffs = torch.tensor([0, 0, 0, 1], dtype=dtype, device=device) - a_coeffs = torch.tensor([1, 0, 0, 0], dtype=dtype, device=device) - output_waveform = F.lfilter(waveform, a_coeffs, b_coeffs) - - assert torch.allclose(waveform[:, 0:-3], output_waveform[:, 3:], atol=1e-5) - - def test_lfilter_basic(self): - self._test_lfilter_basic(torch.float32, torch.device("cpu")) - - def test_lfilter_basic_double(self): - self._test_lfilter_basic(torch.float64, torch.device("cpu")) - - def test_lfilter_basic_gpu(self): - if torch.cuda.is_available(): - self._test_lfilter_basic(torch.float32, torch.device("cuda:0")) - else: - print("skipping GPU test for lfilter_basic because device not available") - pass - - def _test_lfilter(self, waveform, device): - """ - Design an IIR lowpass filter using scipy.signal filter design - https://docs.scipy.org/doc/scipy/reference/generated/scipy.signal.iirdesign.html#scipy.signal.iirdesign - - Example - >>> from scipy.signal import iirdesign - >>> b, a = iirdesign(0.2, 0.3, 1, 60) - """ - - b_coeffs = torch.tensor( - [ - 0.00299893, - -0.0051152, - 0.00841964, - -0.00747802, - 0.00841964, - -0.0051152, - 0.00299893, - ], - device=device, - ) - a_coeffs = torch.tensor( - [ - 1.0, - -4.8155751, - 10.2217618, - -12.14481273, - 8.49018171, - -3.3066882, - 0.56088705, - ], - device=device, - ) - - output_waveform = F.lfilter(waveform, a_coeffs, b_coeffs) - assert len(output_waveform.size()) == 2 - assert output_waveform.size(0) == waveform.size(0) - assert output_waveform.size(1) == waveform.size(1) - - def test_lfilter(self): - - filepath = os.path.join(self.test_dirpath, "assets", "whitenoise.wav") - waveform, _ = torchaudio.load(filepath, normalization=True) - - self._test_lfilter(waveform, torch.device("cpu")) - - def test_lfilter_gpu(self): - if torch.cuda.is_available(): - filepath = os.path.join(self.test_dirpath, "assets", "whitenoise.wav") - waveform, _ = torchaudio.load(filepath, normalization=True) - cuda0 = torch.device("cuda:0") - cuda_waveform = waveform.cuda(device=cuda0) - self._test_lfilter(cuda_waveform, cuda0) - else: - print("skipping GPU test for lfilter because device not available") - pass - @unittest.skipIf("sox" not in BACKENDS, "sox not available") @AudioBackendScope("sox") def test_gain(self): - test_filepath = os.path.join(self.test_dirpath, "assets", "steam-train-whistle-daniel_simon.wav") + test_filepath = common_utils.get_asset_path('steam-train-whistle-daniel_simon.wav') waveform, _ = torchaudio.load(test_filepath) waveform_gain = F.gain(waveform, 3) @@ -112,12 +24,12 @@ def test_gain(self): E.append_effect_to_chain("gain", [3]) sox_gain_waveform = E.sox_build_flow_effects()[0] - assert torch.allclose(waveform_gain, sox_gain_waveform, atol=1e-04) + torch.testing.assert_allclose(waveform_gain, sox_gain_waveform, atol=1e-04, rtol=1e-5) @unittest.skipIf("sox" not in BACKENDS, "sox not available") @AudioBackendScope("sox") def test_dither(self): - test_filepath = os.path.join(self.test_dirpath, "assets", "steam-train-whistle-daniel_simon.wav") + test_filepath = common_utils.get_asset_path('steam-train-whistle-daniel_simon.wav') waveform, _ = torchaudio.load(test_filepath) waveform_dithered = F.dither(waveform) @@ -128,18 +40,18 @@ def test_dither(self): E.append_effect_to_chain("dither", []) sox_dither_waveform = E.sox_build_flow_effects()[0] - assert torch.allclose(waveform_dithered, sox_dither_waveform, atol=1e-04) + torch.testing.assert_allclose(waveform_dithered, sox_dither_waveform, atol=1e-04, rtol=1e-5) E.clear_chain() E.append_effect_to_chain("dither", ["-s"]) sox_dither_waveform_ns = E.sox_build_flow_effects()[0] - assert torch.allclose(waveform_dithered_noiseshaped, sox_dither_waveform_ns, atol=1e-02) + torch.testing.assert_allclose(waveform_dithered_noiseshaped, sox_dither_waveform_ns, atol=1e-02, rtol=1e-5) @unittest.skipIf("sox" not in BACKENDS, "sox not available") @AudioBackendScope("sox") def test_vctk_transform_pipeline(self): - test_filepath_vctk = os.path.join(self.test_dirpath, "assets/VCTK-Corpus/wav48/p224/", "p224_002.wav") + test_filepath_vctk = common_utils.get_asset_path('VCTK-Corpus', 'wav48', 'p224', 'p224_002.wav') wf_vctk, sr_vctk = torchaudio.load(test_filepath_vctk) # rate @@ -157,28 +69,27 @@ def test_vctk_transform_pipeline(self): E.append_effect_to_chain("dither", ["-s"]) wf_vctk_sox = E.sox_build_flow_effects()[0] - assert torch.allclose(wf_vctk, wf_vctk_sox, rtol=1e-03, atol=1e-03) + torch.testing.assert_allclose(wf_vctk, wf_vctk_sox, rtol=1e-03, atol=1e-03) @unittest.skipIf("sox" not in BACKENDS, "sox not available") @AudioBackendScope("sox") def test_lowpass(self): - """ Test biquad lowpass filter, compare to SoX implementation """ - CUTOFF_FREQ = 3000 + cutoff_freq = 3000 - noise_filepath = os.path.join(self.test_dirpath, "assets", "whitenoise.wav") + noise_filepath = common_utils.get_asset_path('whitenoise.wav') E = torchaudio.sox_effects.SoxEffectsChain() E.set_input_file(noise_filepath) - E.append_effect_to_chain("lowpass", [CUTOFF_FREQ]) + E.append_effect_to_chain("lowpass", [cutoff_freq]) sox_output_waveform, sr = E.sox_build_flow_effects() waveform, sample_rate = torchaudio.load(noise_filepath, normalization=True) - output_waveform = F.lowpass_biquad(waveform, sample_rate, CUTOFF_FREQ) + output_waveform = F.lowpass_biquad(waveform, sample_rate, cutoff_freq) - assert torch.allclose(sox_output_waveform, output_waveform, atol=1e-4) + torch.testing.assert_allclose(output_waveform, sox_output_waveform, atol=1e-4, rtol=1e-5) @unittest.skipIf("sox" not in BACKENDS, "sox not available") @AudioBackendScope("sox") @@ -187,19 +98,19 @@ def test_highpass(self): Test biquad highpass filter, compare to SoX implementation """ - CUTOFF_FREQ = 2000 + cutoff_freq = 2000 - noise_filepath = os.path.join(self.test_dirpath, "assets", "whitenoise.wav") + noise_filepath = common_utils.get_asset_path('whitenoise.wav') E = torchaudio.sox_effects.SoxEffectsChain() E.set_input_file(noise_filepath) - E.append_effect_to_chain("highpass", [CUTOFF_FREQ]) + E.append_effect_to_chain("highpass", [cutoff_freq]) sox_output_waveform, sr = E.sox_build_flow_effects() waveform, sample_rate = torchaudio.load(noise_filepath, normalization=True) - output_waveform = F.highpass_biquad(waveform, sample_rate, CUTOFF_FREQ) + output_waveform = F.highpass_biquad(waveform, sample_rate, cutoff_freq) # TBD - this fails at the 1e-4 level, debug why - assert torch.allclose(sox_output_waveform, output_waveform, atol=1e-3) + torch.testing.assert_allclose(output_waveform, sox_output_waveform, atol=1e-3, rtol=1e-5) @unittest.skipIf("sox" not in BACKENDS, "sox not available") @AudioBackendScope("sox") @@ -208,19 +119,19 @@ def test_allpass(self): Test biquad allpass filter, compare to SoX implementation """ - CENTRAL_FREQ = 1000 - Q = 0.707 + central_freq = 1000 + q = 0.707 - noise_filepath = os.path.join(self.test_dirpath, "assets", "whitenoise.wav") + noise_filepath = common_utils.get_asset_path('whitenoise.wav') E = torchaudio.sox_effects.SoxEffectsChain() E.set_input_file(noise_filepath) - E.append_effect_to_chain("allpass", [CENTRAL_FREQ, str(Q) + 'q']) + E.append_effect_to_chain("allpass", [central_freq, str(q) + 'q']) sox_output_waveform, sr = E.sox_build_flow_effects() waveform, sample_rate = torchaudio.load(noise_filepath, normalization=True) - output_waveform = F.allpass_biquad(waveform, sample_rate, CENTRAL_FREQ, Q) + output_waveform = F.allpass_biquad(waveform, sample_rate, central_freq, q) - assert torch.allclose(sox_output_waveform, output_waveform, atol=1e-4) + torch.testing.assert_allclose(output_waveform, sox_output_waveform, atol=1e-4, rtol=1e-5) @unittest.skipIf("sox" not in BACKENDS, "sox not available") @AudioBackendScope("sox") @@ -229,20 +140,20 @@ def test_bandpass_with_csg(self): Test biquad bandpass filter, compare to SoX implementation """ - CENTRAL_FREQ = 1000 - Q = 0.707 - CONST_SKIRT_GAIN = True + central_freq = 1000 + q = 0.707 + const_skirt_gain = True - noise_filepath = os.path.join(self.test_dirpath, "assets", "whitenoise.wav") + noise_filepath = common_utils.get_asset_path('whitenoise.wav') E = torchaudio.sox_effects.SoxEffectsChain() E.set_input_file(noise_filepath) - E.append_effect_to_chain("bandpass", ["-c", CENTRAL_FREQ, str(Q) + 'q']) + E.append_effect_to_chain("bandpass", ["-c", central_freq, str(q) + 'q']) sox_output_waveform, sr = E.sox_build_flow_effects() waveform, sample_rate = torchaudio.load(noise_filepath, normalization=True) - output_waveform = F.bandpass_biquad(waveform, sample_rate, CENTRAL_FREQ, Q, CONST_SKIRT_GAIN) + output_waveform = F.bandpass_biquad(waveform, sample_rate, central_freq, q, const_skirt_gain) - assert torch.allclose(sox_output_waveform, output_waveform, atol=1e-4) + torch.testing.assert_allclose(output_waveform, sox_output_waveform, atol=1e-4, rtol=1e-5) @unittest.skipIf("sox" not in BACKENDS, "sox not available") @AudioBackendScope("sox") @@ -251,20 +162,20 @@ def test_bandpass_without_csg(self): Test biquad bandpass filter, compare to SoX implementation """ - CENTRAL_FREQ = 1000 - Q = 0.707 - CONST_SKIRT_GAIN = False + central_freq = 1000 + q = 0.707 + const_skirt_gain = False - noise_filepath = os.path.join(self.test_dirpath, "assets", "whitenoise.wav") + noise_filepath = common_utils.get_asset_path('whitenoise.wav') E = torchaudio.sox_effects.SoxEffectsChain() E.set_input_file(noise_filepath) - E.append_effect_to_chain("bandpass", [CENTRAL_FREQ, str(Q) + 'q']) + E.append_effect_to_chain("bandpass", [central_freq, str(q) + 'q']) sox_output_waveform, sr = E.sox_build_flow_effects() waveform, sample_rate = torchaudio.load(noise_filepath, normalization=True) - output_waveform = F.bandpass_biquad(waveform, sample_rate, CENTRAL_FREQ, Q, CONST_SKIRT_GAIN) + output_waveform = F.bandpass_biquad(waveform, sample_rate, central_freq, q, const_skirt_gain) - assert torch.allclose(sox_output_waveform, output_waveform, atol=1e-4) + torch.testing.assert_allclose(output_waveform, sox_output_waveform, atol=1e-4, rtol=1e-5) @unittest.skipIf("sox" not in BACKENDS, "sox not available") @AudioBackendScope("sox") @@ -273,19 +184,19 @@ def test_bandreject(self): Test biquad bandreject filter, compare to SoX implementation """ - CENTRAL_FREQ = 1000 - Q = 0.707 + central_freq = 1000 + q = 0.707 - noise_filepath = os.path.join(self.test_dirpath, "assets", "whitenoise.wav") + noise_filepath = common_utils.get_asset_path('whitenoise.wav') E = torchaudio.sox_effects.SoxEffectsChain() E.set_input_file(noise_filepath) - E.append_effect_to_chain("bandreject", [CENTRAL_FREQ, str(Q) + 'q']) + E.append_effect_to_chain("bandreject", [central_freq, str(q) + 'q']) sox_output_waveform, sr = E.sox_build_flow_effects() waveform, sample_rate = torchaudio.load(noise_filepath, normalization=True) - output_waveform = F.bandreject_biquad(waveform, sample_rate, CENTRAL_FREQ, Q) + output_waveform = F.bandreject_biquad(waveform, sample_rate, central_freq, q) - assert torch.allclose(sox_output_waveform, output_waveform, atol=1e-4) + torch.testing.assert_allclose(output_waveform, sox_output_waveform, atol=1e-4, rtol=1e-5) @unittest.skipIf("sox" not in BACKENDS, "sox not available") @AudioBackendScope("sox") @@ -294,20 +205,20 @@ def test_band_with_noise(self): Test biquad band filter with noise mode, compare to SoX implementation """ - CENTRAL_FREQ = 1000 - Q = 0.707 - NOISE = True + central_freq = 1000 + q = 0.707 + noise = True - noise_filepath = os.path.join(self.test_dirpath, "assets", "whitenoise.wav") + noise_filepath = common_utils.get_asset_path('whitenoise.wav') E = torchaudio.sox_effects.SoxEffectsChain() E.set_input_file(noise_filepath) - E.append_effect_to_chain("band", ["-n", CENTRAL_FREQ, str(Q) + 'q']) + E.append_effect_to_chain("band", ["-n", central_freq, str(q) + 'q']) sox_output_waveform, sr = E.sox_build_flow_effects() waveform, sample_rate = torchaudio.load(noise_filepath, normalization=True) - output_waveform = F.band_biquad(waveform, sample_rate, CENTRAL_FREQ, Q, NOISE) + output_waveform = F.band_biquad(waveform, sample_rate, central_freq, q, noise) - assert torch.allclose(sox_output_waveform, output_waveform, atol=1e-4) + torch.testing.assert_allclose(output_waveform, sox_output_waveform, atol=1e-4, rtol=1e-5) @unittest.skipIf("sox" not in BACKENDS, "sox not available") @AudioBackendScope("sox") @@ -316,20 +227,20 @@ def test_band_without_noise(self): Test biquad band filter without noise mode, compare to SoX implementation """ - CENTRAL_FREQ = 1000 - Q = 0.707 - NOISE = False + central_freq = 1000 + q = 0.707 + noise = False - noise_filepath = os.path.join(self.test_dirpath, "assets", "whitenoise.wav") + noise_filepath = common_utils.get_asset_path('whitenoise.wav') E = torchaudio.sox_effects.SoxEffectsChain() E.set_input_file(noise_filepath) - E.append_effect_to_chain("band", [CENTRAL_FREQ, str(Q) + 'q']) + E.append_effect_to_chain("band", [central_freq, str(q) + 'q']) sox_output_waveform, sr = E.sox_build_flow_effects() waveform, sample_rate = torchaudio.load(noise_filepath, normalization=True) - output_waveform = F.band_biquad(waveform, sample_rate, CENTRAL_FREQ, Q, NOISE) + output_waveform = F.band_biquad(waveform, sample_rate, central_freq, q, noise) - assert torch.allclose(sox_output_waveform, output_waveform, atol=1e-4) + torch.testing.assert_allclose(output_waveform, sox_output_waveform, atol=1e-4, rtol=1e-5) @unittest.skipIf("sox" not in BACKENDS, "sox not available") @AudioBackendScope("sox") @@ -338,20 +249,20 @@ def test_treble(self): Test biquad treble filter, compare to SoX implementation """ - CENTRAL_FREQ = 1000 - Q = 0.707 - GAIN = 40 + central_freq = 1000 + q = 0.707 + gain = 40 - noise_filepath = os.path.join(self.test_dirpath, "assets", "whitenoise.wav") + noise_filepath = common_utils.get_asset_path('whitenoise.wav') E = torchaudio.sox_effects.SoxEffectsChain() E.set_input_file(noise_filepath) - E.append_effect_to_chain("treble", [GAIN, CENTRAL_FREQ, str(Q) + 'q']) + E.append_effect_to_chain("treble", [gain, central_freq, str(q) + 'q']) sox_output_waveform, sr = E.sox_build_flow_effects() waveform, sample_rate = torchaudio.load(noise_filepath, normalization=True) - output_waveform = F.treble_biquad(waveform, sample_rate, GAIN, CENTRAL_FREQ, Q) + output_waveform = F.treble_biquad(waveform, sample_rate, gain, central_freq, q) - assert torch.allclose(sox_output_waveform, output_waveform, atol=1e-4) + torch.testing.assert_allclose(output_waveform, sox_output_waveform, atol=1e-4, rtol=1e-5) @unittest.skipIf("sox" not in BACKENDS, "sox not available") @AudioBackendScope("sox") @@ -360,7 +271,7 @@ def test_deemph(self): Test biquad deemph filter, compare to SoX implementation """ - noise_filepath = os.path.join(self.test_dirpath, "assets", "whitenoise.wav") + noise_filepath = common_utils.get_asset_path('whitenoise.wav') E = torchaudio.sox_effects.SoxEffectsChain() E.set_input_file(noise_filepath) E.append_effect_to_chain("deemph") @@ -369,7 +280,7 @@ def test_deemph(self): waveform, sample_rate = torchaudio.load(noise_filepath, normalization=True) output_waveform = F.deemph_biquad(waveform, sample_rate) - assert torch.allclose(sox_output_waveform, output_waveform, atol=1e-4) + torch.testing.assert_allclose(output_waveform, sox_output_waveform, atol=1e-4, rtol=1e-5) @unittest.skipIf("sox" not in BACKENDS, "sox not available") @AudioBackendScope("sox") @@ -378,7 +289,7 @@ def test_riaa(self): Test biquad riaa filter, compare to SoX implementation """ - noise_filepath = os.path.join(self.test_dirpath, "assets", "whitenoise.wav") + noise_filepath = common_utils.get_asset_path('whitenoise.wav') E = torchaudio.sox_effects.SoxEffectsChain() E.set_input_file(noise_filepath) E.append_effect_to_chain("riaa") @@ -387,7 +298,81 @@ def test_riaa(self): waveform, sample_rate = torchaudio.load(noise_filepath, normalization=True) output_waveform = F.riaa_biquad(waveform, sample_rate) - assert torch.allclose(sox_output_waveform, output_waveform, atol=1e-4) + torch.testing.assert_allclose(output_waveform, sox_output_waveform, atol=1e-4, rtol=1e-5) + + @unittest.skipIf("sox" not in BACKENDS, "sox not available") + @AudioBackendScope("sox") + def test_contrast(self): + """ + Test contrast effect, compare to SoX implementation + """ + enhancement_amount = 80. + noise_filepath = common_utils.get_asset_path('whitenoise.wav') + E = torchaudio.sox_effects.SoxEffectsChain() + E.set_input_file(noise_filepath) + E.append_effect_to_chain("contrast", [enhancement_amount]) + sox_output_waveform, sr = E.sox_build_flow_effects() + + waveform, sample_rate = torchaudio.load(noise_filepath, normalization=True) + output_waveform = F.contrast(waveform, enhancement_amount) + + torch.testing.assert_allclose(output_waveform, sox_output_waveform, atol=1e-4, rtol=1e-5) + + @unittest.skipIf("sox" not in BACKENDS, "sox not available") + @AudioBackendScope("sox") + def test_dcshift_with_limiter(self): + """ + Test dcshift effect, compare to SoX implementation + """ + shift = 0.5 + limiter_gain = 0.05 + noise_filepath = common_utils.get_asset_path('whitenoise.wav') + E = torchaudio.sox_effects.SoxEffectsChain() + E.set_input_file(noise_filepath) + E.append_effect_to_chain("dcshift", [shift, limiter_gain]) + sox_output_waveform, sr = E.sox_build_flow_effects() + + waveform, _ = torchaudio.load(noise_filepath, normalization=True) + output_waveform = F.dcshift(waveform, shift, limiter_gain) + + torch.testing.assert_allclose(output_waveform, sox_output_waveform, atol=1e-4, rtol=1e-5) + + @unittest.skipIf("sox" not in BACKENDS, "sox not available") + @AudioBackendScope("sox") + def test_dcshift_without_limiter(self): + """ + Test dcshift effect, compare to SoX implementation + """ + shift = 0.6 + noise_filepath = common_utils.get_asset_path('whitenoise.wav') + E = torchaudio.sox_effects.SoxEffectsChain() + E.set_input_file(noise_filepath) + E.append_effect_to_chain("dcshift", [shift]) + sox_output_waveform, sr = E.sox_build_flow_effects() + + waveform, _ = torchaudio.load(noise_filepath, normalization=True) + output_waveform = F.dcshift(waveform, shift) + + torch.testing.assert_allclose(output_waveform, sox_output_waveform, atol=1e-4, rtol=1e-5) + + @unittest.skipIf("sox" not in BACKENDS, "sox not available") + @AudioBackendScope("sox") + def test_overdrive(self): + """ + Test overdrive effect, compare to SoX implementation + """ + gain = 30 + colour = 40 + noise_filepath = common_utils.get_asset_path('whitenoise.wav') + E = torchaudio.sox_effects.SoxEffectsChain() + E.set_input_file(noise_filepath) + E.append_effect_to_chain("overdrive", [gain, colour]) + sox_output_waveform, sr = E.sox_build_flow_effects() + + waveform, _ = torchaudio.load(noise_filepath, normalization=True) + output_waveform = F.overdrive(waveform, gain, colour) + + torch.testing.assert_allclose(output_waveform, sox_output_waveform, atol=1e-4, rtol=1e-5) @unittest.skipIf("sox" not in BACKENDS, "sox not available") @AudioBackendScope("sox") @@ -396,26 +381,26 @@ def test_equalizer(self): Test biquad peaking equalizer filter, compare to SoX implementation """ - CENTER_FREQ = 300 - Q = 0.707 - GAIN = 1 + center_freq = 300 + q = 0.707 + gain = 1 - noise_filepath = os.path.join(self.test_dirpath, "assets", "whitenoise.wav") + noise_filepath = common_utils.get_asset_path('whitenoise.wav') E = torchaudio.sox_effects.SoxEffectsChain() E.set_input_file(noise_filepath) - E.append_effect_to_chain("equalizer", [CENTER_FREQ, Q, GAIN]) + E.append_effect_to_chain("equalizer", [center_freq, q, gain]) sox_output_waveform, sr = E.sox_build_flow_effects() waveform, sample_rate = torchaudio.load(noise_filepath, normalization=True) - output_waveform = F.equalizer_biquad(waveform, sample_rate, CENTER_FREQ, GAIN, Q) + output_waveform = F.equalizer_biquad(waveform, sample_rate, center_freq, gain, q) - assert torch.allclose(sox_output_waveform, output_waveform, atol=1e-4) + torch.testing.assert_allclose(output_waveform, sox_output_waveform, atol=1e-4, rtol=1e-5) @unittest.skipIf("sox" not in BACKENDS, "sox not available") @AudioBackendScope("sox") def test_perf_biquad_filtering(self): - fn_sine = os.path.join(self.test_dirpath, "assets", "whitenoise.wav") + fn_sine = common_utils.get_asset_path('whitenoise.wav') b0 = 0.4 b1 = 0.2 @@ -435,7 +420,7 @@ def test_perf_biquad_filtering(self): waveform, torch.tensor([a0, a1, a2]), torch.tensor([b0, b1, b2]) ) - assert torch.allclose(waveform_sox_out, waveform_lfilter_out, atol=1e-4) + torch.testing.assert_allclose(waveform_lfilter_out, waveform_sox_out, atol=1e-4, rtol=1e-5) if __name__ == "__main__": diff --git a/test/test_sox_effects.py b/test/test_sox_effects.py index 3445a5144b..487d73a53d 100644 --- a/test/test_sox_effects.py +++ b/test/test_sox_effects.py @@ -2,27 +2,17 @@ import torch import torchaudio import math -import os -from common_utils import AudioBackendScope, BACKENDS, create_temp_assets_dir +import common_utils +from common_utils import AudioBackendScope, BACKENDS @unittest.skipIf("sox" not in BACKENDS, "sox not available") class Test_SoxEffectsChain(unittest.TestCase): - test_dirpath, test_dir = create_temp_assets_dir() - test_filepath = os.path.join(test_dirpath, "assets", - "steam-train-whistle-daniel_simon.mp3") - - @classmethod - def setUpClass(cls): - torchaudio.initialize_sox() - - @classmethod - def tearDownClass(cls): - torchaudio.shutdown_sox() + test_filepath = common_utils.get_asset_path("steam-train-whistle-daniel_simon.mp3") def test_single_channel(self): - fn_sine = os.path.join(self.test_dirpath, "assets", "sinewave.wav") + fn_sine = common_utils.get_asset_path("sinewave.wav") E = torchaudio.sox_effects.SoxEffectsChain() E.set_input_file(fn_sine) E.append_effect_to_chain("echos", [0.8, 0.7, 40, 0.25, 63, 0.3]) @@ -259,6 +249,24 @@ def test_vol(self): # check if effect worked self.assertTrue(x.allclose(z, rtol=1e-4, atol=1e-4)) + def test_vad(self): + sample_files = [ + common_utils.get_asset_path("vad-hello-stereo-44100.wav"), + common_utils.get_asset_path("vad-hello-mono-32000.wav") + ] + + for sample_file in sample_files: + E = torchaudio.sox_effects.SoxEffectsChain() + E.set_input_file(sample_file) + E.append_effect_to_chain("vad") + x, _ = E.sox_build_flow_effects() + + x_orig, sample_rate = torchaudio.load(sample_file) + vad = torchaudio.transforms.Vad(sample_rate) + + y = vad(x_orig) + self.assertTrue(x.allclose(y, rtol=1e-4, atol=1e-4)) + if __name__ == '__main__': with AudioBackendScope("sox"): diff --git a/test/test_torchscript_consistency.py b/test/test_torchscript_consistency.py index fba009d29d..5f0b12c76b 100644 --- a/test/test_torchscript_consistency.py +++ b/test/test_torchscript_consistency.py @@ -1,413 +1,588 @@ """Test suites for jit-ability and its numerical compatibility""" -import os import unittest import torch import torchaudio import torchaudio.functional as F -import torchaudio.transforms +import torchaudio.transforms as T import common_utils -def _test_torchscript_functional_shape(py_method, *args, **kwargs): - jit_method = torch.jit.script(py_method) - - jit_out = jit_method(*args, **kwargs) - py_out = py_method(*args, **kwargs) - - assert jit_out.shape == py_out.shape - return jit_out, py_out - - -def _test_torchscript_functional(py_method, *args, **kwargs): - jit_out, py_out = _test_torchscript_functional_shape(py_method, *args, **kwargs) - assert torch.allclose(jit_out, py_out) - - -def _test_lfilter(waveform): - """ - Design an IIR lowpass filter using scipy.signal filter design - https://docs.scipy.org/doc/scipy/reference/generated/scipy.signal.iirdesign.html#scipy.signal.iirdesign - - Example - >>> from scipy.signal import iirdesign - >>> b, a = iirdesign(0.2, 0.3, 1, 60) - """ - b_coeffs = torch.tensor( - [ - 0.00299893, - -0.0051152, - 0.00841964, - -0.00747802, - 0.00841964, - -0.0051152, - 0.00299893, - ], - device=waveform.device, - ) - a_coeffs = torch.tensor( - [ - 1.0, - -4.8155751, - 10.2217618, - -12.14481273, - 8.49018171, - -3.3066882, - 0.56088705, - ], - device=waveform.device, - ) - _test_torchscript_functional(F.lfilter, waveform, a_coeffs, b_coeffs) - - -class TestFunctional(unittest.TestCase): - """Test functions in `functional` module.""" +def _assert_functional_consistency(func, tensor, device, shape_only=False): + tensor = tensor.to(device) + ts_func = torch.jit.script(func) + output = func(tensor) + ts_output = ts_func(tensor) + + if shape_only: + assert ts_output.shape == output.shape, (ts_output.shape, output.shape) + else: + torch.testing.assert_allclose(ts_output, output) + + +def _assert_transforms_consistency(transform, tensor, device): + tensor = tensor.to(device) + transform = transform.to(device) + ts_transform = torch.jit.script(transform) + output = transform(tensor) + ts_output = ts_transform(tensor) + torch.testing.assert_allclose(ts_output, output) + + +class _FunctionalTestMixin: + """Implements test for `functinoal` modul that are performed for different devices""" + device = None + + def _assert_consistency(self, func, tensor, shape_only=False): + return _assert_functional_consistency(func, tensor, self.device, shape_only=shape_only) + def test_spectrogram(self): + def func(tensor): + n_fft = 400 + ws = 400 + hop = 200 + pad = 0 + window = torch.hann_window(ws, device=tensor.device, dtype=tensor.dtype) + power = 2. + normalize = False + return F.spectrogram(tensor, pad, window, n_fft, hop, ws, power, normalize) + tensor = torch.rand((1, 1000)) - n_fft = 400 - ws = 400 - hop = 200 - pad = 0 - window = torch.hann_window(ws) - power = 2 - normalize = False - - _test_torchscript_functional( - F.spectrogram, tensor, pad, window, n_fft, hop, ws, power, normalize - ) + self._assert_consistency(func, tensor) def test_griffinlim(self): + def func(tensor): + n_fft = 400 + ws = 400 + hop = 200 + window = torch.hann_window(ws, device=tensor.device, dtype=tensor.dtype) + power = 2. + normalize = False + momentum = 0.99 + n_iter = 32 + length = 1000 + rand_int = False + return F.griffinlim(tensor, window, n_fft, hop, ws, power, normalize, n_iter, momentum, length, rand_int) + tensor = torch.rand((1, 201, 6)) - n_fft = 400 - ws = 400 - hop = 200 - window = torch.hann_window(ws) - power = 2 - normalize = False - momentum = 0.99 - n_iter = 32 - length = 1000 - - _test_torchscript_functional( - F.griffinlim, tensor, window, n_fft, hop, ws, power, normalize, n_iter, momentum, length, 0 - ) + self._assert_consistency(func, tensor) def test_compute_deltas(self): + def func(tensor): + win_length = 2 * 7 + 1 + return F.compute_deltas(tensor, win_length=win_length) + channel = 13 n_mfcc = channel * 3 time = 1021 - win_length = 2 * 7 + 1 - specgram = torch.randn(channel, n_mfcc, time) - - _test_torchscript_functional(F.compute_deltas, specgram, win_length=win_length) + tensor = torch.randn(channel, n_mfcc, time) + self._assert_consistency(func, tensor) def test_detect_pitch_frequency(self): - filepath = os.path.join( - common_utils.TEST_DIR_PATH, 'assets', 'steam-train-whistle-daniel_simon.mp3') - waveform, sample_rate = torchaudio.load(filepath) - _test_torchscript_functional(F.detect_pitch_frequency, waveform, sample_rate) + filepath = common_utils.get_asset_path('steam-train-whistle-daniel_simon.mp3') + waveform, _ = torchaudio.load(filepath) + + def func(tensor): + sample_rate = 44100 + return F.detect_pitch_frequency(tensor, sample_rate) + + self._assert_consistency(func, waveform) def test_create_fb_matrix(self): - n_stft = 100 - f_min = 0.0 - f_max = 20.0 - n_mels = 10 - sample_rate = 16000 + if self.device != torch.device('cpu'): + raise unittest.SkipTest('No need to perform test on device other than CPU') + + def func(_): + n_stft = 100 + f_min = 0.0 + f_max = 20.0 + n_mels = 10 + sample_rate = 16000 + return F.create_fb_matrix(n_stft, f_min, f_max, n_mels, sample_rate) - _test_torchscript_functional(F.create_fb_matrix, n_stft, f_min, f_max, n_mels, sample_rate) + dummy = torch.zeros(1, 1) + self._assert_consistency(func, dummy) def test_amplitude_to_DB(self): - spec = torch.rand((6, 201)) - multiplier = 10.0 - amin = 1e-10 - db_multiplier = 0.0 - top_db = 80.0 + def func(tensor): + multiplier = 10.0 + amin = 1e-10 + db_multiplier = 0.0 + top_db = 80.0 + return F.amplitude_to_DB(tensor, multiplier, amin, db_multiplier, top_db) - _test_torchscript_functional(F.amplitude_to_DB, spec, multiplier, amin, db_multiplier, top_db) + tensor = torch.rand((6, 201)) + self._assert_consistency(func, tensor) def test_DB_to_amplitude(self): - x = torch.rand((1, 100)) - ref = 1. - power = 1. + def func(tensor): + ref = 1. + power = 1. + return F.DB_to_amplitude(tensor, ref, power) - _test_torchscript_functional(F.DB_to_amplitude, x, ref, power) + tensor = torch.rand((1, 100)) + self._assert_consistency(func, tensor) def test_create_dct(self): - n_mfcc = 40 - n_mels = 128 - norm = "ortho" + if self.device != torch.device('cpu'): + raise unittest.SkipTest('No need to perform test on device other than CPU') + + def func(_): + n_mfcc = 40 + n_mels = 128 + norm = "ortho" + return F.create_dct(n_mfcc, n_mels, norm) - _test_torchscript_functional(F.create_dct, n_mfcc, n_mels, norm) + dummy = torch.zeros(1, 1) + self._assert_consistency(func, dummy) def test_mu_law_encoding(self): - tensor = torch.rand((1, 10)) - qc = 256 + def func(tensor): + qc = 256 + return F.mu_law_encoding(tensor, qc) - _test_torchscript_functional(F.mu_law_encoding, tensor, qc) + tensor = torch.rand((1, 10)) + self._assert_consistency(func, tensor) def test_mu_law_decoding(self): - tensor = torch.rand((1, 10)) - qc = 256 + def func(tensor): + qc = 256 + return F.mu_law_decoding(tensor, qc) - _test_torchscript_functional(F.mu_law_decoding, tensor, qc) + tensor = torch.rand((1, 10)) + self._assert_consistency(func, tensor) def test_complex_norm(self): - complex_tensor = torch.randn(1, 2, 1025, 400, 2) - power = 2 + def func(tensor): + power = 2. + return F.complex_norm(tensor, power) - _test_torchscript_functional(F.complex_norm, complex_tensor, power) + tensor = torch.randn(1, 2, 1025, 400, 2) + _assert_functional_consistency(func, tensor, self.device) def test_mask_along_axis(self): - specgram = torch.randn(2, 1025, 400) - mask_param = 100 - mask_value = 30. - axis = 2 + def func(tensor): + mask_param = 100 + mask_value = 30. + axis = 2 + return F.mask_along_axis(tensor, mask_param, mask_value, axis) - _test_torchscript_functional(F.mask_along_axis, specgram, mask_param, mask_value, axis) + tensor = torch.randn(2, 1025, 400) + self._assert_consistency(func, tensor) def test_mask_along_axis_iid(self): - specgrams = torch.randn(4, 2, 1025, 400) - mask_param = 100 - mask_value = 30. - axis = 2 + def func(tensor): + mask_param = 100 + mask_value = 30. + axis = 2 + return F.mask_along_axis_iid(tensor, mask_param, mask_value, axis) - _test_torchscript_functional(F.mask_along_axis_iid, specgrams, mask_param, mask_value, axis) + tensor = torch.randn(4, 2, 1025, 400) + self._assert_consistency(func, tensor) def test_gain(self): + def func(tensor): + gainDB = 2.0 + return F.gain(tensor, gainDB) + tensor = torch.rand((1, 1000)) - gainDB = 2.0 + self._assert_consistency(func, tensor) - _test_torchscript_functional(F.gain, tensor, gainDB) + def test_dither_TPDF(self): + def func(tensor): + return F.dither(tensor, 'TPDF') - def test_dither(self): tensor = torch.rand((2, 1000)) + self._assert_consistency(func, tensor, shape_only=True) + + def test_dither_RPDF(self): + def func(tensor): + return F.dither(tensor, 'RPDF') + + tensor = torch.rand((2, 1000)) + self._assert_consistency(func, tensor, shape_only=True) + + def test_dither_GPDF(self): + def func(tensor): + return F.dither(tensor, 'GPDF') - _test_torchscript_functional_shape(F.dither, tensor) - _test_torchscript_functional_shape(F.dither, tensor, "RPDF") - _test_torchscript_functional_shape(F.dither, tensor, "GPDF") + tensor = torch.rand((2, 1000)) + self._assert_consistency(func, tensor, shape_only=True) def test_lfilter(self): - filepath = os.path.join(common_utils.TEST_DIR_PATH, 'assets', 'whitenoise.wav') + filepath = common_utils.get_asset_path('whitenoise.wav') waveform, _ = torchaudio.load(filepath, normalization=True) - _test_lfilter(waveform) - @unittest.skipIf(not torch.cuda.is_available(), "CUDA not available") - def test_lfilter_cuda(self): - filepath = os.path.join(common_utils.TEST_DIR_PATH, "assets", "whitenoise.wav") - waveform, _ = torchaudio.load(filepath, normalization=True) - _test_lfilter(waveform.cuda(device=torch.device("cuda:0"))) + def func(tensor): + # Design an IIR lowpass filter using scipy.signal filter design + # https://docs.scipy.org/doc/scipy/reference/generated/scipy.signal.iirdesign.html#scipy.signal.iirdesign + # + # Example + # >>> from scipy.signal import iirdesign + # >>> b, a = iirdesign(0.2, 0.3, 1, 60) + b_coeffs = torch.tensor( + [ + 0.00299893, + -0.0051152, + 0.00841964, + -0.00747802, + 0.00841964, + -0.0051152, + 0.00299893, + ], + device=tensor.device, + dtype=tensor.dtype, + ) + a_coeffs = torch.tensor( + [ + 1.0, + -4.8155751, + 10.2217618, + -12.14481273, + 8.49018171, + -3.3066882, + 0.56088705, + ], + device=tensor.device, + dtype=tensor.dtype, + ) + return F.lfilter(tensor, a_coeffs, b_coeffs) + + self._assert_consistency(func, waveform) def test_lowpass(self): - cutoff_freq = 3000 + filepath = common_utils.get_asset_path('whitenoise.wav') + waveform, _ = torchaudio.load(filepath, normalization=True) - filepath = os.path.join(common_utils.TEST_DIR_PATH, 'assets', 'whitenoise.wav') - waveform, sample_rate = torchaudio.load(filepath, normalization=True) - _test_torchscript_functional(F.lowpass_biquad, waveform, sample_rate, cutoff_freq) + def func(tensor): + sample_rate = 44100 + cutoff_freq = 3000. + return F.lowpass_biquad(tensor, sample_rate, cutoff_freq) + + self._assert_consistency(func, waveform) def test_highpass(self): - cutoff_freq = 2000 + filepath = common_utils.get_asset_path('whitenoise.wav') + waveform, _ = torchaudio.load(filepath, normalization=True) - filepath = os.path.join(common_utils.TEST_DIR_PATH, 'assets', 'whitenoise.wav') - waveform, sample_rate = torchaudio.load(filepath, normalization=True) - _test_torchscript_functional(F.highpass_biquad, waveform, sample_rate, cutoff_freq) + def func(tensor): + sample_rate = 44100 + cutoff_freq = 2000. + return F.highpass_biquad(tensor, sample_rate, cutoff_freq) + + self._assert_consistency(func, waveform) def test_allpass(self): - central_freq = 1000 - q = 0.707 + filepath = common_utils.get_asset_path('whitenoise.wav') + waveform, _ = torchaudio.load(filepath, normalization=True) - filepath = os.path.join(common_utils.TEST_DIR_PATH, 'assets', 'whitenoise.wav') - waveform, sample_rate = torchaudio.load(filepath, normalization=True) - _test_torchscript_functional(F.allpass_biquad, waveform, sample_rate, central_freq, q) + def func(tensor): + sample_rate = 44100 + central_freq = 1000. + q = 0.707 + return F.allpass_biquad(tensor, sample_rate, central_freq, q) + + self._assert_consistency(func, waveform) def test_bandpass_with_csg(self): - central_freq = 1000 - q = 0.707 - const_skirt_gain = True + filepath = common_utils.get_asset_path("whitenoise.wav") + waveform, _ = torchaudio.load(filepath, normalization=True) - filepath = os.path.join(common_utils.TEST_DIR_PATH, "assets", "whitenoise.wav") - waveform, sample_rate = torchaudio.load(filepath, normalization=True) - _test_torchscript_functional( - F.bandpass_biquad, waveform, sample_rate, central_freq, q, const_skirt_gain) + def func(tensor): + sample_rate = 44100 + central_freq = 1000. + q = 0.707 + const_skirt_gain = True + return F.bandpass_biquad(tensor, sample_rate, central_freq, q, const_skirt_gain) + + self._assert_consistency(func, waveform) def test_bandpass_withou_csg(self): - central_freq = 1000 - q = 0.707 - const_skirt_gain = False + filepath = common_utils.get_asset_path("whitenoise.wav") + waveform, _ = torchaudio.load(filepath, normalization=True) + + def func(tensor): + sample_rate = 44100 + central_freq = 1000. + q = 0.707 + const_skirt_gain = True + return F.bandpass_biquad(tensor, sample_rate, central_freq, q, const_skirt_gain) - filepath = os.path.join(common_utils.TEST_DIR_PATH, "assets", "whitenoise.wav") - waveform, sample_rate = torchaudio.load(filepath, normalization=True) - _test_torchscript_functional( - F.bandpass_biquad, waveform, sample_rate, central_freq, q, const_skirt_gain) + self._assert_consistency(func, waveform) def test_bandreject(self): - central_freq = 1000 - q = 0.707 + filepath = common_utils.get_asset_path("whitenoise.wav") + waveform, _ = torchaudio.load(filepath, normalization=True) + + def func(tensor): + sample_rate = 44100 + central_freq = 1000. + q = 0.707 + return F.bandreject_biquad(tensor, sample_rate, central_freq, q) - filepath = os.path.join(common_utils.TEST_DIR_PATH, "assets", "whitenoise.wav") - waveform, sample_rate = torchaudio.load(filepath, normalization=True) - _test_torchscript_functional( - F.bandreject_biquad, waveform, sample_rate, central_freq, q) + self._assert_consistency(func, waveform) def test_band_with_noise(self): - central_freq = 1000 - q = 0.707 - noise = True + filepath = common_utils.get_asset_path("whitenoise.wav") + waveform, _ = torchaudio.load(filepath, normalization=True) + + def func(tensor): + sample_rate = 44100 + central_freq = 1000. + q = 0.707 + noise = True + return F.band_biquad(tensor, sample_rate, central_freq, q, noise) - filepath = os.path.join(common_utils.TEST_DIR_PATH, "assets", "whitenoise.wav") - waveform, sample_rate = torchaudio.load(filepath, normalization=True) - _test_torchscript_functional(F.band_biquad, waveform, sample_rate, central_freq, q, noise) + self._assert_consistency(func, waveform) def test_band_without_noise(self): - central_freq = 1000 - q = 0.707 - noise = False + filepath = common_utils.get_asset_path("whitenoise.wav") + waveform, _ = torchaudio.load(filepath, normalization=True) - filepath = os.path.join(common_utils.TEST_DIR_PATH, "assets", "whitenoise.wav") - waveform, sample_rate = torchaudio.load(filepath, normalization=True) - _test_torchscript_functional(F.band_biquad, waveform, sample_rate, central_freq, q, noise) + def func(tensor): + sample_rate = 44100 + central_freq = 1000. + q = 0.707 + noise = False + return F.band_biquad(tensor, sample_rate, central_freq, q, noise) + + self._assert_consistency(func, waveform) def test_treble(self): - gain = 40 - central_freq = 1000 - q = 0.707 + filepath = common_utils.get_asset_path("whitenoise.wav") + waveform, _ = torchaudio.load(filepath, normalization=True) - filepath = os.path.join(common_utils.TEST_DIR_PATH, "assets", "whitenoise.wav") - waveform, sample_rate = torchaudio.load(filepath, normalization=True) - _test_torchscript_functional(F.treble_biquad, waveform, sample_rate, gain, central_freq, q) + def func(tensor): + sample_rate = 44100 + gain = 40. + central_freq = 1000. + q = 0.707 + return F.treble_biquad(tensor, sample_rate, gain, central_freq, q) + + self._assert_consistency(func, waveform) def test_deemph(self): - filepath = os.path.join(common_utils.TEST_DIR_PATH, "assets", "whitenoise.wav") - waveform, sample_rate = torchaudio.load(filepath, normalization=True) - _test_torchscript_functional(F.deemph_biquad, waveform, sample_rate) + filepath = common_utils.get_asset_path("whitenoise.wav") + waveform, _ = torchaudio.load(filepath, normalization=True) + + def func(tensor): + sample_rate = 44100 + return F.deemph_biquad(tensor, sample_rate) + + self._assert_consistency(func, waveform) def test_riaa(self): - filepath = os.path.join(common_utils.TEST_DIR_PATH, "assets", "whitenoise.wav") - waveform, sample_rate = torchaudio.load(filepath, normalization=True) - _test_torchscript_functional(F.riaa_biquad, waveform, sample_rate) + filepath = common_utils.get_asset_path("whitenoise.wav") + waveform, _ = torchaudio.load(filepath, normalization=True) + + def func(tensor): + sample_rate = 44100 + return F.riaa_biquad(tensor, sample_rate) + + self._assert_consistency(func, waveform) def test_equalizer(self): - center_freq = 300 - gain = 1 - q = 0.707 + filepath = common_utils.get_asset_path("whitenoise.wav") + waveform, _ = torchaudio.load(filepath, normalization=True) + + def func(tensor): + sample_rate = 44100 + center_freq = 300. + gain = 1. + q = 0.707 + return F.equalizer_biquad(tensor, sample_rate, center_freq, gain, q) - filepath = os.path.join(common_utils.TEST_DIR_PATH, "assets", "whitenoise.wav") - waveform, sample_rate = torchaudio.load(filepath, normalization=True) - _test_torchscript_functional( - F.equalizer_biquad, waveform, sample_rate, center_freq, gain, q) + self._assert_consistency(func, waveform) def test_perf_biquad_filtering(self): - a = torch.tensor([0.7, 0.2, 0.6]) - b = torch.tensor([0.4, 0.2, 0.9]) - filepath = os.path.join(common_utils.TEST_DIR_PATH, "assets", "whitenoise.wav") + filepath = common_utils.get_asset_path("whitenoise.wav") waveform, _ = torchaudio.load(filepath, normalization=True) - _test_torchscript_functional(F.lfilter, waveform, a, b) + def func(tensor): + a = torch.tensor([0.7, 0.2, 0.6], device=tensor.device, dtype=tensor.dtype) + b = torch.tensor([0.4, 0.2, 0.9], device=tensor.device, dtype=tensor.dtype) + return F.lfilter(tensor, a, b) + + self._assert_consistency(func, waveform) + + def test_sliding_window_cmn(self): + def func(tensor): + cmn_window = 600 + min_cmn_window = 100 + center = False + norm_vars = False + a = torch.tensor( + [ + [ + -1.915875792503357, + 1.147700309753418 + ], + [ + 1.8242558240890503, + 1.3869990110397339 + ] + ], + device=tensor.device, + dtype=tensor.dtype + ) + return F.sliding_window_cmn(a, cmn_window, min_cmn_window, center, norm_vars) + b = torch.tensor( + [ + [ + -1.8701, + -0.1196 + ], + [ + 1.8701, + 0.1196 + ] + ] + ) + self._assert_consistency(func, b) -RUN_CUDA = torch.cuda.is_available() -print("Run test with cuda:", RUN_CUDA) + def test_contrast(self): + filepath = common_utils.get_asset_path("whitenoise.wav") + waveform, _ = torchaudio.load(filepath, normalization=True) + def func(tensor): + enhancement_amount = 80. + return F.contrast(tensor, enhancement_amount) -def _test_script_module(f, tensor, *args, **kwargs): + self._assert_consistency(func, waveform) - py_method = f(*args, **kwargs) - jit_method = torch.jit.script(py_method) + def test_dcshift(self): + filepath = common_utils.get_asset_path("whitenoise.wav") + waveform, _ = torchaudio.load(filepath, normalization=True) - py_out = py_method(tensor) - jit_out = jit_method(tensor) + def func(tensor): + shift = 0.5 + limiter_gain = 0.05 + return F.dcshift(tensor, shift, limiter_gain) - assert torch.allclose(jit_out, py_out) + self._assert_consistency(func, waveform) - if RUN_CUDA: + def test_overdrive(self): + filepath = common_utils.get_asset_path("whitenoise.wav") + waveform, _ = torchaudio.load(filepath, normalization=True) - tensor = tensor.to("cuda") + def func(tensor): + gain = 30. + colour = 50. + return F.overdrive(tensor, gain, colour) - py_method = py_method.cuda() - jit_method = torch.jit.script(py_method) + self._assert_consistency(func, waveform) - py_out = py_method(tensor) - jit_out = jit_method(tensor) - assert torch.allclose(jit_out, py_out) +class _TransformsTestMixin: + """Implements test for Transforms that are performed for different devices""" + device = None + def _assert_consistency(self, transform, tensor): + _assert_transforms_consistency(transform, tensor, self.device) -class TestTransforms(unittest.TestCase): def test_Spectrogram(self): tensor = torch.rand((1, 1000)) - _test_script_module(torchaudio.transforms.Spectrogram, tensor) + self._assert_consistency(T.Spectrogram(), tensor) def test_GriffinLim(self): tensor = torch.rand((1, 201, 6)) - _test_script_module(torchaudio.transforms.GriffinLim, tensor, length=1000, rand_init=False) + self._assert_consistency(T.GriffinLim(length=1000, rand_init=False), tensor) def test_AmplitudeToDB(self): spec = torch.rand((6, 201)) - _test_script_module(torchaudio.transforms.AmplitudeToDB, spec) + self._assert_consistency(T.AmplitudeToDB(), spec) def test_MelScale(self): spec_f = torch.rand((1, 6, 201)) - _test_script_module(torchaudio.transforms.MelScale, spec_f) + self._assert_consistency(T.MelScale(), spec_f) def test_MelSpectrogram(self): tensor = torch.rand((1, 1000)) - _test_script_module(torchaudio.transforms.MelSpectrogram, tensor) + self._assert_consistency(T.MelSpectrogram(), tensor) def test_MFCC(self): tensor = torch.rand((1, 1000)) - _test_script_module(torchaudio.transforms.MFCC, tensor) + self._assert_consistency(T.MFCC(), tensor) def test_Resample(self): tensor = torch.rand((2, 1000)) sample_rate = 100. sample_rate_2 = 50. - - _test_script_module(torchaudio.transforms.Resample, tensor, sample_rate, sample_rate_2) + self._assert_consistency(T.Resample(sample_rate, sample_rate_2), tensor) def test_ComplexNorm(self): tensor = torch.rand((1, 2, 201, 2)) - _test_script_module(torchaudio.transforms.ComplexNorm, tensor) + self._assert_consistency(T.ComplexNorm(), tensor) def test_MuLawEncoding(self): tensor = torch.rand((1, 10)) - _test_script_module(torchaudio.transforms.MuLawEncoding, tensor) + self._assert_consistency(T.MuLawEncoding(), tensor) def test_MuLawDecoding(self): tensor = torch.rand((1, 10)) - _test_script_module(torchaudio.transforms.MuLawDecoding, tensor) + self._assert_consistency(T.MuLawDecoding(), tensor) def test_TimeStretch(self): n_freq = 400 hop_length = 512 fixed_rate = 1.3 tensor = torch.rand((10, 2, n_freq, 10, 2)) - _test_script_module( - torchaudio.transforms.TimeStretch, - tensor, n_freq=n_freq, hop_length=hop_length, fixed_rate=fixed_rate) + self._assert_consistency( + T.TimeStretch(n_freq=n_freq, hop_length=hop_length, fixed_rate=fixed_rate), + tensor, + ) def test_Fade(self): - test_filepath = os.path.join( - common_utils.TEST_DIR_PATH, 'assets', 'steam-train-whistle-daniel_simon.wav') + test_filepath = common_utils.get_asset_path('steam-train-whistle-daniel_simon.wav') waveform, _ = torchaudio.load(test_filepath) fade_in_len = 3000 fade_out_len = 3000 - - _test_script_module(torchaudio.transforms.Fade, waveform, fade_in_len, fade_out_len) + self._assert_consistency(T.Fade(fade_in_len, fade_out_len), waveform) def test_FrequencyMasking(self): tensor = torch.rand((10, 2, 50, 10, 2)) - _test_script_module( - torchaudio.transforms.FrequencyMasking, tensor, freq_mask_param=60, iid_masks=False) + self._assert_consistency(T.FrequencyMasking(freq_mask_param=60, iid_masks=False), tensor) def test_TimeMasking(self): tensor = torch.rand((10, 2, 50, 10, 2)) - _test_script_module( - torchaudio.transforms.TimeMasking, tensor, time_mask_param=30, iid_masks=False) + self._assert_consistency(T.TimeMasking(time_mask_param=30, iid_masks=False), tensor) def test_Vol(self): - test_filepath = os.path.join( - common_utils.TEST_DIR_PATH, 'assets', 'steam-train-whistle-daniel_simon.wav') + test_filepath = common_utils.get_asset_path('steam-train-whistle-daniel_simon.wav') waveform, _ = torchaudio.load(test_filepath) - _test_script_module(torchaudio.transforms.Vol, waveform, 1.1) + self._assert_consistency(T.Vol(1.1), waveform) + + def test_SlidingWindowCmn(self): + tensor = torch.rand((1000, 10)) + self._assert_consistency(T.SlidingWindowCmn(), tensor) + + def test_Vad(self): + filepath = common_utils.get_asset_path("vad-hello-mono-32000.wav") + waveform, sample_rate = torchaudio.load(filepath) + self._assert_consistency(T.Vad(sample_rate=sample_rate), waveform) + + +class TestFunctionalCPU(_FunctionalTestMixin, unittest.TestCase): + """Test suite for Functional module on CPU""" + device = torch.device('cpu') + + +@unittest.skipIf(not torch.cuda.is_available(), 'CUDA not available') +class TestFunctionalCUDA(_FunctionalTestMixin, unittest.TestCase): + """Test suite for Functional module on GPU""" + device = torch.device('cuda') + + +class TestTransformsCPU(_TransformsTestMixin, unittest.TestCase): + """Test suite for Transforms module on CPU""" + device = torch.device('cpu') + + +@unittest.skipIf(not torch.cuda.is_available(), 'CUDA not available') +class TestTransformsCUDA(_TransformsTestMixin, unittest.TestCase): + """Test suite for Transforms module on GPU""" + device = torch.device('cuda') if __name__ == '__main__': diff --git a/test/test_transforms.py b/test/test_transforms.py index f8501e72e2..9c0313ba7c 100644 --- a/test/test_transforms.py +++ b/test/test_transforms.py @@ -1,5 +1,4 @@ import math -import os import unittest import torch @@ -7,7 +6,7 @@ import torchaudio.transforms as transforms import torchaudio.functional as F -from common_utils import AudioBackendScope, BACKENDS, create_temp_assets_dir +import common_utils class Tester(unittest.TestCase): @@ -19,10 +18,6 @@ class Tester(unittest.TestCase): waveform = (torch.cos(2 * math.pi * torch.arange(0, 4 * sample_rate).float() * freq / sample_rate)) waveform.unsqueeze_(0) # (1, 64000) waveform = (waveform * volume * 2**31).long() - # file for stereo stft test - test_dirpath, test_dir = create_temp_assets_dir() - test_filepath = os.path.join(test_dirpath, 'assets', - 'steam-train-whistle-daniel_simon.wav') def scale(self, waveform, factor=2.0**31): # scales a waveform by a factor @@ -45,7 +40,8 @@ def test_mu_law_companding(self): self.assertTrue(waveform_exp.min() >= -1. and waveform_exp.max() <= 1.) def test_AmplitudeToDB(self): - waveform, sample_rate = torchaudio.load(self.test_filepath) + filepath = common_utils.get_asset_path('steam-train-whistle-daniel_simon.wav') + waveform, sample_rate = torchaudio.load(filepath) mag_to_db_transform = transforms.AmplitudeToDB('magnitude', 80.) power_to_db_transform = transforms.AmplitudeToDB('power', 80.) @@ -53,7 +49,7 @@ def test_AmplitudeToDB(self): mag_to_db_torch = mag_to_db_transform(torch.abs(waveform)) power_to_db_torch = power_to_db_transform(torch.pow(waveform, 2)) - self.assertTrue(torch.allclose(mag_to_db_torch, power_to_db_torch)) + torch.testing.assert_allclose(mag_to_db_torch, power_to_db_torch) def test_melscale_load_save(self): specgram = torch.ones(1, 1000, 100) @@ -67,7 +63,7 @@ def test_melscale_load_save(self): fb_copy = melscale_transform_copy.fb self.assertEqual(fb_copy.size(), (1000, 128)) - self.assertTrue(torch.allclose(fb, fb_copy)) + torch.testing.assert_allclose(fb, fb_copy) def test_melspectrogram_load_save(self): waveform = self.waveform.float() @@ -83,10 +79,10 @@ def test_melspectrogram_load_save(self): fb = mel_spectrogram_transform.mel_scale.fb fb_copy = mel_spectrogram_transform_copy.mel_scale.fb - self.assertTrue(torch.allclose(window, window_copy)) + torch.testing.assert_allclose(window, window_copy) # the default for n_fft = 400 and n_mels = 128 self.assertEqual(fb_copy.size(), (201, 128)) - self.assertTrue(torch.allclose(fb, fb_copy)) + torch.testing.assert_allclose(fb, fb_copy) def test_mel2(self): top_db = 80. @@ -114,7 +110,8 @@ def test_mel2(self): self.assertTrue(mel_transform2.mel_scale.fb.sum(1).le(1.).all()) self.assertTrue(mel_transform2.mel_scale.fb.sum(1).ge(0.).all()) # check on multi-channel audio - x_stereo, sr_stereo = torchaudio.load(self.test_filepath) # (2, 278756), 44100 + filepath = common_utils.get_asset_path('steam-train-whistle-daniel_simon.wav') + x_stereo, sr_stereo = torchaudio.load(filepath) # (2, 278756), 44100 spectrogram_stereo = s2db(mel_transform(x_stereo)) # (2, 128, 1394) self.assertTrue(spectrogram_stereo.dim() == 3) self.assertTrue(spectrogram_stereo.size(0) == 2) @@ -164,7 +161,7 @@ def test_mfcc(self): self.assertTrue(torch_mfcc_norm_none.allclose(norm_check)) def test_resample_size(self): - input_path = os.path.join(self.test_dirpath, 'assets', 'sinewave.wav') + input_path = common_utils.get_asset_path('sinewave.wav') waveform, sample_rate = torchaudio.load(input_path) upsample_rate = sample_rate * 2 @@ -217,7 +214,7 @@ def test_compute_deltas_twochannel(self): transform = transforms.ComputeDeltas(win_length=3) computed = transform(specgram) assert computed.shape == expected.shape, (computed.shape, expected.shape) - assert torch.allclose(computed, expected, atol=1e-6, rtol=1e-8) + torch.testing.assert_allclose(computed, expected, atol=1e-6, rtol=1e-8) if __name__ == '__main__': diff --git a/torchaudio/__init__.py b/torchaudio/__init__.py index 2b04a2f28a..e748a34bc2 100644 --- a/torchaudio/__init__.py +++ b/torchaudio/__init__.py @@ -1,15 +1,17 @@ +import atexit import os.path +from pathlib import Path +from typing import Any, Callable, Optional, Tuple, Union import torch - +from torch import Tensor from torchaudio import ( compliance, datasets, kaldi_io, sox_effects, - transforms, + transforms ) - from torchaudio._backend import ( check_input, _audio_backend_guard, @@ -17,6 +19,7 @@ get_audio_backend, set_audio_backend, ) +from torchaudio._soundfile_backend import SignalInfo, EncodingInfo try: from .version import __version__, git_version # noqa: F401 @@ -24,27 +27,27 @@ pass -def load(filepath, - out=None, - normalization=True, - channels_first=True, - num_frames=0, - offset=0, - signalinfo=None, - encodinginfo=None, - filetype=None): +def load(filepath: Union[str, Path], + out: Optional[Tensor] = None, + normalization: Union[bool, float, Callable] = True, + channels_first: bool = True, + num_frames: int = 0, + offset: int = 0, + signalinfo: Optional[SignalInfo] = None, + encodinginfo: Optional[EncodingInfo] = None, + filetype: Optional[str] = None) -> Tuple[Tensor, int]: r"""Loads an audio file from disk into a tensor Args: - filepath (str or pathlib.Path): Path to audio file - out (torch.Tensor, optional): An output tensor to use instead of creating one. (Default: ``None``) - normalization (bool, number, or callable, optional): If boolean `True`, then output is divided by `1 << 31` + filepath (str or Path): Path to audio file + out (Tensor, optional): An output tensor to use instead of creating one. (Default: ``None``) + normalization (bool, float, or callable, optional): If boolean `True`, then output is divided by `1 << 31` (assumes signed 32-bit audio), and normalizes to `[-1, 1]`. - If `number`, then output is divided by that number - If `callable`, then the output is passed as a parameter + If `float`, then output is divided by that number + If `Callable`, then the output is passed as a parameter to the given function, then the output is divided by the result. (Default: ``True``) - channels_first (bool): Set channels first or length first in result. (Default: ``True``) + channels_first (bool, optional): Set channels first or length first in result. (Default: ``True``) num_frames (int, optional): Number of frames to load. 0 to load everything after the offset. (Default: ``0``) offset (int, optional): Number of frames from the start of the file to begin data loading. @@ -57,7 +60,7 @@ def load(filepath, automatically. (Default: ``None``) Returns: - Tuple[torch.Tensor, int]: An output tensor of size `[C x L]` or `[L x C]` where L is the number + (Tensor, int): An output tensor of size `[C x L]` or `[L x C]` where L is the number of audio frames and C is the number of channels. An integer which is the sample rate of the audio (as listed in the metadata of the file) @@ -86,15 +89,15 @@ def load(filepath, ) -def load_wav(filepath, **kwargs): +def load_wav(filepath: Union[str, Path], **kwargs: Any) -> Tuple[Tensor, int]: r""" Loads a wave file. It assumes that the wav file uses 16 bit per sample that needs normalization by shifting the input right by 16 bits. Args: - filepath (str or pathlib.Path): Path to audio file + filepath (str or Path): Path to audio file Returns: - Tuple[torch.Tensor, int]: An output tensor of size `[C x L]` or `[L x C]` where L is the number + (Tensor, int): An output tensor of size `[C x L]` or `[L x C]` where L is the number of audio frames and C is the number of channels. An integer which is the sample rate of the audio (as listed in the metadata of the file) """ @@ -102,17 +105,17 @@ def load_wav(filepath, **kwargs): return load(filepath, **kwargs) -def save(filepath, src, sample_rate, precision=16, channels_first=True): +def save(filepath: str, src: Tensor, sample_rate: int, precision: int = 16, channels_first: bool = True) -> None: r"""Convenience function for `save_encinfo`. Args: filepath (str): Path to audio file - src (torch.Tensor): An input 2D tensor of shape `[C x L]` or `[L x C]` where L is + src (Tensor): An input 2D tensor of shape `[C x L]` or `[L x C]` where L is the number of audio frames, C is the number of channels sample_rate (int): An integer which is the sample rate of the audio (as listed in the metadata of the file) - precision (int): Bit precision (Default: ``16``) - channels_first (bool): Set channels first or length first in result. ( + precision (int, optional): Bit precision (Default: ``16``) + channels_first (bool, optional): Set channels first or length first in result. ( Default: ``True``) """ @@ -122,23 +125,23 @@ def save(filepath, src, sample_rate, precision=16, channels_first=True): @_audio_backend_guard("sox") -def save_encinfo(filepath, - src, - channels_first=True, - signalinfo=None, - encodinginfo=None, - filetype=None): +def save_encinfo(filepath: str, + src: Tensor, + channels_first: bool = True, + signalinfo: Optional[SignalInfo] = None, + encodinginfo: Optional[EncodingInfo] = None, + filetype: Optional[str] = None) -> None: r"""Saves a tensor of an audio signal to disk as a standard format like mp3, wav, etc. Args: filepath (str): Path to audio file - src (torch.Tensor): An input 2D tensor of shape `[C x L]` or `[L x C]` where L is + src (Tensor): An input 2D tensor of shape `[C x L]` or `[L x C]` where L is the number of audio frames, C is the number of channels - channels_first (bool): Set channels first or length first in result. (Default: ``True``) - signalinfo (sox_signalinfo_t): A sox_signalinfo_t type, which could be helpful if the - audio type cannot be automatically determined. (Default: ``None``) + channels_first (bool, optional): Set channels first or length first in result. (Default: ``True``) + signalinfo (sox_signalinfo_t, optional): A sox_signalinfo_t type, which could be helpful if the + audio type cannot be automatically determined (Default: ``None``). encodinginfo (sox_encodinginfo_t, optional): A sox_encodinginfo_t type, which could be set if the - audio type cannot be automatically determined. (Default: ``None``) + audio type cannot be automatically determined (Default: ``None``). filetype (str, optional): A filetype or extension to be set if sox cannot determine it automatically. (Default: ``None``) @@ -165,17 +168,18 @@ def save_encinfo(filepath, "Expected format where C < 16, but found {}".format(src.size())) # sox stores the sample rate as a float, though practically sample rates are almost always integers # convert integers to floats - if not isinstance(signalinfo.rate, float): - if float(signalinfo.rate) == signalinfo.rate: - signalinfo.rate = float(signalinfo.rate) - else: - raise TypeError('Sample rate should be a float or int') - # check if the bit precision (i.e. bits per sample) is an integer - if not isinstance(signalinfo.precision, int): - if int(signalinfo.precision) == signalinfo.precision: - signalinfo.precision = int(signalinfo.precision) - else: - raise TypeError('Bit precision should be an integer') + if signalinfo: + if signalinfo.rate and not isinstance(signalinfo.rate, float): + if float(signalinfo.rate) == signalinfo.rate: + signalinfo.rate = float(signalinfo.rate) + else: + raise TypeError('Sample rate should be a float or int') + # check if the bit precision (i.e. bits per sample) is an integer + if signalinfo.precision and not isinstance(signalinfo.precision, int): + if int(signalinfo.precision) == signalinfo.precision: + signalinfo.precision = int(signalinfo.precision) + else: + raise TypeError('Bit precision should be an integer') # programs such as librosa normalize the signal, unnormalize if detected if src.min() >= -1.0 and src.max() <= 1.0: src = src * (1 << 31) @@ -193,14 +197,14 @@ def save_encinfo(filepath, _torch_sox.write_audio_file(filepath, src, signalinfo, encodinginfo, filetype) -def info(filepath): +def info(filepath: str) -> Tuple[SignalInfo, EncodingInfo]: r"""Gets metadata from an audio file without loading the signal. Args: filepath (str): Path to audio file Returns: - Tuple[sox_signalinfo_t, sox_encodinginfo_t]: A si (sox_signalinfo_t) signal + (sox_signalinfo_t, sox_encodinginfo_t): A si (sox_signalinfo_t) signal info as a python object. An ei (sox_encodinginfo_t) encoding info Example @@ -212,7 +216,7 @@ def info(filepath): @_audio_backend_guard("sox") -def sox_signalinfo_t(): +def sox_signalinfo_t() -> SignalInfo: r"""Create a sox_signalinfo_t object. This object can be used to set the sample rate, number of channels, length, bit precision and headroom multiplier primarily for effects @@ -237,7 +241,7 @@ def sox_signalinfo_t(): @_audio_backend_guard("sox") -def sox_encodinginfo_t(): +def sox_encodinginfo_t() -> EncodingInfo: r"""Create a sox_encodinginfo_t object. This object can be used to set the encoding type, bit precision, compression factor, reverse bytes, reverse nibbles, reverse bits and endianness. This can be used in an effects chain to encode the @@ -277,7 +281,7 @@ def sox_encodinginfo_t(): @_audio_backend_guard("sox") -def get_sox_encoding_t(i=None): +def get_sox_encoding_t(i: int = None) -> EncodingInfo: r"""Get enum of sox_encoding_t for sox encodings. Args: @@ -297,7 +301,7 @@ def get_sox_encoding_t(i=None): @_audio_backend_guard("sox") -def get_sox_option_t(i=2): +def get_sox_option_t(i: int = 2) -> Any: r"""Get enum of sox_option_t for sox encodinginfo options. Args: @@ -316,7 +320,7 @@ def get_sox_option_t(i=2): @_audio_backend_guard("sox") -def get_sox_bool(i=0): +def get_sox_bool(i: int = 0) -> Any: r"""Get enum of sox_bool for sox encodinginfo options. Args: @@ -335,28 +339,70 @@ def get_sox_bool(i=0): return _torch_sox.sox_bool(i) -@_audio_backend_guard("sox") -def initialize_sox(): - """Initialize sox for use with effects chains. This is not required for simple - loading. Importantly, only run `initialize_sox` once and do not shutdown - after each effect chain, but rather once you are finished with all effects chains. - """ +_SOX_INITIALIZED = False +# This variable has a micro lifecycle. (False -> True -> None) +# False: Not initialized +# True: Initialized +# None: Already shut down (should not be initialized again.) - import _torch_sox - return _torch_sox.initialize_sox() +_SOX_SUCCESS_CODE = 0 +# defined at +# https://fossies.org/dox/sox-14.4.2/sox_8h.html#a8e07e80cebeff3339265d89c387cea93a9ef2b87ec303edfe40751d9a85fadeeb @_audio_backend_guard("sox") -def shutdown_sox(): - """Showdown sox for effects chain. Not required for simple loading. Importantly, - only call once. Attempting to re-initialize sox will result in seg faults. +def initialize_sox() -> int: + """Initialize sox for use with effects chains. + + You only need to call this function once to use SoX effects chains multiple times. + It is safe to call this function multiple times as long as ``shutdown_sox`` is not yet called. + Once ``shutdown_sox`` is called, you can no longer use SoX effects and calling this function + results in `RuntimeError`. + + Note: + This function is not required for simple loading. + + Returns: + int: Code corresponding to sox_error_t enum. See + https://fossies.org/dox/sox-14.4.2/sox_8h.html#a8e07e80cebeff3339265d89c387cea93 """ + global _SOX_INITIALIZED + if _SOX_INITIALIZED is None: + raise RuntimeError('SoX effects chain has been already shut down. Can not initialize again.') + if not _SOX_INITIALIZED: + import _torch_sox + code = _torch_sox.initialize_sox() + if code == _SOX_SUCCESS_CODE: + _SOX_INITIALIZED = True + atexit.register(shutdown_sox) + return code + return _SOX_SUCCESS_CODE - import _torch_sox - return _torch_sox.shutdown_sox() + +@_audio_backend_guard("sox") +def shutdown_sox() -> int: + """Showdown sox for effects chain. + + You do not need to call this function as it will be called automatically + at the end of program execution, if ``initialize_sox`` was called. + + It is safe to call this function multiple times. + + Returns: + int: Code corresponding to sox_error_t enum. See + https://fossies.org/dox/sox-14.4.2/sox_8h.html#a8e07e80cebeff3339265d89c387cea93 + """ + global _SOX_INITIALIZED + if _SOX_INITIALIZED: + import _torch_sox + code = _torch_sox.shutdown_sox() + if code == _SOX_INITIALIZED: + _SOX_INITIALIZED = None + return code + return _SOX_SUCCESS_CODE -def _audio_normalization(signal, normalization): +def _audio_normalization(signal: Tensor, normalization: Union[bool, float, Callable]) -> None: """Audio normalization of a tensor in-place. The normalization can be a bool, a number, or a callable that takes the audio tensor as an input. SoX uses 32-bit signed integers internally, thus bool normalizes based on that assumption. diff --git a/torchaudio/_backend.py b/torchaudio/_backend.py index d95b8159ab..f5646d7970 100644 --- a/torchaudio/_backend.py +++ b/torchaudio/_backend.py @@ -1,20 +1,26 @@ from functools import wraps +from typing import Any, List, Union import platform import torch +from torch import Tensor from . import _soundfile_backend, _sox_backend -_audio_backend = "soundfile" if platform.system() == "Windows" else "sox" -_audio_backends = {"sox": _sox_backend, "soundfile": _soundfile_backend} +if platform.system() == "Windows": + _audio_backend = "soundfile" + _audio_backends = {"soundfile": _soundfile_backend} +else: + _audio_backend = "sox" + _audio_backends = {"sox": _sox_backend, "soundfile": _soundfile_backend} -def set_audio_backend(backend): +def set_audio_backend(backend: str) -> None: """ Specifies the package used to load. Args: - backend (string): Name of the backend. One of {}. + backend (str): Name of the backend. One of {}. """.format(_audio_backends.keys()) global _audio_backend if backend not in _audio_backends: @@ -24,14 +30,14 @@ def set_audio_backend(backend): _audio_backend = backend -def get_audio_backend(): +def get_audio_backend() -> str: """ Gets the name of the package used to load. """ return _audio_backend -def _get_audio_backend_module(): +def _get_audio_backend_module() -> Any: """ Gets the module backend to load. """ @@ -39,7 +45,7 @@ def _get_audio_backend_module(): return _audio_backends[backend] -def _audio_backend_guard(backends): +def _audio_backend_guard(backends: Union[str, List[str]]) -> Any: if isinstance(backends, str): backends = [backends] @@ -55,7 +61,7 @@ def wrapper(*args, **kwargs): return decorator -def check_input(src): +def check_input(src: Tensor) -> None: if not torch.is_tensor(src): raise TypeError('Expected a tensor, got %s' % type(src)) if src.is_cuda: diff --git a/torchaudio/_soundfile_backend.py b/torchaudio/_soundfile_backend.py index f3b72d071a..1a88ba5e80 100644 --- a/torchaudio/_soundfile_backend.py +++ b/torchaudio/_soundfile_backend.py @@ -1,6 +1,8 @@ import os +from typing import Any, Optional, Tuple, Union import torch +from torch import Tensor _subtype_to_precision = { 'PCM_S8': 8, @@ -12,7 +14,11 @@ class SignalInfo: - def __init__(self, channels=None, rate=None, precision=None, length=None): + def __init__(self, + channels: Optional[int] = None, + rate: Optional[float] = None, + precision: Optional[int] = None, + length: Optional[int] = None) -> None: self.channels = channels self.rate = rate self.precision = precision @@ -20,16 +26,14 @@ def __init__(self, channels=None, rate=None, precision=None, length=None): class EncodingInfo: - def __init__( - self, - encoding=None, - bits_per_sample=None, - compression=None, - reverse_bytes=None, - reverse_nibbles=None, - reverse_bits=None, - opposite_endian=None - ): + def __init__(self, + encoding: Any = None, + bits_per_sample: Optional[int] = None, + compression: Optional[float] = None, + reverse_bytes: Any = None, + reverse_nibbles: Any = None, + reverse_bits: Any = None, + opposite_endian: Optional[bool] = None) -> None: self.encoding = encoding self.bits_per_sample = bits_per_sample self.compression = compression @@ -39,24 +43,22 @@ def __init__( self.opposite_endian = opposite_endian -def check_input(src): +def check_input(src: Tensor) -> None: if not torch.is_tensor(src): raise TypeError("Expected a tensor, got %s" % type(src)) if src.is_cuda: raise TypeError("Expected a CPU based tensor, got %s" % type(src)) -def load( - filepath, - out=None, - normalization=True, - channels_first=True, - num_frames=0, - offset=0, - signalinfo=None, - encodinginfo=None, - filetype=None, -): +def load(filepath: str, + out: Optional[Tensor] = None, + normalization: Optional[bool] = True, + channels_first: Optional[bool] = True, + num_frames: int = 0, + offset: int = 0, + signalinfo: SignalInfo = None, + encodinginfo: EncodingInfo = None, + filetype: Optional[str] = None) -> Tuple[Tensor, int]: r"""See torchaudio.load""" assert out is None @@ -96,7 +98,7 @@ def load( return out, sample_rate -def save(filepath, src, sample_rate, precision=16, channels_first=True): +def save(filepath: str, src: Tensor, sample_rate: int, precision: int = 16, channels_first: bool = True) -> None: r"""See torchaudio.save""" ch_idx, len_idx = (0, 1) if channels_first else (1, 0) @@ -129,7 +131,7 @@ def save(filepath, src, sample_rate, precision=16, channels_first=True): return soundfile.write(filepath, src, sample_rate, precision) -def info(filepath): +def info(filepath: str) -> Tuple[SignalInfo, EncodingInfo]: r"""See torchaudio.info""" import soundfile diff --git a/torchaudio/_sox_backend.py b/torchaudio/_sox_backend.py index 3aa66d94d5..802bd0fe17 100644 --- a/torchaudio/_sox_backend.py +++ b/torchaudio/_sox_backend.py @@ -1,21 +1,21 @@ import os.path +from typing import Optional, Tuple import torch - +from torch import Tensor import torchaudio - - -def load( - filepath, - out=None, - normalization=True, - channels_first=True, - num_frames=0, - offset=0, - signalinfo=None, - encodinginfo=None, - filetype=None, -): +from torchaudio._soundfile_backend import SignalInfo, EncodingInfo + + +def load(filepath: str, + out: Optional[Tensor] = None, + normalization: bool = True, + channels_first: bool = True, + num_frames: int = 0, + offset: int = 0, + signalinfo: SignalInfo = None, + encodinginfo: EncodingInfo = None, + filetype: Optional[str] = None) -> Tuple[Tensor, int]: r"""See torchaudio.load""" # stringify if `pathlib.Path` (noop if already `str`) @@ -53,7 +53,7 @@ def load( return out, sample_rate -def save(filepath, src, sample_rate, precision=16, channels_first=True): +def save(filepath: str, src: Tensor, sample_rate: int, precision: int = 16, channels_first: bool = True) -> None: r"""See torchaudio.save""" si = torchaudio.sox_signalinfo_t() @@ -65,7 +65,7 @@ def save(filepath, src, sample_rate, precision=16, channels_first=True): return torchaudio.save_encinfo(filepath, src, channels_first, si) -def info(filepath): +def info(filepath: str) -> Tuple[SignalInfo, EncodingInfo]: r"""See torchaudio.info""" import _torch_sox diff --git a/torchaudio/common_utils.py b/torchaudio/common_utils.py index 2321ad26a6..28b77200a6 100644 --- a/torchaudio/common_utils.py +++ b/torchaudio/common_utils.py @@ -4,7 +4,7 @@ PY34 = sys.version_info >= (3, 4) -def _check_module_exists(name): +def _check_module_exists(name: str) -> bool: r"""Returns if a top-level module with :attr:`name` exists *without** importing it. This is generally safer than try-catch block around a `import X`. It avoids third party libraries breaking assumptions of some of diff --git a/torchaudio/datasets/commonvoice.py b/torchaudio/datasets/commonvoice.py index 7d8e57c5fc..a11b9dc1c8 100644 --- a/torchaudio/datasets/commonvoice.py +++ b/torchaudio/datasets/commonvoice.py @@ -1,9 +1,10 @@ import os - -from torch.utils.data import Dataset +from typing import List, Dict, Tuple import torchaudio from torchaudio.datasets.utils import download_url, extract_archive, unicode_csv_reader +from torch import Tensor +from torch.utils.data import Dataset # Default TSV should be one of # dev.tsv @@ -17,9 +18,72 @@ URL = "english" VERSION = "cv-corpus-4-2019-12-10" TSV = "train.tsv" - - -def load_commonvoice_item(line, header, path, folder_audio): +_CHECKSUMS = { + "https://voice-prod-bundler-ee1969a6ce8178826482b88e843c335139bd3fb4.s3.amazonaws.com/cv-corpus-3/tt.tar.gz": + None, + "https://voice-prod-bundler-ee1969a6ce8178826482b88e843c335139bd3fb4.s3.amazonaws.com/cv-corpus-3/en.tar.gz": + None, + "https://voice-prod-bundler-ee1969a6ce8178826482b88e843c335139bd3fb4.s3.amazonaws.com/cv-corpus-3/de.tar.gz": + None, + "https://voice-prod-bundler-ee1969a6ce8178826482b88e843c335139bd3fb4.s3.amazonaws.com/cv-corpus-3/fr.tar.gz": + None, + "https://voice-prod-bundler-ee1969a6ce8178826482b88e843c335139bd3fb4.s3.amazonaws.com/cv-corpus-3/cy.tar.gz": + None, + "https://voice-prod-bundler-ee1969a6ce8178826482b88e843c335139bd3fb4.s3.amazonaws.com/cv-corpus-3/br.tar.gz": + None, + "https://voice-prod-bundler-ee1969a6ce8178826482b88e843c335139bd3fb4.s3.amazonaws.com/cv-corpus-3/cv.tar.gz": + None, + "https://voice-prod-bundler-ee1969a6ce8178826482b88e843c335139bd3fb4.s3.amazonaws.com/cv-corpus-3/tr.tar.gz": + None, + "https://voice-prod-bundler-ee1969a6ce8178826482b88e843c335139bd3fb4.s3.amazonaws.com/cv-corpus-3/ky.tar.gz": + None, + "https://voice-prod-bundler-ee1969a6ce8178826482b88e843c335139bd3fb4.s3.amazonaws.com/cv-corpus-3/ga-IE.tar.gz": + None, + "https://voice-prod-bundler-ee1969a6ce8178826482b88e843c335139bd3fb4.s3.amazonaws.com/cv-corpus-3/kab.tar.gz": + None, + "https://voice-prod-bundler-ee1969a6ce8178826482b88e843c335139bd3fb4.s3.amazonaws.com/cv-corpus-3/ca.tar.gz": + None, + "https://voice-prod-bundler-ee1969a6ce8178826482b88e843c335139bd3fb4.s3.amazonaws.com/cv-corpus-3/zh-TW.tar.gz": + None, + "https://voice-prod-bundler-ee1969a6ce8178826482b88e843c335139bd3fb4.s3.amazonaws.com/cv-corpus-3/sl.tar.gz": + None, + "https://voice-prod-bundler-ee1969a6ce8178826482b88e843c335139bd3fb4.s3.amazonaws.com/cv-corpus-3/it.tar.gz": + None, + "https://voice-prod-bundler-ee1969a6ce8178826482b88e843c335139bd3fb4.s3.amazonaws.com/cv-corpus-3/nl.tar.gz": + None, + "https://voice-prod-bundler-ee1969a6ce8178826482b88e843c335139bd3fb4.s3.amazonaws.com/cv-corpus-3/cnh.tar.gz": + None, + "https://voice-prod-bundler-ee1969a6ce8178826482b88e843c335139bd3fb4.s3.amazonaws.com/cv-corpus-3/eo.tar.gz": + None, + "https://voice-prod-bundler-ee1969a6ce8178826482b88e843c335139bd3fb4.s3.amazonaws.com/cv-corpus-3/et.tar.gz": + None, + "https://voice-prod-bundler-ee1969a6ce8178826482b88e843c335139bd3fb4.s3.amazonaws.com/cv-corpus-3/fa.tar.gz": + None, + "https://voice-prod-bundler-ee1969a6ce8178826482b88e843c335139bd3fb4.s3.amazonaws.com/cv-corpus-3/eu.tar.gz": + None, + "https://voice-prod-bundler-ee1969a6ce8178826482b88e843c335139bd3fb4.s3.amazonaws.com/cv-corpus-3/es.tar.gz": + None, + "https://voice-prod-bundler-ee1969a6ce8178826482b88e843c335139bd3fb4.s3.amazonaws.com/cv-corpus-3/zh-CN.tar.gz": + None, + "https://voice-prod-bundler-ee1969a6ce8178826482b88e843c335139bd3fb4.s3.amazonaws.com/cv-corpus-3/mn.tar.gz": + None, + "https://voice-prod-bundler-ee1969a6ce8178826482b88e843c335139bd3fb4.s3.amazonaws.com/cv-corpus-3/sah.tar.gz": + None, + "https://voice-prod-bundler-ee1969a6ce8178826482b88e843c335139bd3fb4.s3.amazonaws.com/cv-corpus-3/dv.tar.gz": + None, + "https://voice-prod-bundler-ee1969a6ce8178826482b88e843c335139bd3fb4.s3.amazonaws.com/cv-corpus-3/rw.tar.gz": + None, + "https://voice-prod-bundler-ee1969a6ce8178826482b88e843c335139bd3fb4.s3.amazonaws.com/cv-corpus-3/sv-SE.tar.gz": + None, + "https://voice-prod-bundler-ee1969a6ce8178826482b88e843c335139bd3fb4.s3.amazonaws.com/cv-corpus-3/ru.tar.gz": + None +} + + +def load_commonvoice_item(line: List[str], + header: List[str], + path: str, + folder_audio: str) -> Tuple[Tensor, int, Dict[str, str]]: # Each line as the following data: # client_id, path, sentence, up_votes, down_votes, age, gender, accent @@ -47,12 +111,13 @@ class COMMONVOICE(Dataset): _ext_audio = ".mp3" _folder_audio = "clips" - def __init__(self, root, - tsv=TSV, - url=URL, - folder_in_archive=FOLDER_IN_ARCHIVE, - version=VERSION, - download=False): + def __init__(self, + root: str, + tsv: str = TSV, + url: str = URL, + folder_in_archive: str = FOLDER_IN_ARCHIVE, + version: str = VERSION, + download: bool = False) -> None: languages = { "tatar": "tt", @@ -115,8 +180,9 @@ def __init__(self, root, if download: if not os.path.isdir(self._path): if not os.path.isfile(archive): - download_url(url, root) - extract_archive(archive, self._path) + checksum = _CHECKSUMS.get(url, None) + download_url(url, root, hash_value=checksum) + extract_archive(archive) self._tsv = os.path.join(root, folder_in_archive, tsv) @@ -125,9 +191,9 @@ def __init__(self, root, self._header = next(walker) self._walker = list(walker) - def __getitem__(self, n): + def __getitem__(self, n: int) -> Tuple[Tensor, int, Dict[str, str]]: line = self._walker[n] return load_commonvoice_item(line, self._header, self._path, self._folder_audio) - def __len__(self): + def __len__(self) -> int: return len(self._walker) diff --git a/torchaudio/datasets/librispeech.py b/torchaudio/datasets/librispeech.py index 8ca8c1af38..449ab744d3 100644 --- a/torchaudio/datasets/librispeech.py +++ b/torchaudio/datasets/librispeech.py @@ -1,20 +1,39 @@ import os +from typing import Tuple import torchaudio +from torch import Tensor from torch.utils.data import Dataset from torchaudio.datasets.utils import ( download_url, extract_archive, - unicode_csv_reader, walk_files, ) URL = "train-clean-100" FOLDER_IN_ARCHIVE = "LibriSpeech" - - -def load_librispeech_item(fileid, path, ext_audio, ext_txt): - +_CHECKSUMS = { + "http://www.openslr.org/resources/12/dev-clean.tar.gz": + "76f87d090650617fca0cac8f88b9416e0ebf80350acb97b343a85fa903728ab3", + "http://www.openslr.org/resources/12/dev-other.tar.gz": + "12661c48e8c3fe1de2c1caa4c3e135193bfb1811584f11f569dd12645aa84365", + "http://www.openslr.org/resources/12/test-clean.tar.gz": + "39fde525e59672dc6d1551919b1478f724438a95aa55f874b576be21967e6c23", + "http://www.openslr.org/resources/12/test-other.tar.gz": + "d09c181bba5cf717b3dee7d4d592af11a3ee3a09e08ae025c5506f6ebe961c29", + "http://www.openslr.org/resources/12/train-clean-100.tar.gz": + "d4ddd1d5a6ab303066f14971d768ee43278a5f2a0aa43dc716b0e64ecbbbf6e2", + "http://www.openslr.org/resources/12/train-clean-360.tar.gz": + "146a56496217e96c14334a160df97fffedd6e0a04e66b9c5af0d40be3c792ecf", + "http://www.openslr.org/resources/12/train-other-500.tar.gz": + "ddb22f27f96ec163645d53215559df6aa36515f26e01dd70798188350adcb6d2" +} + + +def load_librispeech_item(fileid: str, + path: str, + ext_audio: str, + ext_txt: str) -> Tuple[Tensor, int, str, int, int, int]: speaker_id, chapter_id, utterance_id = fileid.split("-") file_text = speaker_id + "-" + chapter_id + ext_txt @@ -56,9 +75,11 @@ class LIBRISPEECH(Dataset): _ext_txt = ".trans.txt" _ext_audio = ".flac" - def __init__( - self, root, url=URL, folder_in_archive=FOLDER_IN_ARCHIVE, download=False - ): + def __init__(self, + root: str, + url: str = URL, + folder_in_archive: str = FOLDER_IN_ARCHIVE, + download: bool = False) -> None: if url in [ "dev-clean", @@ -86,7 +107,8 @@ def __init__( if download: if not os.path.isdir(self._path): if not os.path.isfile(archive): - download_url(url, root) + checksum = _CHECKSUMS.get(url, None) + download_url(url, root, hash_value=checksum) extract_archive(archive) walker = walk_files( @@ -94,9 +116,9 @@ def __init__( ) self._walker = list(walker) - def __getitem__(self, n): + def __getitem__(self, n: int) -> Tuple[Tensor, int, str, int, int, int]: fileid = self._walker[n] return load_librispeech_item(fileid, self._path, self._ext_audio, self._ext_txt) - def __len__(self): + def __len__(self) -> int: return len(self._walker) diff --git a/torchaudio/datasets/ljspeech.py b/torchaudio/datasets/ljspeech.py index f08795277a..0b4ee86acc 100644 --- a/torchaudio/datasets/ljspeech.py +++ b/torchaudio/datasets/ljspeech.py @@ -1,15 +1,21 @@ import os import csv +from typing import List, Tuple import torchaudio from torchaudio.datasets.utils import download_url, extract_archive, unicode_csv_reader +from torch import Tensor from torch.utils.data import Dataset URL = "https://data.keithito.com/data/speech/LJSpeech-1.1.tar.bz2" FOLDER_IN_ARCHIVE = "wavs" +_CHECKSUMS = { + "https://data.keithito.com/data/speech/LJSpeech-1.1.tar.bz2": + "be1a30453f28eb8dd26af4101ae40cbf2c50413b1bb21936cbcdc6fae3de8aa5" +} -def load_ljspeech_item(line, path, ext_audio): +def load_ljspeech_item(line: List[str], path: str, ext_audio: str) -> Tuple[Tensor, int, str, str]: assert len(line) == 3 fileid, transcript, normalized_transcript = line fileid_audio = fileid + ext_audio @@ -35,9 +41,11 @@ class LJSPEECH(Dataset): _ext_audio = ".wav" _ext_archive = '.tar.bz2' - def __init__( - self, root, url=URL, folder_in_archive=FOLDER_IN_ARCHIVE, download=False - ): + def __init__(self, + root: str, + url: str = URL, + folder_in_archive: str = FOLDER_IN_ARCHIVE, + download: bool = False) -> None: basename = os.path.basename(url) archive = os.path.join(root, basename) @@ -51,16 +59,17 @@ def __init__( if download: if not os.path.isdir(self._path): if not os.path.isfile(archive): - download_url(url, root) + checksum = _CHECKSUMS.get(url, None) + download_url(url, root, hash_value=checksum) extract_archive(archive) with open(self._metadata_path, "r") as metadata: walker = unicode_csv_reader(metadata, delimiter="|", quoting=csv.QUOTE_NONE) self._walker = list(walker) - def __getitem__(self, n): + def __getitem__(self, n: int) -> Tuple[Tensor, int, str, str]: line = self._walker[n] return load_ljspeech_item(line, self._path, self._ext_audio) - def __len__(self): + def __len__(self) -> int: return len(self._walker) diff --git a/torchaudio/datasets/speechcommands.py b/torchaudio/datasets/speechcommands.py index 5c67eb060b..9943d5965b 100644 --- a/torchaudio/datasets/speechcommands.py +++ b/torchaudio/datasets/speechcommands.py @@ -1,7 +1,9 @@ import os +from typing import Tuple import torchaudio from torch.utils.data import Dataset +from torch import Tensor from torchaudio.datasets.utils import ( download_url, extract_archive, @@ -12,9 +14,15 @@ URL = "speech_commands_v0.02" HASH_DIVIDER = "_nohash_" EXCEPT_FOLDER = "_background_noise_" +_CHECKSUMS = { + "https://storage.googleapis.com/download.tensorflow.org/data/speech_commands_v0.01.tar.gz": + "3cd23799cb2bbdec517f1cc028f8d43c", + "https://storage.googleapis.com/download.tensorflow.org/data/speech_commands_v0.02.tar.gz": + "6b74f3901214cb2c2934e98196829835", +} -def load_speechcommands_item(filepath, path): +def load_speechcommands_item(filepath: str, path: str) -> Tuple[Tensor, int, str, str, int]: relpath = os.path.relpath(filepath, path) label, filename = os.path.split(relpath) speaker, _ = os.path.splitext(filename) @@ -33,13 +41,11 @@ class SPEECHCOMMANDS(Dataset): waveform, sample_rate, label, speaker_id, utterance_number """ - def __init__( - self, - root, - url=URL, - folder_in_archive=FOLDER_IN_ARCHIVE, - download=False - ): + def __init__(self, + root: str, + url: str = URL, + folder_in_archive: str = FOLDER_IN_ARCHIVE, + download: bool = False) -> None: if url in [ "speech_commands_v0.01", "speech_commands_v0.02", @@ -60,16 +66,17 @@ def __init__( if download: if not os.path.isdir(self._path): if not os.path.isfile(archive): - download_url(url, root) + checksum = _CHECKSUMS.get(url, None) + download_url(url, root, hash_value=checksum, hash_type="md5") extract_archive(archive, self._path) walker = walk_files(self._path, suffix=".wav", prefix=True) walker = filter(lambda w: HASH_DIVIDER in w and EXCEPT_FOLDER not in w, walker) self._walker = list(walker) - def __getitem__(self, n): + def __getitem__(self, n: int) -> Tuple[Tensor, int, str, str, int]: fileid = self._walker[n] return load_speechcommands_item(fileid, self._path) - def __len__(self): + def __len__(self) -> int: return len(self._walker) diff --git a/torchaudio/datasets/utils.py b/torchaudio/datasets/utils.py index f7d12baa2d..2840b43471 100644 --- a/torchaudio/datasets/utils.py +++ b/torchaudio/datasets/utils.py @@ -7,20 +7,24 @@ import tarfile import threading import zipfile +from _io import TextIOWrapper from queue import Queue +from typing import Any, Iterable, List, Optional, Tuple, Union import torch import urllib +import urllib.request from torch.utils.data import Dataset from torch.utils.model_zoo import tqdm -def unicode_csv_reader(unicode_csv_data, **kwargs): +def unicode_csv_reader(unicode_csv_data: TextIOWrapper, **kwargs: Any) -> Any: r"""Since the standard csv library does not handle unicode in Python 2, we need a wrapper. Borrowed and slightly modified from the Python docs: https://docs.python.org/2/library/csv.html#csv-examples - Arguments: - unicode_csv_data: unicode csv data (see example below) + Args: + unicode_csv_data (TextIOWrapper): unicode csv data (see example below) + Examples: >>> from torchaudio.datasets.utils import unicode_csv_reader >>> import io @@ -44,7 +48,7 @@ def unicode_csv_reader(unicode_csv_data, **kwargs): yield line -def makedir_exist_ok(dirpath): +def makedir_exist_ok(dirpath: str) -> None: """ Python2 support for os.makedirs(.., exist_ok=True) """ @@ -57,14 +61,17 @@ def makedir_exist_ok(dirpath): raise -def stream_url(url, start_byte=None, block_size=32 * 1024, progress_bar=True): +def stream_url(url: str, + start_byte: Optional[int] = None, + block_size: int = 32 * 1024, + progress_bar: bool = True) -> Iterable: """Stream url by chunk Args: url (str): Url. - start_byte (Optional[int]): Start streaming at that point. - block_size (int): Size of chunks to stream. - progress_bar (bool): Display a progress bar. + start_byte (int, optional): Start streaming at that point (Default: ``None``). + block_size (int, optional): Size of chunks to stream (Default: ``32 * 1024``). + progress_bar (bool, optional): Display a progress bar (Default: ``True``). """ # If we already have the whole file, there is no need to download it again @@ -95,25 +102,23 @@ def stream_url(url, start_byte=None, block_size=32 * 1024, progress_bar=True): pbar.update(len(chunk)) -def download_url( - url, - download_folder, - filename=None, - hash_value=None, - hash_type="sha256", - progress_bar=True, - resume=False, -): +def download_url(url: str, + download_folder: str, + filename: Optional[str] = None, + hash_value: Optional[str] = None, + hash_type: str = "sha256", + progress_bar: bool = True, + resume: bool = False) -> None: """Download file to disk. Args: url (str): Url. download_folder (str): Folder to download file. - filename (str): Name of downloaded file. If None, it is inferred from the url. - hash_value (str): Hash for url. - hash_type (str): Hash type, among "sha256" and "md5". - progress_bar (bool): Display a progress bar. - resume (bool): Enable resuming download. + filename (str, optional): Name of downloaded file. If None, it is inferred from the url (Default: ``None``). + hash_value (str, optional): Hash for url (Default: ``None``). + hash_type (str, optional): Hash type, among "sha256" and "md5" (Default: ``"sha256"``). + progress_bar (bool, optional): Display a progress bar (Default: ``True``). + resume (bool, optional): Enable resuming download (Default: ``False``). """ req = urllib.request.Request(url, method="HEAD") @@ -122,10 +127,10 @@ def download_url( # Detect filename filename = filename or req_info.get_filename() or os.path.basename(url) filepath = os.path.join(download_folder, filename) - if resume and os.path.exists(filepath): mode = "ab" - local_size = os.path.getsize(filepath) + local_size: Optional[int] = os.path.getsize(filepath) + elif not resume and os.path.exists(filepath): raise RuntimeError( "{} already exists. Delete the file manually and retry.".format(filepath) @@ -157,13 +162,16 @@ def download_url( ) -def validate_file(file_obj, hash_value, hash_type="sha256"): +def validate_file(file_obj: Any, hash_value: str, hash_type: str = "sha256") -> bool: """Validate a given file object with its hash. Args: file_obj: File object to read from. hash_value (str): Hash for url. - hash_type (str): Hash type, among "sha256" and "md5". + hash_type (str, optional): Hash type, among "sha256" and "md5" (Default: ``"sha256"``). + + Returns: + bool: return True if its a valid file, else False. """ if hash_type == "sha256": @@ -183,14 +191,16 @@ def validate_file(file_obj, hash_value, hash_type="sha256"): return hash_func.hexdigest() == hash_value -def extract_archive(from_path, to_path=None, overwrite=False): +def extract_archive(from_path: str, to_path: Optional[str] = None, overwrite: bool = False) -> List[str]: """Extract archive. - Arguments: - from_path: the path of the archive. - to_path: the root path of the extraced files (directory of from_path) - overwrite: overwrite existing files (False) + Args: + from_path (str): the path of the archive. + to_path (str, optional): the root path of the extraced files (directory of from_path) (Default: ``None``) + overwrite (bool, optional): overwrite existing files (Default: ``False``) + Returns: - List of paths to extracted files even if not overwritten. + list: List of paths to extracted files even if not overwritten. + Examples: >>> url = 'http://www.quest.dcs.shef.ac.uk/wmt16_files_mmt/validation.tar.gz' >>> from_path = './validation.tar.gz' @@ -206,7 +216,7 @@ def extract_archive(from_path, to_path=None, overwrite=False): with tarfile.open(from_path, "r") as tar: logging.info("Opened tar file {}.".format(from_path)) files = [] - for file_ in tar: + for file_ in tar: # type: Any file_path = os.path.join(to_path, file_.name) if file_.isfile(): files.append(file_path) @@ -237,7 +247,10 @@ def extract_archive(from_path, to_path=None, overwrite=False): raise NotImplementedError("We currently only support tar.gz, tgz, and zip achives.") -def walk_files(root, suffix, prefix=False, remove_suffix=False): +def walk_files(root: str, + suffix: Union[str, Tuple[str]], + prefix: bool = False, + remove_suffix: bool = False) -> Iterable[str]: """List recursively all files ending with a suffix at a given root Args: root (str): Path to directory whose folders need to be listed @@ -269,14 +282,14 @@ class _DiskCache(Dataset): Wrap a dataset so that, whenever a new item is returned, it is saved to disk. """ - def __init__(self, dataset, location=".cached"): + def __init__(self, dataset: Dataset, location: str = ".cached") -> None: self.dataset = dataset self.location = location self._id = id(self) - self._cache = [None] * len(dataset) + self._cache: List = [None] * len(dataset) - def __getitem__(self, n): + def __getitem__(self, n: int) -> Any: if self._cache[n]: f = self._cache[n] return torch.load(f) @@ -291,11 +304,11 @@ def __getitem__(self, n): return item - def __len__(self): + def __len__(self) -> int: return len(self.dataset) -def diskcache_iterator(dataset, location=".cached"): +def diskcache_iterator(dataset: Dataset, location: str = ".cached") -> Dataset: return _DiskCache(dataset, location) @@ -311,31 +324,31 @@ class _ThreadedIterator(threading.Thread): class _End: pass - def __init__(self, generator, maxsize): + def __init__(self, generator: Iterable, maxsize: int) -> None: threading.Thread.__init__(self) - self.queue = Queue(maxsize) + self.queue: Queue = Queue(maxsize) self.generator = generator self.daemon = True self.start() - def run(self): + def run(self) -> None: for item in self.generator: self.queue.put(item) self.queue.put(self._End) - def __iter__(self): + def __iter__(self) -> Any: return self - def __next__(self): + def __next__(self) -> Any: next_item = self.queue.get() if next_item == self._End: raise StopIteration return next_item # Required for Python 2.7 compatibility - def next(self): + def next(self) -> Any: return self.__next__() -def bg_iterator(iterable, maxsize): +def bg_iterator(iterable: Iterable, maxsize: int) -> Any: return _ThreadedIterator(iterable, maxsize=maxsize) diff --git a/torchaudio/datasets/vctk.py b/torchaudio/datasets/vctk.py index 87f51d68a0..c84373713d 100644 --- a/torchaudio/datasets/vctk.py +++ b/torchaudio/datasets/vctk.py @@ -1,17 +1,31 @@ import os import warnings +from typing import Any, Tuple import torchaudio +from torch import Tensor from torch.utils.data import Dataset -from torchaudio.datasets.utils import download_url, extract_archive, walk_files +from torchaudio.datasets.utils import ( + download_url, + extract_archive, + walk_files +) URL = "http://homepages.inf.ed.ac.uk/jyamagis/release/VCTK-Corpus.tar.gz" FOLDER_IN_ARCHIVE = "VCTK-Corpus" - - -def load_vctk_item( - fileid, path, ext_audio, ext_txt, folder_audio, folder_txt, downsample=False -): +_CHECKSUMS = { + "http://homepages.inf.ed.ac.uk/jyamagis/release/VCTK-Corpus.tar.gz": + "45e8dede780278ef5541fde0b82ac292" +} + + +def load_vctk_item(fileid: str, + path: str, + ext_audio: str, + ext_txt: str, + folder_audio: str, + folder_txt: str, + downsample: bool = False) -> Tuple[Tensor, int, str, str, str]: speaker_id, utterance_id = fileid.split("_") # Read text @@ -50,21 +64,19 @@ class VCTK(Dataset): _ext_audio = ".wav" _except_folder = "p315" - def __init__( - self, - root, - url=URL, - folder_in_archive=FOLDER_IN_ARCHIVE, - download=False, - downsample=False, - transform=None, - target_transform=None, - ): + def __init__(self, + root: str, + url: str = URL, + folder_in_archive: str = FOLDER_IN_ARCHIVE, + download: bool = False, + downsample: bool = False, + transform: Any = None, + target_transform: Any = None) -> None: if downsample: warnings.warn( "In the next version, transforms will not be part of the dataset. " - "Please use `downsample=False` to enable this behavior now, ", + "Please use `downsample=False` to enable this behavior now, " "and suppress this warning." ) @@ -86,7 +98,8 @@ def __init__( if download: if not os.path.isdir(self._path): if not os.path.isfile(archive): - download_url(url, root) + checksum = _CHECKSUMS.get(url, None) + download_url(url, root, hash_value=checksum, hash_type="md5") extract_archive(archive) if not os.path.isdir(self._path): @@ -100,7 +113,7 @@ def __init__( walker = filter(lambda w: self._except_folder not in w, walker) self._walker = list(walker) - def __getitem__(self, n): + def __getitem__(self, n: int) -> Tuple[Tensor, int, str, str, str]: fileid = self._walker[n] item = load_vctk_item( fileid, @@ -121,5 +134,5 @@ def __getitem__(self, n): utterance = self.target_transform(utterance) return waveform, sample_rate, utterance, speaker_id, utterance_id - def __len__(self): + def __len__(self) -> int: return len(self._walker) diff --git a/torchaudio/datasets/yesno.py b/torchaudio/datasets/yesno.py index 7d0fe58f4c..e45b157c35 100644 --- a/torchaudio/datasets/yesno.py +++ b/torchaudio/datasets/yesno.py @@ -1,15 +1,25 @@ import os import warnings +from typing import Any, List, Tuple import torchaudio +from torch import Tensor from torch.utils.data import Dataset -from torchaudio.datasets.utils import download_url, extract_archive, walk_files +from torchaudio.datasets.utils import ( + download_url, + extract_archive, + walk_files +) URL = "http://www.openslr.org/resources/1/waves_yesno.tar.gz" FOLDER_IN_ARCHIVE = "waves_yesno" +_CHECKSUMS = { + "http://www.openslr.org/resources/1/waves_yesno.tar.gz": + "962ff6e904d2df1126132ecec6978786" +} -def load_yesno_item(fileid, path, ext_audio): +def load_yesno_item(fileid: str, path: str, ext_audio: str) -> Tuple[Tensor, int, List[int]]: # Read label labels = [int(c) for c in fileid.split("_")] @@ -28,15 +38,13 @@ class YESNO(Dataset): _ext_audio = ".wav" - def __init__( - self, - root, - url=URL, - folder_in_archive=FOLDER_IN_ARCHIVE, - download=False, - transform=None, - target_transform=None, - ): + def __init__(self, + root: str, + url: str = URL, + folder_in_archive: str = FOLDER_IN_ARCHIVE, + download: bool = False, + transform: Any = None, + target_transform: Any = None) -> None: if transform is not None or target_transform is not None: warnings.warn( @@ -55,7 +63,8 @@ def __init__( if download: if not os.path.isdir(self._path): if not os.path.isfile(archive): - download_url(url, root) + checksum = _CHECKSUMS.get(url, None) + download_url(url, root, hash_value=checksum, hash_type="md5") extract_archive(archive) if not os.path.isdir(self._path): @@ -68,7 +77,7 @@ def __init__( ) self._walker = list(walker) - def __getitem__(self, n): + def __getitem__(self, n: int) -> Tuple[Tensor, int, List[int]]: fileid = self._walker[n] item = load_yesno_item(fileid, self._path, self._ext_audio) @@ -82,5 +91,5 @@ def __getitem__(self, n): labels = self.target_transform(labels) return waveform, sample_rate, labels - def __len__(self): + def __len__(self) -> int: return len(self._walker) diff --git a/torchaudio/functional.py b/torchaudio/functional.py index 282470fb4c..cb5156596d 100644 --- a/torchaudio/functional.py +++ b/torchaudio/functional.py @@ -31,37 +31,16 @@ "deemph_biquad", "riaa_biquad", "biquad", + "contrast", + "dcshift", + "overdrive", 'mask_along_axis', - 'mask_along_axis_iid' + 'mask_along_axis_iid', + 'sliding_window_cmn', + 'vad', ] -# TODO: remove this once https://github.com/pytorch/pytorch/issues/21478 gets solved -@torch.jit.ignore -def _stft( - waveform: Tensor, - n_fft: int, - hop_length: Optional[int], - win_length: Optional[int], - window: Optional[Tensor], - center: bool, - pad_mode: str, - normalized: bool, - onesided: bool -) -> Tensor: - return torch.stft( - waveform, - n_fft, - hop_length, - win_length, - window, - center, - pad_mode, - normalized, - onesided, - ) - - def istft( stft_matrix: Tensor, n_fft: int, @@ -265,7 +244,7 @@ def spectrogram( waveform = waveform.view(-1, shape[-1]) # default values are consistent with librosa.core.spectrum._spectrogram - spec_f = _stft( + spec_f = torch.stft( waveform, n_fft, hop_length, win_length, window, True, "reflect", False, True ) @@ -365,8 +344,8 @@ def griffinlim( length=length).float() # Rebuild the spectrogram - rebuilt = _stft(inverse, n_fft, hop_length, win_length, window, - True, 'reflect', False, True) + rebuilt = torch.stft(inverse, n_fft, hop_length, win_length, window, + True, 'reflect', False, True) # Update our phase estimates angles = rebuilt - tprev.mul_(momentum / (1 + momentum)) @@ -743,11 +722,11 @@ def lfilter( # (n_order, ) matmul (n_channel, n_order, n_sample) -> (n_channel, n_sample) input_signal_windows = torch.matmul(b_coeffs_flipped, torch.take(padded_waveform, window_idxs)) + input_signal_windows.div_(a_coeffs[0]) + a_coeffs_flipped.div_(a_coeffs[0]) for i_sample, o0 in enumerate(input_signal_windows.t()): windowed_output_signal = padded_output_waveform[:, i_sample:(i_sample + n_order)] - o0.sub_(torch.mv(windowed_output_signal, a_coeffs_flipped)) - o0.div_(a_coeffs[0]) - + o0.addmv_(windowed_output_signal, a_coeffs_flipped, alpha=-1) padded_output_waveform[:, i_sample + n_order - 1] = o0 output = torch.clamp(padded_output_waveform[:, (n_order - 1):], min=-1., max=1.) @@ -1186,6 +1165,137 @@ def riaa_biquad( return biquad(waveform, b0, b1, b2, a0, a1, a2) +def contrast( + waveform: Tensor, + enhancement_amount: float = 75. +) -> Tensor: + r"""Apply contrast effect. Similar to SoX implementation. + Comparable with compression, this effect modifies an audio signal to make it sound louder + + Args: + waveform (Tensor): audio waveform of dimension of `(..., time)` + enhancement_amount (float): controls the amount of the enhancement + Allowed range of values for enhancement_amount : 0-100 + Note that enhancement_amount = 0 still gives a significant contrast enhancement + + Returns: + Tensor: Waveform of dimension of `(..., time)` + + References: + http://sox.sourceforge.net/sox.html + """ + + if not 0 <= enhancement_amount <= 100: + raise ValueError("Allowed range of values for enhancement_amount : 0-100") + + contrast = enhancement_amount / 750. + + temp1 = waveform * (math.pi / 2) + temp2 = contrast * torch.sin(temp1 * 4) + output_waveform = torch.sin(temp1 + temp2) + + return output_waveform + + +def dcshift( + waveform: Tensor, + shift: float, + limiter_gain: Optional[float] = None +) -> Tensor: + r"""Apply a DC shift to the audio. Similar to SoX implementation. + This can be useful to remove a DC offset + (caused perhaps by a hardware problem in the recording chain) from the audio + + Args: + waveform (Tensor): audio waveform of dimension of `(..., time)` + shift (float): indicates the amount to shift the audio + Allowed range of values for shift : -2.0 to +2.0 + limiter_gain (float): It is used only on peaks to prevent clipping + It should have a value much less than 1 (e.g. 0.05 or 0.02) + + Returns: + Tensor: Waveform of dimension of `(..., time)` + + References: + http://sox.sourceforge.net/sox.html + """ + output_waveform = waveform + limiter_threshold = 0. + + if limiter_gain is not None: + limiter_threshold = 1.0 - (abs(shift) - limiter_gain) + + if limiter_gain is not None and shift > 0: + mask = waveform > limiter_threshold + temp = (waveform[mask] - limiter_threshold) * limiter_gain / (1 - limiter_threshold) + output_waveform[mask] = (temp + limiter_threshold + shift).clamp(max=limiter_threshold) + output_waveform[~mask] = (waveform[~mask] + shift).clamp(min=-1, max=1) + elif limiter_gain is not None and shift < 0: + mask = waveform < -limiter_threshold + temp = (waveform[mask] + limiter_threshold) * limiter_gain / (1 - limiter_threshold) + output_waveform[mask] = (temp - limiter_threshold + shift).clamp(min=-limiter_threshold) + output_waveform[~mask] = (waveform[~mask] + shift).clamp(min=-1, max=1) + else: + output_waveform = (waveform + shift).clamp(min=-1, max=1) + + return output_waveform + + +def overdrive( + waveform: Tensor, + gain: float = 20, + colour: float = 20 +) -> Tensor: + r"""Apply a overdrive effect to the audio. Similar to SoX implementation. + This effect applies a non linear distortion to the audio signal. + + Args: + waveform (Tensor): audio waveform of dimension of `(..., time)` + gain (float): desired gain at the boost (or attenuation) in dB + Allowed range of values are 0 to 100 + colour (float): controls the amount of even harmonic content in the over-driven output + Allowed range of values are 0 to 100 + + Returns: + Tensor: Waveform of dimension of `(..., time)` + + References: + http://sox.sourceforge.net/sox.html + """ + actual_shape = waveform.shape + device, dtype = waveform.device, waveform.dtype + + # convert to 2D (..,time) + waveform = waveform.view(-1, actual_shape[-1]) + + gain = _dB2Linear(gain) + colour = colour / 200 + last_in = torch.zeros(waveform.shape[:-1], dtype=dtype, device=device) + last_out = torch.zeros(waveform.shape[:-1], dtype=dtype, device=device) + + temp = waveform * gain + colour + + mask1 = temp < -1 + temp[mask1] = torch.tensor(-2.0 / 3.0, dtype=dtype, device=device) + # Wrapping the constant with Tensor is required for Torchscript + + mask2 = temp > 1 + temp[mask2] = torch.tensor(2.0 / 3.0, dtype=dtype, device=device) + + mask3 = (~mask1 & ~mask2) + temp[mask3] = temp[mask3] - (temp[mask3]**3) * (1. / 3) + + output_waveform = torch.zeros_like(waveform, dtype=dtype, device=device) + + # TODO: Implement a torch CPP extension + for i in range(waveform.shape[-1]): + last_out = temp[:, i] - last_in + 0.995 * last_out + last_in = temp[:, i] + output_waveform[:, i] = waveform[:, i] * 0.5 + last_out * 0.75 + + return output_waveform.clamp(min=-1, max=1).view(actual_shape) + + def mask_along_axis_iid( specgrams: Tensor, mask_param: int, @@ -1210,13 +1320,16 @@ def mask_along_axis_iid( if axis != 2 and axis != 3: raise ValueError('Only Frequency and Time masking are supported') - value = torch.rand(specgrams.shape[:2]) * mask_param - min_value = torch.rand(specgrams.shape[:2]) * (specgrams.size(axis) - value) + device = specgrams.device + dtype = specgrams.dtype + + value = torch.rand(specgrams.shape[:2], device=device, dtype=dtype) * mask_param + min_value = torch.rand(specgrams.shape[:2], device=device, dtype=dtype) * (specgrams.size(axis) - value) # Create broadcastable mask - mask_start = (min_value.long())[..., None, None].float() - mask_end = (min_value.long() + value.long())[..., None, None].float() - mask = torch.arange(0, specgrams.size(axis)).float() + mask_start = min_value[..., None, None] + mask_end = (min_value + value)[..., None, None] + mask = torch.arange(0, specgrams.size(axis), device=device, dtype=dtype) # Per batch example masking specgrams = specgrams.transpose(axis, -1) @@ -1298,6 +1411,8 @@ def compute_deltas( >>> delta = compute_deltas(specgram) >>> delta2 = compute_deltas(delta) """ + device = specgram.device + dtype = specgram.dtype # pack batch shape = specgram.size() @@ -1312,7 +1427,7 @@ def compute_deltas( specgram = torch.nn.functional.pad(specgram, (n, n), mode=mode) - kernel = (torch.arange(-n, n + 1, 1, device=specgram.device, dtype=specgram.dtype).repeat(specgram.shape[1], 1, 1)) + kernel = torch.arange(-n, n + 1, 1, device=device, dtype=dtype).repeat(specgram.shape[1], 1, 1) output = torch.nn.functional.conv1d(specgram, kernel, groups=specgram.shape[1]) / denom @@ -1431,7 +1546,7 @@ def _apply_probability_distribution( signal_scaled_dis = signal_scaled + gaussian else: # dtype needed for https://github.com/pytorch/pytorch/issues/32358 - TPDF = torch.bartlett_window(time_size + 1, dtype=torch.float) + TPDF = torch.bartlett_window(time_size + 1, dtype=signal_scaled.dtype, device=signal_scaled.device) TPDF = TPDF.repeat((channel_size + 1), 1) signal_scaled_dis = signal_scaled + TPDF @@ -1631,3 +1746,390 @@ def detect_pitch_frequency( freq = freq.view(shape[:-1] + list(freq.shape[-1:])) return freq + + +def sliding_window_cmn( + waveform: Tensor, + cmn_window: int = 600, + min_cmn_window: int = 100, + center: bool = False, + norm_vars: bool = False, +) -> Tensor: + r""" + Apply sliding-window cepstral mean (and optionally variance) normalization per utterance. + + Args: + waveform (Tensor): Tensor of audio of dimension (..., freq, time) + cmn_window (int, optional): Window in frames for running average CMN computation (int, default = 600) + min_cmn_window (int, optional): Minimum CMN window used at start of decoding (adds latency only at start). + Only applicable if center == false, ignored if center==true (int, default = 100) + center (bool, optional): If true, use a window centered on the current frame + (to the extent possible, modulo end effects). If false, window is to the left. (bool, default = false) + norm_vars (bool, optional): If true, normalize variance to one. (bool, default = false) + + Returns: + Tensor: Tensor of freq of dimension (..., frame) + """ + input_shape = waveform.shape + num_frames, num_feats = input_shape[-2:] + waveform = waveform.view(-1, num_frames, num_feats) + num_channels = waveform.shape[0] + + dtype = waveform.dtype + device = waveform.device + last_window_start = last_window_end = -1 + cur_sum = torch.zeros(num_channels, num_feats, dtype=dtype, device=device) + cur_sumsq = torch.zeros(num_channels, num_feats, dtype=dtype, device=device) + cmn_waveform = torch.zeros( + num_channels, num_frames, num_feats, dtype=dtype, device=device) + for t in range(num_frames): + window_start = 0 + window_end = 0 + if center: + window_start = t - cmn_window // 2 + window_end = window_start + cmn_window + else: + window_start = t - cmn_window + window_end = t + 1 + if window_start < 0: + window_end -= window_start + window_start = 0 + if not center: + if window_end > t: + window_end = max(t + 1, min_cmn_window) + if window_end > num_frames: + window_start -= (window_end - num_frames) + window_end = num_frames + if window_start < 0: + window_start = 0 + if last_window_start == -1: + input_part = waveform[:, window_start: window_end - window_start, :] + cur_sum += torch.sum(input_part, 1) + if norm_vars: + cur_sumsq += torch.cumsum(input_part ** 2, 1)[:, -1, :] + else: + if window_start > last_window_start: + frame_to_remove = waveform[:, last_window_start, :] + cur_sum -= frame_to_remove + if norm_vars: + cur_sumsq -= (frame_to_remove ** 2) + if window_end > last_window_end: + frame_to_add = waveform[:, last_window_end, :] + cur_sum += frame_to_add + if norm_vars: + cur_sumsq += (frame_to_add ** 2) + window_frames = window_end - window_start + last_window_start = window_start + last_window_end = window_end + cmn_waveform[:, t, :] = waveform[:, t, :] - cur_sum / window_frames + if norm_vars: + if window_frames == 1: + cmn_waveform[:, t, :] = torch.zeros( + num_channels, num_feats, dtype=dtype, device=device) + else: + variance = cur_sumsq + variance = variance / window_frames + variance -= ((cur_sum ** 2) / (window_frames ** 2)) + variance = torch.pow(variance, -0.5) + cmn_waveform[:, t, :] *= variance + + cmn_waveform = cmn_waveform.view(input_shape[:-2] + (num_frames, num_feats)) + if len(input_shape) == 2: + cmn_waveform = cmn_waveform.squeeze(0) + return cmn_waveform + + +def _measure( + measure_len_ws: int, + samples: Tensor, + spectrum: Tensor, + noise_spectrum: Tensor, + spectrum_window: Tensor, + spectrum_start: int, + spectrum_end: int, + cepstrum_window: Tensor, + cepstrum_start: int, + cepstrum_end: int, + noise_reduction_amount: float, + measure_smooth_time_mult: float, + noise_up_time_mult: float, + noise_down_time_mult: float, + index_ns: int, + boot_count: int +) -> float: + + assert spectrum.size()[-1] == noise_spectrum.size()[-1] + + samplesLen_ns = samples.size()[-1] + dft_len_ws = spectrum.size()[-1] + + dftBuf = torch.zeros(dft_len_ws) + + _index_ns = torch.tensor([index_ns] + [ + (index_ns + i) % samplesLen_ns + for i in range(1, measure_len_ws) + ]) + dftBuf[:measure_len_ws] = \ + samples[_index_ns] * spectrum_window[:measure_len_ws] + + # memset(c->dftBuf + i, 0, (p->dft_len_ws - i) * sizeof(*c->dftBuf)); + dftBuf[measure_len_ws:dft_len_ws].zero_() + + # lsx_safe_rdft((int)p->dft_len_ws, 1, c->dftBuf); + _dftBuf = torch.rfft(dftBuf, 1) + + # memset(c->dftBuf, 0, p->spectrum_start * sizeof(*c->dftBuf)); + _dftBuf[:spectrum_start].zero_() + + mult: float = boot_count / (1. + boot_count) \ + if boot_count >= 0 \ + else measure_smooth_time_mult + + _d = complex_norm(_dftBuf[spectrum_start:spectrum_end]) + spectrum[spectrum_start:spectrum_end].mul_(mult).add_(_d * (1 - mult)) + _d = spectrum[spectrum_start:spectrum_end] ** 2 + + _zeros = torch.zeros(spectrum_end - spectrum_start) + _mult = _zeros \ + if boot_count >= 0 \ + else torch.where( + _d > noise_spectrum[spectrum_start:spectrum_end], + torch.tensor(noise_up_time_mult), # if + torch.tensor(noise_down_time_mult) # else + ) + + noise_spectrum[spectrum_start:spectrum_end].mul_(_mult).add_(_d * (1 - _mult)) + _d = torch.sqrt( + torch.max( + _zeros, + _d - noise_reduction_amount * noise_spectrum[spectrum_start:spectrum_end])) + + _cepstrum_Buf: Tensor = torch.zeros(dft_len_ws >> 1) + _cepstrum_Buf[spectrum_start:spectrum_end] = _d * cepstrum_window + _cepstrum_Buf[spectrum_end:dft_len_ws >> 1].zero_() + + # lsx_safe_rdft((int)p->dft_len_ws >> 1, 1, c->dftBuf); + _cepstrum_Buf = torch.rfft(_cepstrum_Buf, 1) + + result: float = float(torch.sum( + complex_norm( + _cepstrum_Buf[cepstrum_start:cepstrum_end], + power=2.0))) + result = \ + math.log(result / (cepstrum_end - cepstrum_start)) \ + if result > 0 \ + else -math.inf + return max(0, 21 + result) + + +def vad( + waveform: Tensor, + sample_rate: int, + trigger_level: float = 7.0, + trigger_time: float = 0.25, + search_time: float = 1.0, + allowed_gap: float = 0.25, + pre_trigger_time: float = 0.0, + # Fine-tuning parameters + boot_time: float = .35, + noise_up_time: float = .1, + noise_down_time: float = .01, + noise_reduction_amount: float = 1.35, + measure_freq: float = 20.0, + measure_duration: Optional[float] = None, + measure_smooth_time: float = .4, + hp_filter_freq: float = 50., + lp_filter_freq: float = 6000., + hp_lifter_freq: float = 150., + lp_lifter_freq: float = 2000., +) -> Tensor: + r"""Voice Activity Detector. Similar to SoX implementation. + Attempts to trim silence and quiet background sounds from the ends of recordings of speech. + The algorithm currently uses a simple cepstral power measurement to detect voice, + so may be fooled by other things, especially music. + + The effect can trim only from the front of the audio, + so in order to trim from the back, the reverse effect must also be used. + + Args: + waveform (Tensor): Tensor of audio of dimension `(..., time)` + sample_rate (int): Sample rate of audio signal. + trigger_level (float, optional): The measurement level used to trigger activity detection. + This may need to be cahnged depending on the noise level, signal level, + and other characteristics of the input audio. (Default: 7.0) + trigger_time (float, optional): The time constant (in seconds) + used to help ignore short bursts of sound. (Default: 0.25) + search_time (float, optional): The amount of audio (in seconds) + to search for quieter/shorter bursts of audio to include prior + to the detected trigger point. (Default: 1.0) + allowed_gap (float, optional): The allowed gap (in seconds) between + quiteter/shorter bursts of audio to include prior + to the detected trigger point. (Default: 0.25) + pre_trigger_time (float, optional): The amount of audio (in seconds) to preserve + before the trigger point and any found quieter/shorter bursts. (Default: 0.0) + boot_time (float, optional) The algorithm (internally) uses adaptive noise + estimation/reduction in order to detect the start of the wanted audio. + This option sets the time for the initial noise estimate. (Default: 0.35) + noise_up_time (float, optional) Time constant used by the adaptive noise estimator + for when the noise level is increasing. (Default: 0.1) + noise_down_time (float, optional) Time constant used by the adaptive noise estimator + for when the noise level is decreasing. (Default: 0.01) + noise_reduction_amount (float, optional) Amount of noise reduction to use in + the detection algorithm (e.g. 0, 0.5, ...). (Default: 1.35) + measure_freq (float, optional) Frequency of the algorithmโ€™s + processing/measurements. (Default: 20.0) + measure_duration: (float, optional) Measurement duration. + (Default: Twice the measurement period; i.e. with overlap.) + measure_smooth_time (float, optional) Time constant used to smooth + spectral measurements. (Default: 0.4) + hp_filter_freq (float, optional) "Brick-wall" frequency of high-pass filter applied + at the input to the detector algorithm. (Default: 50.0) + lp_filter_freq (float, optional) "Brick-wall" frequency of low-pass filter applied + at the input to the detector algorithm. (Default: 6000.0) + hp_lifter_freq (float, optional) "Brick-wall" frequency of high-pass lifter used + in the detector algorithm. (Default: 150.0) + lp_lifter_freq (float, optional) "Brick-wall" frequency of low-pass lifter used + in the detector algorithm. (Default: 2000.0) + + Returns: + Tensor: Tensor of audio of dimension (..., time). + + References: + http://sox.sourceforge.net/sox.html + """ + + measure_duration: float = 2.0 / measure_freq \ + if measure_duration is None \ + else measure_duration + + measure_len_ws = int(sample_rate * measure_duration + .5) + measure_len_ns = measure_len_ws + # for (dft_len_ws = 16; dft_len_ws < measure_len_ws; dft_len_ws <<= 1); + dft_len_ws = 16 + while (dft_len_ws < measure_len_ws): + dft_len_ws *= 2 + + measure_period_ns = int(sample_rate / measure_freq + .5) + measures_len = math.ceil(search_time * measure_freq) + search_pre_trigger_len_ns = measures_len * measure_period_ns + gap_len = int(allowed_gap * measure_freq + .5) + + fixed_pre_trigger_len_ns = int(pre_trigger_time * sample_rate + .5) + samplesLen_ns = fixed_pre_trigger_len_ns + search_pre_trigger_len_ns + measure_len_ns + + spectrum_window = torch.zeros(measure_len_ws) + for i in range(measure_len_ws): + # sox.h:741 define SOX_SAMPLE_MIN (sox_sample_t)SOX_INT_MIN(32) + spectrum_window[i] = 2. / math.sqrt(float(measure_len_ws)) + # lsx_apply_hann(spectrum_window, (int)measure_len_ws); + spectrum_window *= torch.hann_window(measure_len_ws, dtype=torch.float) + + spectrum_start: int = int(hp_filter_freq / sample_rate * dft_len_ws + .5) + spectrum_start: int = max(spectrum_start, 1) + spectrum_end: int = int(lp_filter_freq / sample_rate * dft_len_ws + .5) + spectrum_end: int = min(spectrum_end, dft_len_ws // 2) + + cepstrum_window = torch.zeros(spectrum_end - spectrum_start) + for i in range(spectrum_end - spectrum_start): + cepstrum_window[i] = 2. / math.sqrt(float(spectrum_end) - spectrum_start) + # lsx_apply_hann(cepstrum_window,(int)(spectrum_end - spectrum_start)); + cepstrum_window *= torch.hann_window(spectrum_end - spectrum_start, dtype=torch.float) + + cepstrum_start = math.ceil(sample_rate * .5 / lp_lifter_freq) + cepstrum_end = math.floor(sample_rate * .5 / hp_lifter_freq) + cepstrum_end = min(cepstrum_end, dft_len_ws // 4) + + assert cepstrum_end > cepstrum_start + + noise_up_time_mult = math.exp(-1. / (noise_up_time * measure_freq)) + noise_down_time_mult = math.exp(-1. / (noise_down_time * measure_freq)) + measure_smooth_time_mult = math.exp(-1. / (measure_smooth_time * measure_freq)) + trigger_meas_time_mult = math.exp(-1. / (trigger_time * measure_freq)) + + boot_count_max = int(boot_time * measure_freq - .5) + measure_timer_ns = measure_len_ns + boot_count = measures_index = flushedLen_ns = samplesIndex_ns = 0 + + # pack batch + shape = waveform.size() + waveform = waveform.view(-1, shape[-1]) + + n_channels, ilen = waveform.size() + + mean_meas = torch.zeros(n_channels) + samples = torch.zeros(n_channels, samplesLen_ns) + spectrum = torch.zeros(n_channels, dft_len_ws) + noise_spectrum = torch.zeros(n_channels, dft_len_ws) + measures = torch.zeros(n_channels, measures_len) + + has_triggered: bool = False + num_measures_to_flush: int = 0 + pos: int = 0 + + while (pos < ilen and not has_triggered): + measure_timer_ns -= 1 + for i in range(n_channels): + samples[i, samplesIndex_ns] = waveform[i, pos] + # if (!p->measure_timer_ns) { + if (measure_timer_ns == 0): + index_ns: int = \ + (samplesIndex_ns + samplesLen_ns - measure_len_ns) % samplesLen_ns + meas: float = _measure( + measure_len_ws=measure_len_ws, + samples=samples[i], + spectrum=spectrum[i], + noise_spectrum=noise_spectrum[i], + spectrum_window=spectrum_window, + spectrum_start=spectrum_start, + spectrum_end=spectrum_end, + cepstrum_window=cepstrum_window, + cepstrum_start=cepstrum_start, + cepstrum_end=cepstrum_end, + noise_reduction_amount=noise_reduction_amount, + measure_smooth_time_mult=measure_smooth_time_mult, + noise_up_time_mult=noise_up_time_mult, + noise_down_time_mult=noise_down_time_mult, + index_ns=index_ns, + boot_count=boot_count) + measures[i, measures_index] = meas + mean_meas[i] = mean_meas[i] * trigger_meas_time_mult + meas * (1. - trigger_meas_time_mult) + + has_triggered = has_triggered or (mean_meas[i] >= trigger_level) + if has_triggered: + n: int = measures_len + k: int = measures_index + jTrigger: int = n + jZero: int = n + j: int = 0 + + for j in range(n): + if (measures[i, k] >= trigger_level) and (j <= jTrigger + gap_len): + jZero = jTrigger = j + elif (measures[i, k] == 0) and (jTrigger >= jZero): + jZero = j + k = (k + n - 1) % n + j = min(j, jZero) + # num_measures_to_flush = range_limit(j, num_measures_to_flush, n); + num_measures_to_flush = (min(max(num_measures_to_flush, j), n)) + # end if has_triggered + # end if (measure_timer_ns == 0): + # end for + samplesIndex_ns += 1 + pos += 1 + # end while + if samplesIndex_ns == samplesLen_ns: + samplesIndex_ns = 0 + if measure_timer_ns == 0: + measure_timer_ns = measure_period_ns + measures_index += 1 + measures_index = measures_index % measures_len + if boot_count >= 0: + boot_count = -1 if boot_count == boot_count_max else boot_count + 1 + + if has_triggered: + flushedLen_ns = (measures_len - num_measures_to_flush) * measure_period_ns + samplesIndex_ns = (samplesIndex_ns + flushedLen_ns) % samplesLen_ns + + res = waveform[:, pos - samplesLen_ns + flushedLen_ns:] + # unpack batch + return res.view(shape[:-1] + res.shape[-1:]) diff --git a/torchaudio/kaldi_io.py b/torchaudio/kaldi_io.py index 50b101db7a..d32aaed357 100644 --- a/torchaudio/kaldi_io.py +++ b/torchaudio/kaldi_io.py @@ -1,7 +1,10 @@ # To use this file, the dependency (https://github.com/vesis84/kaldi-io-for-python) # needs to be installed. This is a light wrapper around kaldi_io that returns # torch.Tensors. +from typing import Any, Callable, Iterable, Tuple, Union + import torch +from torch import Tensor from torchaudio.common_utils import IMPORT_KALDI_IO, IMPORT_NUMPY if IMPORT_NUMPY: @@ -20,19 +23,20 @@ ] -def _convert_method_output_to_tensor(file_or_fd, fn, convert_contiguous=False): +def _convert_method_output_to_tensor(file_or_fd: Any, + fn: Callable, + convert_contiguous: bool = False) -> Iterable[Tuple[str, Tensor]]: r"""Takes a method invokes it. The output is converted to a tensor. Args: file_or_fd (str/FileDescriptor): File name or file descriptor - fn (Callable[[...], Generator[str, numpy.ndarray]]): Function that has the signature ( - file name/descriptor) -> Generator(str, numpy.ndarray) and converts it to ( - file name/descriptor) -> Generator(str, torch.Tensor). - convert_contiguous (bool): Determines whether the array should be converted into a - contiguous layout. (Default: ``None``) + fn (Callable): Function that has the signature (file name/descriptor) and converts it to + Iterable[Tuple[str, Tensor]]. + convert_contiguous (bool, optional): Determines whether the array should be converted into a + contiguous layout. (Default: ``False``) Returns: - Generator[str, torch.Tensor]: The string is the key and the tensor is vec/mat + Iterable[Tuple[str, Tensor]]: The string is the key and the tensor is vec/mat """ if not IMPORT_KALDI_IO: raise ImportError('Could not import kaldi_io. Did you install it?') @@ -43,14 +47,14 @@ def _convert_method_output_to_tensor(file_or_fd, fn, convert_contiguous=False): yield key, torch.from_numpy(np_arr) -def read_vec_int_ark(file_or_fd): +def read_vec_int_ark(file_or_fd: Any) -> Iterable[Tuple[str, Tensor]]: r"""Create generator of (key,vector) tuples, which reads from the ark file/stream. Args: file_or_fd (str/FileDescriptor): ark, gzipped ark, pipe or opened file descriptor Returns: - Generator[str, torch.Tensor]: The string is the key and the tensor is the vector read from file + Iterable[Tuple[str, Tensor]]: The string is the key and the tensor is the vector read from file Example >>> # read ark to a 'dictionary' @@ -62,14 +66,14 @@ def read_vec_int_ark(file_or_fd): return _convert_method_output_to_tensor(file_or_fd, kaldi_io.read_vec_int_ark, convert_contiguous=True) -def read_vec_flt_scp(file_or_fd): +def read_vec_flt_scp(file_or_fd: Any) -> Iterable[Tuple[str, Tensor]]: r"""Create generator of (key,vector) tuples, read according to Kaldi scp. Args: file_or_fd (str/FileDescriptor): scp, gzipped scp, pipe or opened file descriptor Returns: - Generator[str, torch.Tensor]: The string is the key and the tensor is the vector read from file + Iterable[Tuple[str, Tensor]]: The string is the key and the tensor is the vector read from file Example >>> # read scp to a 'dictionary' @@ -78,14 +82,14 @@ def read_vec_flt_scp(file_or_fd): return _convert_method_output_to_tensor(file_or_fd, kaldi_io.read_vec_flt_scp) -def read_vec_flt_ark(file_or_fd): +def read_vec_flt_ark(file_or_fd: Any) -> Iterable[Tuple[str, Tensor]]: r"""Create generator of (key,vector) tuples, which reads from the ark file/stream. Args: file_or_fd (str/FileDescriptor): ark, gzipped ark, pipe or opened file descriptor Returns: - Generator[str, torch.Tensor]: The string is the key and the tensor is the vector read from file + Iterable[Tuple[str, Tensor]]: The string is the key and the tensor is the vector read from file Example >>> # read ark to a 'dictionary' @@ -94,14 +98,14 @@ def read_vec_flt_ark(file_or_fd): return _convert_method_output_to_tensor(file_or_fd, kaldi_io.read_vec_flt_ark) -def read_mat_scp(file_or_fd): +def read_mat_scp(file_or_fd: Any) -> Iterable[Tuple[str, Tensor]]: r"""Create generator of (key,matrix) tuples, read according to Kaldi scp. Args: file_or_fd (str/FileDescriptor): scp, gzipped scp, pipe or opened file descriptor Returns: - Generator[str, torch.Tensor]: The string is the key and the tensor is the matrix read from file + Iterable[Tuple[str, Tensor]]: The string is the key and the tensor is the matrix read from file Example >>> # read scp to a 'dictionary' @@ -110,14 +114,14 @@ def read_mat_scp(file_or_fd): return _convert_method_output_to_tensor(file_or_fd, kaldi_io.read_mat_scp) -def read_mat_ark(file_or_fd): +def read_mat_ark(file_or_fd: Any) -> Iterable[Tuple[str, Tensor]]: r"""Create generator of (key,matrix) tuples, which reads from the ark file/stream. Args: file_or_fd (str/FileDescriptor): ark, gzipped ark, pipe or opened file descriptor Returns: - Generator[str, torch.Tensor]: The string is the key and the tensor is the matrix read from file + Iterable[Tuple[str, Tensor]]: The string is the key and the tensor is the matrix read from file Example >>> # read ark to a 'dictionary' diff --git a/torchaudio/sox_effects.py b/torchaudio/sox_effects.py index 76591bd084..472d291902 100644 --- a/torchaudio/sox_effects.py +++ b/torchaudio/sox_effects.py @@ -86,8 +86,8 @@ def __init__(self, out_siginfo: Any = None, out_encinfo: Any = None, filetype: str = "raw") -> None: - self.input_file = None - self.chain = [] + self.input_file: Optional[str] = None + self.chain: List[str] = [] self.MAX_EFFECT_OPTS = 20 self.out_siginfo = out_siginfo self.out_encinfo = out_encinfo @@ -100,12 +100,12 @@ def __init__(self, def append_effect_to_chain(self, ename: str, - eargs: Optional[List[str]] = None) -> None: + eargs: Optional[Union[List[str], str]] = None) -> None: r"""Append effect to a sox effects chain. Args: ename (str): which is the name of effect - eargs (List[str], optional): which is a list of effect options. (Default: ``None``) + eargs (List[str] or str, optional): which is a list of effect options. (Default: ``None``) """ e = SoxEffect() # check if we have a valid effect @@ -149,6 +149,7 @@ def sox_build_flow_effects(self, # print("effect options:", [x.eopts for x in self.chain]) + torchaudio.initialize_sox() import _torch_sox sr = _torch_sox.build_flow_effects(self.input_file, out, diff --git a/torchaudio/transforms.py b/torchaudio/transforms.py index 8775bbdb5b..29da721869 100644 --- a/torchaudio/transforms.py +++ b/torchaudio/transforms.py @@ -26,6 +26,8 @@ 'Fade', 'FrequencyMasking', 'TimeMasking', + 'SlidingWindowCmn', + 'Vad', ] @@ -453,7 +455,7 @@ def __init__(self, super(MFCC, self).__init__() supported_dct_types = [2] if dct_type not in supported_dct_types: - raise ValueError('DCT type not supported'.format(dct_type)) + raise ValueError('DCT type not supported: {}'.format(dct_type)) self.sample_rate = sample_rate self.n_mfcc = n_mfcc self.dct_type = dct_type @@ -837,10 +839,10 @@ class Vol(torch.nn.Module): Args: gain (float): Interpreted according to the given gain_type: - If `gain_typeโ€™ = โ€˜amplitudeโ€™, `gainโ€™ is a positive amplitude ratio. - If `gain_typeโ€™ = โ€˜powerโ€™, `gainโ€™ is a power (voltage squared). - If `gain_typeโ€™ = โ€˜dbโ€™, `gainโ€™ is in decibels. - gain_type (str, optional): Type of gain. One of: โ€˜amplitudeโ€™, โ€˜powerโ€™, โ€˜dbโ€™ (Default: ``"amplitude"``) + If ``gain_type`` = ``amplitude``, ``gain`` is a positive amplitude ratio. + If ``gain_type`` = ``power``, ``gain`` is a power (voltage squared). + If ``gain_type`` = ``db``, ``gain`` is in decibels. + gain_type (str, optional): Type of gain. One of: ``amplitude``, ``power``, ``db`` (Default: ``amplitude``) """ def __init__(self, gain: float, gain_type: str = 'amplitude'): @@ -869,3 +871,157 @@ def forward(self, waveform: Tensor) -> Tensor: waveform = F.gain(waveform, 10 * math.log10(self.gain)) return torch.clamp(waveform, -1, 1) + + +class SlidingWindowCmn(torch.nn.Module): + r""" + Apply sliding-window cepstral mean (and optionally variance) normalization per utterance. + + Args: + cmn_window (int, optional): Window in frames for running average CMN computation (int, default = 600) + min_cmn_window (int, optional): Minimum CMN window used at start of decoding (adds latency only at start). + Only applicable if center == false, ignored if center==true (int, default = 100) + center (bool, optional): If true, use a window centered on the current frame + (to the extent possible, modulo end effects). If false, window is to the left. (bool, default = false) + norm_vars (bool, optional): If true, normalize variance to one. (bool, default = false) + """ + + def __init__(self, + cmn_window: int = 600, + min_cmn_window: int = 100, + center: bool = False, + norm_vars: bool = False) -> None: + super().__init__() + self.cmn_window = cmn_window + self.min_cmn_window = min_cmn_window + self.center = center + self.norm_vars = norm_vars + + def forward(self, waveform: Tensor) -> Tensor: + r""" + Args: + waveform (Tensor): Tensor of audio of dimension (..., time). + + Returns: + Tensor: Tensor of audio of dimension (..., time). + """ + cmn_waveform = F.sliding_window_cmn( + waveform, self.cmn_window, self.min_cmn_window, self.center, self.norm_vars) + return cmn_waveform + + +class Vad(torch.nn.Module): + r"""Voice Activity Detector. Similar to SoX implementation. + Attempts to trim silence and quiet background sounds from the ends of recordings of speech. + The algorithm currently uses a simple cepstral power measurement to detect voice, + so may be fooled by other things, especially music. + + The effect can trim only from the front of the audio, + so in order to trim from the back, the reverse effect must also be used. + + Args: + sample_rate (int): Sample rate of audio signal. + trigger_level (float, optional): The measurement level used to trigger activity detection. + This may need to be cahnged depending on the noise level, signal level, + and other characteristics of the input audio. (Default: 7.0) + trigger_time (float, optional): The time constant (in seconds) + used to help ignore short bursts of sound. (Default: 0.25) + search_time (float, optional): The amount of audio (in seconds) + to search for quieter/shorter bursts of audio to include prior + to the detected trigger point. (Default: 1.0) + allowed_gap (float, optional): The allowed gap (in seconds) between + quiteter/shorter bursts of audio to include prior + to the detected trigger point. (Default: 0.25) + pre_trigger_time (float, optional): The amount of audio (in seconds) to preserve + before the trigger point and any found quieter/shorter bursts. (Default: 0.0) + boot_time (float, optional) The algorithm (internally) uses adaptive noise + estimation/reduction in order to detect the start of the wanted audio. + This option sets the time for the initial noise estimate. (Default: 0.35) + noise_up_time (float, optional) Time constant used by the adaptive noise estimator + for when the noise level is increasing. (Default: 0.1) + noise_down_time (float, optional) Time constant used by the adaptive noise estimator + for when the noise level is decreasing. (Default: 0.01) + noise_reduction_amount (float, optional) Amount of noise reduction to use in + the detection algorithm (e.g. 0, 0.5, ...). (Default: 1.35) + measure_freq (float, optional) Frequency of the algorithmโ€™s + processing/measurements. (Default: 20.0) + measure_duration: (float, optional) Measurement duration. + (Default: Twice the measurement period; i.e. with overlap.) + measure_smooth_time (float, optional) Time constant used to smooth + spectral measurements. (Default: 0.4) + hp_filter_freq (float, optional) "Brick-wall" frequency of high-pass filter applied + at the input to the detector algorithm. (Default: 50.0) + lp_filter_freq (float, optional) "Brick-wall" frequency of low-pass filter applied + at the input to the detector algorithm. (Default: 6000.0) + hp_lifter_freq (float, optional) "Brick-wall" frequency of high-pass lifter used + in the detector algorithm. (Default: 150.0) + lp_lifter_freq (float, optional) "Brick-wall" frequency of low-pass lifter used + in the detector algorithm. (Default: 2000.0) + + References: + http://sox.sourceforge.net/sox.html + """ + + def __init__(self, + sample_rate: int, + trigger_level: float = 7.0, + trigger_time: float = 0.25, + search_time: float = 1.0, + allowed_gap: float = 0.25, + pre_trigger_time: float = 0.0, + boot_time: float = .35, + noise_up_time: float = .1, + noise_down_time: float = .01, + noise_reduction_amount: float = 1.35, + measure_freq: float = 20.0, + measure_duration: Optional[float] = None, + measure_smooth_time: float = .4, + hp_filter_freq: float = 50., + lp_filter_freq: float = 6000., + hp_lifter_freq: float = 150., + lp_lifter_freq: float = 2000.) -> None: + super().__init__() + + self.sample_rate = sample_rate + self.trigger_level = trigger_level + self.trigger_time = trigger_time + self.search_time = search_time + self.allowed_gap = allowed_gap + self.pre_trigger_time = pre_trigger_time + self.boot_time = boot_time + self.noise_up_time = noise_up_time + self.noise_down_time = noise_up_time + self.noise_reduction_amount = noise_reduction_amount + self.measure_freq = measure_freq + self.measure_duration = measure_duration + self.measure_smooth_time = measure_smooth_time + self.hp_filter_freq = hp_filter_freq + self.lp_filter_freq = lp_filter_freq + self.hp_lifter_freq = hp_lifter_freq + self.lp_lifter_freq = lp_lifter_freq + + def forward(self, waveform: Tensor) -> Tensor: + r""" + Args: + waveform (Tensor): Tensor of audio of dimension `(..., time)` + """ + return F.vad( + waveform=waveform, + sample_rate=self.sample_rate, + trigger_level=self.trigger_level, + trigger_time=self.trigger_time, + search_time=self.search_time, + allowed_gap=self.allowed_gap, + pre_trigger_time=self.pre_trigger_time, + boot_time=self.boot_time, + noise_up_time=self.noise_up_time, + noise_down_time=self.noise_up_time, + noise_reduction_amount=self.noise_reduction_amount, + measure_freq=self.measure_freq, + measure_duration=self.measure_duration, + measure_smooth_time=self.measure_smooth_time, + hp_filter_freq=self.hp_filter_freq, + lp_filter_freq=self.lp_filter_freq, + hp_lifter_freq=self.hp_lifter_freq, + lp_lifter_freq=self.lp_lifter_freq, + ) From e065a0f4c49680b17e2cfd9e666962a8ee1cefb0 Mon Sep 17 00:00:00 2001 From: Moto Hira Date: Thu, 28 May 2020 12:18:22 -0700 Subject: [PATCH 05/73] Import torchaudio 20200528 Summary: Import Up to #664 Reviewed By: cpuhrsch Differential Revision: D21728204 fbshipit-source-id: 648dd622087fa762194ca5f89a310500e777263d --- .use_external_sox | 0 README.md | 25 +- build_tools/__init__.py | 0 build_tools/setup_helpers/__init__.py | 1 + .../setup_helpers/build_third_party.sh | 36 ++ .../setup_helpers/build_third_party_helper.sh | 173 +++++++++ build_tools/setup_helpers/extension.py | 111 ++++++ docs/source/functional.rst | 5 + docs/source/models.rst | 17 + packaging/build_from_source.sh | 62 ---- packaging/build_wheel.sh | 8 +- packaging/pkg_helpers.bash | 2 +- packaging/torchaudio/build.sh | 4 +- setup.py | 99 ++---- test/README.md | 51 +++ test/__init__.py | 10 + test/assets/vad-go-mono-32000.wav | Bin 0 -> 54660 bytes test/assets/vad-go-stereo-44100.wav | Bin 0 -> 173400 bytes test/assets/vad-hello-mono-32000.wav | Bin 275106 -> 0 bytes test/assets/vad-hello-stereo-44100.wav | Bin 937862 -> 0 bytes test/common_utils.py | 104 ++++++ test/kaldi_compatibility_cpu_test.py | 5 + test/kaldi_compatibility_cuda_test.py | 5 + test/kaldi_compatibility_impl.py | 104 ++++++ test/test_batch_consistency.py | 102 +++--- test/test_compliance_kaldi.py | 10 +- test/test_dataloader.py | 10 +- test/test_datasets.py | 5 +- test/test_functional.py | 39 +-- test/test_io.py | 4 +- test/test_kaldi_io.py | 2 +- test/test_librosa_compatibility.py | 184 +++++----- test/test_models.py | 30 ++ test/test_sox_compatibility.py | 93 +++-- test/test_sox_effects.py | 50 ++- test/test_transforms.py | 17 +- test/torchscript_consistency_cpu_test.py | 5 + test/torchscript_consistency_cuda_test.py | 5 + ...ncy.py => torchscript_consistency_impl.py} | 221 ++++++------ torchaudio/__init__.py | 40 +-- torchaudio/_sox_backend.py | 8 +- torchaudio/compliance/kaldi.py | 67 ++-- torchaudio/{torch_sox.cpp => csrc/sox.cpp} | 14 +- torchaudio/{torch_sox.h => csrc/sox.h} | 18 +- torchaudio/functional.py | 327 +++++++++++------- torchaudio/models/__init__.py | 1 + torchaudio/models/wav2letter.py | 74 ++++ torchaudio/sox_effects.py | 26 +- torchaudio/transforms.py | 30 +- 49 files changed, 1517 insertions(+), 687 deletions(-) create mode 100644 .use_external_sox create mode 100644 build_tools/__init__.py create mode 100644 build_tools/setup_helpers/__init__.py create mode 100755 build_tools/setup_helpers/build_third_party.sh create mode 100644 build_tools/setup_helpers/build_third_party_helper.sh create mode 100644 build_tools/setup_helpers/extension.py create mode 100644 docs/source/models.rst delete mode 100755 packaging/build_from_source.sh create mode 100644 test/README.md create mode 100644 test/__init__.py create mode 100644 test/assets/vad-go-mono-32000.wav create mode 100644 test/assets/vad-go-stereo-44100.wav delete mode 100644 test/assets/vad-hello-mono-32000.wav delete mode 100644 test/assets/vad-hello-stereo-44100.wav create mode 100644 test/kaldi_compatibility_cpu_test.py create mode 100644 test/kaldi_compatibility_cuda_test.py create mode 100644 test/kaldi_compatibility_impl.py create mode 100644 test/test_models.py create mode 100644 test/torchscript_consistency_cpu_test.py create mode 100644 test/torchscript_consistency_cuda_test.py rename test/{test_torchscript_consistency.py => torchscript_consistency_impl.py} (74%) rename torchaudio/{torch_sox.cpp => csrc/sox.cpp} (98%) rename torchaudio/{torch_sox.h => csrc/sox.h} (88%) create mode 100644 torchaudio/models/__init__.py create mode 100644 torchaudio/models/wav2letter.py diff --git a/.use_external_sox b/.use_external_sox new file mode 100644 index 0000000000..e69de29bb2 diff --git a/README.md b/README.md index 816fd75f6c..fc3326075a 100644 --- a/README.md +++ b/README.md @@ -13,7 +13,7 @@ having all the computations be through Pytorch operations which makes it easy to use and feel like a natural extension. - [Support audio I/O (Load files, Save files)](http://pytorch.org/audio/) - - Load the following formats into a torch Tensor using sox + - Load the following formats into a torch Tensor using SoX - mp3, wav, aac, ogg, flac, avr, cdda, cvs/vms, - aiff, au, amr, mp2, mp4, ac3, avi, wmv, - mpeg, ircam and any other format supported by libsox. @@ -98,10 +98,29 @@ Quick Usage ```python import torchaudio -waveform, sample_rate = torchaudio.load('foo.mp3') # load tensor from file -torchaudio.save('foo_save.mp3', waveform, sample_rate) # save tensor to file + +waveform, sample_rate = torchaudio.load('foo.wav') # load tensor from file +torchaudio.save('foo_save.wav', waveform, sample_rate) # save tensor to file ``` +Backend Dispatch +---------------- + +By default in OSX and Linux, torchaudio uses SoX as a backend to load and save files. +The backend can be changed to [SoundFile](https://pysoundfile.readthedocs.io/en/latest/) +using the following. See [SoundFile](https://pysoundfile.readthedocs.io/en/latest/) +for installation instructions. + +```python +import torchaudio +torchaudio.set_audio_backend("soundfile") # switch backend + +waveform, sample_rate = torchaudio.load('foo.wav') # load tensor from file, as usual +torchaudio.save('foo_save.wav', waveform, sample_rate) # save tensor to file, as usual +``` + +Unlike SoX, SoundFile does not currently support mp3. + API Reference ------------- diff --git a/build_tools/__init__.py b/build_tools/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/build_tools/setup_helpers/__init__.py b/build_tools/setup_helpers/__init__.py new file mode 100644 index 0000000000..7afa3f31cd --- /dev/null +++ b/build_tools/setup_helpers/__init__.py @@ -0,0 +1 @@ +from .extension import * # noqa diff --git a/build_tools/setup_helpers/build_third_party.sh b/build_tools/setup_helpers/build_third_party.sh new file mode 100755 index 0000000000..c5e8f8115d --- /dev/null +++ b/build_tools/setup_helpers/build_third_party.sh @@ -0,0 +1,36 @@ +#!/bin/bash +# Build third party libraries in `/third_party/build` or in `/third_party/build`. + +set -e + +this_dir="$( cd "$( dirname "${BASH_SOURCE[0]}" )" >/dev/null 2>&1 && pwd )" +root_dir="${this_dir}/../.." + +prefix="${1:-}" +if [ -z "${prefix}" ]; then + prefix="${root_dir}" +fi + +tp_dir="${prefix}/third_party" +tmp_dir="${tp_dir}/tmp" +build_dir="${tp_dir}/build" + +mkdir -p "${tmp_dir}" "${build_dir}" + +. "${this_dir}/build_third_party_helper.sh" + +if ! found_lame "${build_dir}" ; then + build_lame "${tmp_dir}" "${build_dir}" +fi + +if ! found_flac "${build_dir}" ; then + build_flac "${tmp_dir}" "${build_dir}" +fi + +if ! found_mad "${build_dir}" ; then + build_mad "${tmp_dir}" "${build_dir}" +fi + +if ! found_sox "${build_dir}" ; then + build_sox "${tmp_dir}" "${build_dir}" +fi diff --git a/build_tools/setup_helpers/build_third_party_helper.sh b/build_tools/setup_helpers/build_third_party_helper.sh new file mode 100644 index 0000000000..a31fafe718 --- /dev/null +++ b/build_tools/setup_helpers/build_third_party_helper.sh @@ -0,0 +1,173 @@ +#!/usr/bin/env bash + +set -euo pipefail + +# Global options +CURL_OPTS="-L --retry 10 --connect-timeout 5 --max-time 180" +MAKE_OPTS="-j" +CONFIG_OPTS="" + +if [ -z ${DEBUG+x} ]; then + CURL_OPTS="${CURL_OPTS} --silent --show-error" + MAKE_OPTS="${MAKE_OPTS} --quiet" + CONFIG_OPTS="${CONFIG_OPTS} --quiet" +fi + +all_found() { + dir="$1" + shift + while [ "$#" -gt 0 ]; do + if [ ! -f "${dir}/$1" ]; then + return 1 + fi + shift + done +} + + +found_lame() { + all_found "$1" 'include/lame/lame.h' 'lib/libmp3lame.a' +} + +found_flac() { + all_found "$1" \ + 'include/FLAC/format.h' \ + 'include/FLAC/stream_decoder.h' \ + 'include/FLAC/export.h' \ + 'include/FLAC/ordinals.h' \ + 'include/FLAC/all.h' \ + 'include/FLAC/assert.h' \ + 'include/FLAC/callback.h' \ + 'include/FLAC/metadata.h' \ + 'include/FLAC/stream_encoder.h' \ + 'include/FLAC++/export.h' \ + 'include/FLAC++/decoder.h' \ + 'include/FLAC++/all.h' \ + 'include/FLAC++/metadata.h' \ + 'include/FLAC++/encoder.h' \ + 'lib/libFLAC++.a' \ + 'lib/libFLAC.a' +} + +found_mad() { + all_found "$1" 'include/mad.h' 'lib/libmad.a' +} + +found_sox() { + all_found "$1" 'include/sox.h' 'lib/libsox.a' +} + +build_lame() { + work_dir="$1" + install_dir="$2" + package="lame-3.99.5" + url="https://downloads.sourceforge.net/project/lame/lame/3.99/lame-3.99.5.tar.gz" + ( + cd "${work_dir}" + if [ ! -d "${package}" ]; then + if [ ! -f "${package}.tar.gz" ]; then + printf "Fetching liblame from %s\n" "${url}" + curl $CURL_OPTS -o "${package}.tar.gz" "${url}" + fi + tar xfp "${package}.tar.gz" + fi + # build statically + printf "Building liblame\n" + cd "${package}" + if [ ! -f Makefile ]; then + ./configure ${CONFIG_OPTS} \ + --disable-shared --enable-static --prefix="${install_dir}" CFLAGS=-fPIC CXXFLAGS=-fPIC \ + --with-pic --disable-debug --disable-dependency-tracking --enable-nasm + fi + make ${MAKE_OPTS} > make.log 2>&1 + make ${MAKE_OPTS} install + ) +} + +build_flac() { + work_dir="$1" + install_dir="$2" + package="flac-1.3.2" + url="https://downloads.sourceforge.net/project/flac/flac-src/flac-1.3.2.tar.xz" + ( + cd "${work_dir}" + if [ ! -d "${package}" ]; then + if [ ! -f "${package}.tar.xz" ]; then + printf "Fetching flac from %s\n" "${url}" + curl $CURL_OPTS -o "${package}.tar.xz" "${url}" + fi + tar xfp "${package}.tar.xz" + fi + # build statically + printf "Building flac\n" + cd "${package}" + if [ ! -f Makefile ]; then + ./configure ${CONFIG_OPTS} \ + --disable-shared --enable-static --prefix="${install_dir}" CFLAGS=-fPIC CXXFLAGS=-fPIC \ + --with-pic --disable-debug --disable-dependency-tracking + fi + make ${MAKE_OPTS} > make.log 2>&1 + make ${MAKE_OPTS} install + ) +} + +build_mad() { + work_dir="$1" + install_dir="$2" + package="libmad-0.15.1b" + url="https://downloads.sourceforge.net/project/mad/libmad/0.15.1b/libmad-0.15.1b.tar.gz" + ( + cd "${work_dir}" + if [ ! -d "${package}" ]; then + if [ ! -f "${package}.tar.gz" ]; then + printf "Fetching mad from %s\n" "${url}" + curl $CURL_OPTS -o "${package}.tar.gz" "${url}" + fi + tar xfp "${package}.tar.gz" + fi + # build statically + printf "Building mad\n" + cd "${package}" + if [ ! -f Makefile ]; then + # See https://stackoverflow.com/a/12864879/23845 + sed -i.bak 's/-march=i486//' configure + ./configure ${CONFIG_OPTS} \ + --disable-shared --enable-static --prefix="${install_dir}" CFLAGS=-fPIC CXXFLAGS=-fPIC \ + --with-pic --disable-debug --disable-dependency-tracking + fi + make ${MAKE_OPTS} > make.log 2>&1 + make ${MAKE_OPTS} install + ) +} + +build_sox() { + work_dir="$1" + install_dir="$2" + package="sox-14.4.2" + url="https://downloads.sourceforge.net/project/sox/sox/14.4.2/sox-14.4.2.tar.bz2" + ( + cd "${work_dir}" + if [ ! -d "${package}" ]; then + if [ ! -f "${package}.tar.bz2" ]; then + printf "Fetching SoX from %s\n" "${url}" + curl $CURL_OPTS -o "${package}.tar.bz2" "${url}" + fi + tar xfp "${package}.tar.bz2" + fi + # build statically + printf "Building sox\n" + cd "${package}" + if [ ! -f Makefile ]; then + # --without-png makes OS X build less hazardous; somehow the build + # finds png and enables it. We don't want it; we'd need to package + # it statically if we do. + ./configure ${CONFIG_OPTS} --disable-shared --enable-static --prefix="${install_dir}" \ + LDFLAGS="-L${install_dir}/lib" CPPFLAGS="-I${install_dir}/include" \ + --with-lame --with-flac --with-mad --without-alsa --without-coreaudio \ + --without-png --without-oggvorbis --without-oss --without-sndfile \ + CFLAGS=-fPIC CXXFLAGS=-fPIC --with-pic --disable-debug --disable-dependency-tracking + fi + make ${MAKE_OPTS} > make.log 2>&1 + make ${MAKE_OPTS} install + ) +} diff --git a/build_tools/setup_helpers/extension.py b/build_tools/setup_helpers/extension.py new file mode 100644 index 0000000000..65e48dfc10 --- /dev/null +++ b/build_tools/setup_helpers/extension.py @@ -0,0 +1,111 @@ +import platform +import subprocess +from pathlib import Path + +from torch.utils.cpp_extension import ( + CppExtension, + BuildExtension as TorchBuildExtension +) + +__all__ = [ + 'get_ext_modules', + 'BuildExtension', +] + +_THIS_DIR = Path(__file__).parent.resolve() +_ROOT_DIR = _THIS_DIR.parent.parent.resolve() +_CSRC_DIR = _ROOT_DIR / 'torchaudio' / 'csrc' +_TP_BASE_DIR = _ROOT_DIR / 'third_party' +_TP_INSTALL_DIR = _TP_BASE_DIR / 'build' + +# Temporary fix for building in fbcode +# at the moment, we have to use external sox in fbcode +_BUILD_DEPS = not (_ROOT_DIR / '.use_external_sox').exists() + + +def _get_eca(debug): + eca = [] + if debug: + eca += ["-O0", "-g"] + else: + eca += ["-O3"] + return eca + + +def _get_ela(debug): + ela = [] + if debug: + if platform.system() == "Windows": + ela += ["/DEBUG:FULL"] + else: + ela += ["-O0", "-g"] + else: + ela += ["-O3"] + return ela + + +def _get_srcs(): + return [str(p) for p in _CSRC_DIR.glob('**/*.cpp')] + + +def _get_include_dirs(): + dirs = [ + str(_ROOT_DIR), + ] + if _BUILD_DEPS: + dirs.append(str(_TP_INSTALL_DIR / 'include')) + return dirs + + +def _get_extra_objects(): + objs = [] + if _BUILD_DEPS: + # NOTE: The order of the library listed bellow matters. + # + # (the most important thing is that dependencies come after a library + # e.g., sox comes first) + libs = ['libsox.a', 'libmad.a', 'libFLAC.a', 'libmp3lame.a'] + for lib in libs: + objs.append(str(_TP_INSTALL_DIR / 'lib' / lib)) + return objs + + +def _get_libraries(): + return [] if _BUILD_DEPS else ['sox'] + + +def _build_codecs(): + subprocess.run( + args=[str(_THIS_DIR / 'build_third_party.sh')], + check=True, + ) + + +def _configure_third_party(): + _build_codecs() + + +_EXT_NAME = 'torchaudio._torchaudio' + + +def get_ext_modules(debug=False): + if platform.system() == 'Windows': + return None + return [ + CppExtension( + _EXT_NAME, + _get_srcs(), + libraries=_get_libraries(), + include_dirs=_get_include_dirs(), + extra_compile_args=_get_eca(debug), + extra_objects=_get_extra_objects(), + extra_link_args=_get_ela(debug), + ), + ] + + +class BuildExtension(TorchBuildExtension): + def build_extension(self, ext): + if ext.name == _EXT_NAME and _BUILD_DEPS: + _configure_third_party() + super().build_extension(ext) diff --git a/docs/source/functional.rst b/docs/source/functional.rst index d8f318ea18..5f68666539 100644 --- a/docs/source/functional.rst +++ b/docs/source/functional.rst @@ -138,6 +138,11 @@ Functions to perform common audio operations. .. autofunction:: overdrive +:hidden:`phaser` +~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +.. autofunction:: phaser + :hidden:`mask_along_axis` ~~~~~~~~~~~~~~~~~~~~~~~~~ diff --git a/docs/source/models.rst b/docs/source/models.rst new file mode 100644 index 0000000000..5b40482976 --- /dev/null +++ b/docs/source/models.rst @@ -0,0 +1,17 @@ +.. role:: hidden + :class: hidden-section + +torchaudio.models +====================== + +.. currentmodule:: torchaudio.models + +The models subpackage contains definitions of models for addressing common audio tasks. + + +:hidden:`Wav2Letter` +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +.. autoclass:: Wav2Letter + + .. automethod:: forward diff --git a/packaging/build_from_source.sh b/packaging/build_from_source.sh deleted file mode 100755 index f5981f0a5e..0000000000 --- a/packaging/build_from_source.sh +++ /dev/null @@ -1,62 +0,0 @@ -#!/bin/bash - -set -ex - -# Arguments: PREFIX, specifying where to install dependencies into - -PREFIX="$1" - -rm -rf /tmp/torchaudio-deps -mkdir /tmp/torchaudio-deps -pushd /tmp/torchaudio-deps - - -# Curl Settings -CURL_OPTS="-L --retry 10 --connect-timeout 5 --max-time 180" - -curl $CURL_OPTS -o sox-14.4.2.tar.bz2 "https://downloads.sourceforge.net/project/sox/sox/14.4.2/sox-14.4.2.tar.bz2" -curl $CURL_OPTS -o lame-3.99.5.tar.gz "https://downloads.sourceforge.net/project/lame/lame/3.99/lame-3.99.5.tar.gz" -curl $CURL_OPTS -o flac-1.3.2.tar.xz "https://downloads.sourceforge.net/project/flac/flac-src/flac-1.3.2.tar.xz" -curl $CURL_OPTS -o libmad-0.15.1b.tar.gz "https://downloads.sourceforge.net/project/mad/libmad/0.15.1b/libmad-0.15.1b.tar.gz" - -# unpack the dependencies -tar xfp sox-14.4.2.tar.bz2 -tar xfp lame-3.99.5.tar.gz -tar xfp flac-1.3.2.tar.xz -tar xfp libmad-0.15.1b.tar.gz - -# build lame, statically -pushd lame-3.99.5 -./configure --disable-shared --enable-static --prefix="$PREFIX/third_party/lame" CFLAGS=-fPIC CXXFLAGS=-fPIC --with-pic --disable-debug --disable-dependency-tracking --enable-nasm -make -s -j && make install -popd - -# build flac, statically -pushd flac-1.3.2 -./configure --disable-shared --enable-static --prefix="$PREFIX/third_party/flac" CFLAGS=-fPIC CXXFLAGS=-fPIC \ - --with-pic --disable-debug --disable-dependency-tracking -make -s -j && make install -popd - -# build mad, statically -pushd libmad-0.15.1b -# See https://stackoverflow.com/a/12864879/23845 -sed -i.bak 's/-march=i486//' configure -./configure --disable-shared --enable-static --prefix="$PREFIX/third_party/mad" CFLAGS=-fPIC CXXFLAGS=-fPIC \ - --with-pic --disable-debug --disable-dependency-tracking -make -s -j && make install -popd - -# build sox, statically -# --without-png makes OS X build less hazardous; somehow the build -# finds png and enables it. We don't want it; we'd need to package -# it statically if we do. -pushd sox-14.4.2 -./configure --disable-shared --enable-static --prefix="$PREFIX/third_party/sox" \ - LDFLAGS="-L$PREFIX/third_party/lame/lib -L$PREFIX/third_party/flac/lib -L$PREFIX/third_party/mad/lib" \ - CPPFLAGS="-I$PREFIX/third_party/lame/include -I$PREFIX/third_party/flac/include -I$PREFIX/third_party/mad/include" \ - --with-lame --with-flac --with-mad --without-alsa --without-coreaudio --without-png --without-oggvorbis --without-oss --without-sndfile CFLAGS=-fPIC CXXFLAGS=-fPIC --with-pic --disable-debug --disable-dependency-tracking -make -s -j && make install -popd - -popd diff --git a/packaging/build_wheel.sh b/packaging/build_wheel.sh index fc0742ece1..73cec89ff5 100755 --- a/packaging/build_wheel.sh +++ b/packaging/build_wheel.sh @@ -8,8 +8,12 @@ export BUILD_TYPE="wheel" export NO_CUDA_PACKAGE=1 setup_env 0.6.0 setup_wheel_python -"$script_dir/build_from_source.sh" "$(pwd)" # Build static dependencies pip_install numpy future setup_pip_pytorch_version python setup.py clean -IS_WHEEL=1 python setup.py bdist_wheel +if [[ "$OSTYPE" == "msys" ]]; then + python_tag="$(echo "cp$PYTHON_VERSION" | tr -d '.')" + python setup.py bdist_wheel --plat-name win_amd64 --python-tag $python_tag +else + python setup.py bdist_wheel +fi diff --git a/packaging/pkg_helpers.bash b/packaging/pkg_helpers.bash index bc8ec997df..4030128a98 100644 --- a/packaging/pkg_helpers.bash +++ b/packaging/pkg_helpers.bash @@ -122,7 +122,7 @@ retry () { # # Precondition: If Linux, you are in a soumith/manylinux-cuda* Docker image setup_wheel_python() { - if [[ "$(uname)" == Darwin ]]; then + if [[ "$(uname)" == Darwin || "$OSTYPE" == "msys" ]]; then eval "$(conda shell.bash hook)" conda env remove -n "env$PYTHON_VERSION" || true conda create -yn "env$PYTHON_VERSION" python="$PYTHON_VERSION" diff --git a/packaging/torchaudio/build.sh b/packaging/torchaudio/build.sh index dff89cf31b..e2b53ddcf4 100644 --- a/packaging/torchaudio/build.sh +++ b/packaging/torchaudio/build.sh @@ -1,6 +1,4 @@ #!/usr/bin/env bash set -ex -packaging/build_from_source.sh "$(pwd)" - -IS_CONDA=1 python setup.py install --single-version-externally-managed --record=record.txt +python setup.py install --single-version-externally-managed --record=record.txt diff --git a/setup.py b/setup.py index 0128a2fe61..5cf1ad680a 100644 --- a/setup.py +++ b/setup.py @@ -1,65 +1,22 @@ #!/usr/bin/env python import os -import platform -import sys +import shutil import subprocess - +from pathlib import Path +import distutils.command.clean from setuptools import setup, find_packages -from torch.utils.cpp_extension import BuildExtension, CppExtension - - -def check_env_flag(name, default=''): - return os.getenv(name, default).upper() in set(['ON', '1', 'YES', 'TRUE', 'Y']) - -DEBUG = check_env_flag('DEBUG') -IS_WHEEL = check_env_flag('IS_WHEEL') -IS_CONDA = check_env_flag('IS_CONDA') - -print('DEBUG:', DEBUG, 'IS_WHEEL:', IS_WHEEL, 'IS_CONDA:', IS_CONDA) - -eca = [] -ela = [] -if DEBUG: - if platform.system() == 'Windows': - ela += ['/DEBUG:FULL'] - else: - eca += ['-O0', '-g'] - ela += ['-O0', '-g'] +from build_tools import setup_helpers -libraries = [] -include_dirs = [] -extra_objects = [] - -# Hypothetically, the conda distribution could rely on an external sox, -# but the library is pretty small and it is not available on the default -# anaconda channel. So we statically link it in, just as we do with wheels. -if IS_WHEEL or IS_CONDA: - audio_path = os.path.dirname(os.path.abspath(__file__)) - - include_dirs += [os.path.join(audio_path, 'third_party/flac/include')] - include_dirs += [os.path.join(audio_path, 'third_party/lame/include')] - include_dirs += [os.path.join(audio_path, 'third_party/sox/include')] - include_dirs += [os.path.join(audio_path, 'third_party/mad/include')] - - # proper link order (sox, mad, flac, lame) - # (the most important thing is that dependencies come after a libraryl - # e.g., sox comes first) - extra_objects += [os.path.join(audio_path, 'third_party/sox/lib/libsox.a')] - extra_objects += [os.path.join(audio_path, 'third_party/mad/lib/libmad.a')] - extra_objects += [os.path.join(audio_path, 'third_party/flac/lib/libFLAC.a')] - extra_objects += [os.path.join(audio_path, 'third_party/lame/lib/libmp3lame.a')] -else: - libraries += ['sox'] +ROOT_DIR = Path(__file__).parent.resolve() # Creating the version file -cwd = os.path.dirname(os.path.abspath(__file__)) version = '0.6.0a0' sha = 'Unknown' try: - sha = subprocess.check_output(['git', 'rev-parse', 'HEAD'], cwd=cwd).decode('ascii').strip() + sha = subprocess.check_output(['git', 'rev-parse', 'HEAD'], cwd=ROOT_DIR).decode('ascii').strip() except Exception: pass @@ -69,7 +26,7 @@ def check_env_flag(name, default=''): version += '+' + sha[:7] print('-- Building version ' + version) -version_path = os.path.join(cwd, 'torchaudio', 'version.py') +version_path = ROOT_DIR / 'torchaudio' / 'version.py' with open(version_path, 'w') as f: f.write("__version__ = '{}'\n".format(version)) f.write("git_version = {}\n".format(repr(sha))) @@ -80,19 +37,26 @@ def check_env_flag(name, default=''): if pytorch_package_version is not None: pytorch_package_dep += "==" + pytorch_package_version -if platform.system() == 'Windows': - ext_modules = None -else: - ext_modules = [ - CppExtension( - '_torch_sox', - ['torchaudio/torch_sox.cpp'], - libraries=libraries, - include_dirs=include_dirs, - extra_compile_args=eca, - extra_objects=extra_objects, - extra_link_args=ela), - ] + +class clean(distutils.command.clean.clean): + def run(self): + # Run default behavior first + distutils.command.clean.clean.run(self) + + # Remove torchaudio extension + for path in (ROOT_DIR / 'torchaudio').glob('**/*.so'): + print(f'removing \'{path}\'') + path.unlink() + # Remove build directory + build_dirs = [ + ROOT_DIR / 'build', + ROOT_DIR / 'third_party' / 'build', + ] + for path in build_dirs: + if path.exists(): + print(f'removing \'{path}\' (and everything under it)') + shutil.rmtree(str(path), ignore_errors=True) + setup( name="torchaudio", @@ -116,9 +80,10 @@ def check_env_flag(name, default=''): "Topic :: Multimedia :: Sound/Audio", "Topic :: Scientific/Engineering :: Artificial Intelligence" ], - # Exclude the build files. - packages=find_packages(exclude=["build"]), - ext_modules=ext_modules, - cmdclass={'build_ext': BuildExtension}, + packages=find_packages(exclude=["build*", "test*", "torchaudio.csrc*", "third_party*", "build_tools*"]), + ext_modules=setup_helpers.get_ext_modules(), + cmdclass={ + 'build_ext': setup_helpers.BuildExtension.with_options(no_python_abi_suffix=True) + }, install_requires=[pytorch_package_dep] ) diff --git a/test/README.md b/test/README.md new file mode 100644 index 0000000000..a6686603af --- /dev/null +++ b/test/README.md @@ -0,0 +1,51 @@ +# Torchaudio Test Suite + +## Structure of tests + +The following is an overview of the tests and related modules for `torchaudio`. + +### Purpose specific test suites + +#### Numerical compatibility agains existing software +- [Librosa compatibility test](./test_librosa_compatibility.py) + Test suite for numerical compatibility against librosa. +- [SoX compatibility test](./test_sox_compatibility.py) + Test suite for numerical compatibility against SoX. +- [Kaldi compatibility test](./test_kaldi_compatibility.py) + Test suite for numerical compatibility against Kaldi. + +#### Result consistency with PyTorch framework +- [TorchScript consistency test](./test_torchscript_consistency.py) + Test suite to check 1. if an API is TorchScript-able, and 2. the results from Python and Torchscript match. +- [Batch consistency test](./test_batch_consistency.py) + Test suite to check if functionals/Transforms handle single sample input and batch input and return the same result. + +### Module specific test suites + +The following test modules are defined for corresponding `torchaudio` module/functions. + +- [`torchaudio.datasets`](./test_datasets.py) +- [`torchaudio.functional`](./test_functional.py) +- [`torchaudio.transforms`](./test_transforms.py) +- [`torchaudio.compliance.kaldi`](./test_compliance_kaldi.py) +- [`torchaudio.kaldi_io`](./test_kaldi_io.py) +- [`torchaudio.sox_effects`](test/test_sox_effects.py) +- [`torchaudio.save`, `torchaudio.load`, `torchaudio.info`](test/test_io.py) + +### Test modules that do not fall into the above categories +- [test_dataloader.py](./test_dataloader.py) + Simple test for loading data and applying preprocessing. + +### Support files +- [assets](./assets): Contain sample audio files. +- [assets/kaldi](./assets/kaldi): Contains Kaldi format matrix files used in [./test_compliance_kaldi.py](./test_compliance_kaldi.py). +- [compliance](./compliance): Scripts used to generate above Kaldi matrix files. + + +## Adding test + +When you add a new feature(functional/transform), consider the following + +1. When you add a new feature, please make it Torchscript-able and batch-consistent unless it degrades the performance. Please add the tests to see if the new feature meet these requirements. +1. If the feature should be numerical compatible against existing software (SoX, Librosa, Kaldi etc), add a corresponding test. +1. If the new feature is unique to `torchaudio` (not a PyTorch implementation of an existing Software functionality), consider adding correctness tests (wheather the expected output is produced for the set of input) under the corresponding test module (`test_functional.py`, `test_transforms.py`). diff --git a/test/__init__.py b/test/__init__.py new file mode 100644 index 0000000000..13b4c619ca --- /dev/null +++ b/test/__init__.py @@ -0,0 +1,10 @@ +def _init_fb_ctypes(): + # Initiaization required only in facebook infrastructure to use soundfile + import libfb.py.ctypesmonkeypatch + libfb.py.ctypesmonkeypatch.install() + + +try: + _init_fb_ctypes() +except Exception: + pass diff --git a/test/assets/vad-go-mono-32000.wav b/test/assets/vad-go-mono-32000.wav new file mode 100644 index 0000000000000000000000000000000000000000..277d4bb0b9b98ff6782344eb1c4cc2f056fac58b GIT binary patch literal 54660 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

^U8dd6-QWY9K*}vx6Fm} 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
pW&Y8SkvdX(?z z*@SMK7kl-FGO2z|R@BO?R){t{kfkKEVHvm|E63keGg?QTqEBQVwp`9I~>gF%Zu!wD8O@zP1sY+qowwbXcN79`Um%&-oPDf zJanRssZK+)n={Ys;T$$6I=9W;&IdEvq40c6XT5RDSc|--RwKW!rTlT$Xfe&YD8^c^ zu;=tz{02m~Bj$Zk)4YW>*lVIYtn&iK8`v=YCMW1Uf%0}&cGrJbGxdY&ik^*RH0A<% zOp;edXIj-fNLQP&)HlDWLGv( zSnNN43vK4tr7@l$+q^UQ8m}f*ym^SVGMU_WqsVHv16E?{klt=(G6uGfJKTaK+D%BR z0Tpv95Q}z`#WgU@FrW5ad~6!#74&6jLj2k#SM$? z6&DfrDeie(-|&s_hwvu5zFo@MV)t`AyQNdxN#(3{uG!q3WW!V2{@|vw`+EuP2tU7l z)SqFG7CD>-@|TlKy@n_AXKxP?u)EjfIrKRykEx<;(RzVk{~{>Vasd<^rFrgJ^_V(|OFA^3XrU9N#{aUuAEry`Lo2dT??lZ7mXyl2~Kc|L?q z=2`iEz8rS{FZl{?YR!38?I)|Cbzyb2qqMpfL-JvzF@@F`>&DCFK#j>n`ULS279Jms z+x|~;t^dKA@9zn$@(Tvf`VE8M{Yc5ou+>y_w}uHDU-31N(uQVG>SkGa!RRLs z7~A9<*xdYXmQ_d0St_IT5+jL1WSupP#8`(&Z{WEb!3erAn3hHdQ_}>Y5VeC}uvdJX zd<%{yIYN2KfY4>NKGa6734N4(LW5-HkS3o7*NQ#CW@2eDrx*zo#u~v)!VOdvivlAM z9qAu)T>~`!K z)+??IFfMoTxpp$mc3Npuy}z`K*g>2qhiM~J8GJFG@uR96EZpBysP&If= z949+Oc``{{R|DWbG(n_M2gPj}CuYi2vaX~uwcH?nh;-tPnBt!lntxcV_D*9T?gds^ zl1S<`fT!nt`Odu|b?lPZ$sA2bI|9sHPe9Ft_c>;&8-vo+9_doA$e3Nfr{h;a!^nQTh_fY_MCIEKiFVc~JC$pWZLk z1*>4ml}oOwKD0ZzO&^h5EF*;BF;UQ(b>R?IHTDpr!_O&-`QEW0wSX~U?codtUUZ# zo{9*}m)r9#axZ@_H7zU~YTxB@?J6v}mdUi3!#CACBQo{^`9LQskFiWmN36p;@^9gNW z4q}zfEWE7wl$SLB0&>0yAA*LkhV7|mGMnr9&1|sLx{np6{@MYPXtCy8UcxGf_-fDD zL2EAiY?WdO0+(rIpaJE9|HvI{ESZV5+5A>YRi#zcRPsSSRikAUl|>%HH@Q6ca9zw6oyDI*_*KO+P#J%Sc;np>^Sp}k4{w3w z-d=g#oh7%sIps!oEKt0b!;g5Zm)9%j4)LOayKyP}oBu4Xw_h&ql>a_9nYa_%R*2Z8 zqG#N3kurQ%d=GCCSMB~{tdj{dpW}Xdx0;{DJ?f=*(|PIK;cg0eCC54)oL!Exn>$DB zl+Isv3a6vp(W!5LaT?n*+`e`?cmpl+_Su?$-X8B?gT?4Q`z)gVw3Cs}6@c6f_wWcCME?Y$ z>`nO6{N%alHF)Cn=IhBz)|8ZoZO$TkO2v@BRCm%E_NUaRl-kFqsSo^bSf%b%ANfW6{-`GLq~tGNiQMDE$UyBFsR-M^ zR7Q9D(YQ%>nnl<^YZ5CNIL3Yk?y-r%JM3QY7<&?&%~l3$u%f{a^kASrEfR<(`>m0r zoRxyyFwX*CbEL|Ll_kT}6*Hg6eC8S8$Q+dEtZnjvwOlR(c69Y%cX=^bS0)XWltn`D zmklXVE%ZXv44oGhLdQiq9Nz_BiXA~sP7fBAvx2?k?%+P`kcN~Q>Y);a&ZxLx0&+U| zJLwzYSn^x zaslZmACgxhJDn&-07c*lZHyhWv0^zpF21mDA{UPpb@_GChK~{rc~Vi3FYw_~?H^{H zy&>$7Ta=}6;oz@R)V(sMwT1O^CT&Sb6JoIyQ`OfarHb{c;kM84he8oK2*K^Mg!A-JdzrXlulS3%jY=8m|d!Xw|$ZMl;BauNCNJS_AkjmzK<75l&d90SD|rEQqnH2l?HX;1U(IoS~-=ZaU#9p?>p>v(hBBHm&L_VPpS zL4UR5`&FI7!beo28+KoD${r&w+l$2u`;zeN3^JLsO6GEEsxnR_sR^93X3itp(b>g% zIUV>2=M|sr_%f8zFJeY~?2Q3B`{U#Am9VpRIPjmk7<@UYqu+^6>7xHNc4{TY0!QU+tx zkw8+?4A_4^t^Q=Pb&#a9Oh`v7I@#P!N18fYYc^)z%mu6=zToGr)2v2d1A7_h$3_LS zGd*;Rwh0ZSLqZX>S!g{;6RJj@A&}_4;03iNxIrxsE>J6iSU(PqM81R6#b6)x9H?V2 zgALTdV189S7{=}=Mk`itS=7u8JMnMg89yWbqg%vA*!edQ7lZ=(>=V19OcI_ePsP5I z;g|~QP|PCb#=KX1WAl*vaV~xEfTy71r*Xcp(Itxj_xkBP>ixzci(3{RotUBKVhtsopq9e<${$}UM zQPvT$O1|=~td>57H8EPU??!eOGQZJ1#t!Q0y{OO%(yQltW}EjDO3? zJkXO#WpioDEixfSvf1Q4>;cRr17v-=6n><~7bOb32|KLay zN*AToDvX~q$jWNCtg3dSoR?uuepN;x>dr#=ULRH`(c$^cFwQUhxAwh7Z?>CP8KOSYASZ0dM~+e2aF1mjnHa$i{{F zGrod(JORt7&7t+QT=XvuULM*i5~oFxEP5MKOK(I5>CMS%L}$FOw(;CR1-+&I*$tZ0f z)r;A#R@csX)kyw{5@WBf48UmC%kW%<=^x|{zk8k zKO8>zjl7reQ%;Xv>zarg(pmiD^@C4-5BT*p5T}6h&`dn?O*sPS@j-u%n&veo%1uc7 zV-@tHQ=biRF0rIeDt^^2!&lga_ypVHW9|EFj=crQn{(NHdnU8(C3t2NW+=y4b|BQ| zbwa$5Q=6A_X7RetVcyv}#HTpZfYx1+N4O4)axXFB?ZsDm7h=8dW(mc=?3{>WgJd6` zLKV^0siJyHQXONk8nDmFZOtdq79tk{pS^D|A4wEaDk^kOEe`Eh!$NCSiO@RrEw~4| z>zt|)dR;JTRPW2^=AJ13{V~*p>bsyiEHBbFw+X5$r(l0E-RYXEj5Q*}BkK_Aayt zNQ}+czL3R=gm%-YU~@V?pwR}_Ve$ZR858TZiOKT-86^dDU4S(ArTPOt!~N{X>SNqd zbv1UbDiqs7Ws6OwHpQNmYvcOM*l<=E<-8I>#C3*ek9aPk;2kkW>{ROntdyYjvdSN- zpWKN)KUf9eh1Nny=jn53*{FI2lqhxkyhxDYSOim7B#P!SfR5t&Y z>g;`02i(spiTh3Uaek>=w!;2jB#8jFa}v8b_Wy=JSI!`3oh9U)y8^aBe-q$u0Udq@ znMOvzXRbGy!8@VHbtGH#KBNq=Q@R;jNCD#>nWO7;tyY$f=0j-(wvTG`GmytqvUjos z%OGn)-!^1_h`OwdD8sslbnJlmMH9)>w5eP`hs%C+m~4*SgSxbotOX3NTGSQQ=|^}{ zd=Z6c5}AtjmJYGhZTR`FB{xWaSRGd&TUa8}iN8{x5W&2JHbYg1yq#vX!~ObPcP=%v1B2K_XZx(ts8r14$DyRgD0K?0TRi+#>w}-B1#i zg*8P@x>59^73EB7s-3`Jyg~1g&-4&A*#wrJW#y&V0^Xe6;KSHczLH(xC)ry5nDyb` zSOM;_kI=^du-|wymY=6#wfJ|SE8L-z`3bt3Z=w5u_;8x{z!> zFp}8;ueC#b7JLwssu%E%mOO_<)O1lt+b%|82Yrk7R6Nj1AZpJ6>^3%6mG#7=t$q#Y z-J>wxO~5wk{nJ z+U1p1eKDpj;BAz`?JQrox#Ugwa9(hCA?jc|anl7HsyEH==4J8?|EhPxp9fE*LEc>1 z%j=+qdTGfb?;JVrwV^@(1#RiqV7vS|jEjA&rZ|E%-yN9GtYufkI`$ANG&e*H+a!MH zZN(P;%TKBG0IJx1?>_uZ66kx~RC*ydtQ~Wv!jdwZ};iDChnj zc;=1{Eb#UQn)wd{8G*zI9IC)(xj#@}EehOMV**7;_dpj?JrG5b2L_QF)}Lgmg-EPc zQBuZAPD)#0^@sId)w4dRTF{%NtVoi^M4H7&VJj<{izqVb0>9Li zz-=`pxL1`AEmDs{qg1_!9%^Mo8+AIOmD(B6T{ViBs#b-LskuQ$iU*pJ9p({|+{j9Y zY4hk~<^cbrF6#pvsoi2bOXlxk``y3U2B$xJYZqnh?JqR3y_|-_HEA|mVz=;LGSFE7 z^!71is5grA_9v3x#dIRYOzetHKt!lM=wG$TX_cNlRL|8zH4~HvYaS<|6PjVDK_o$R zrYCAOqM|Po*)gV_kKLWSz(DRf6(q?;InqGZCJWV{&{xx7!+(fegy%$0o`&A$RjHwM zq$X_f@9~+m53E}s!Uy0tHk4L{4MR_iGXF*tsb?4sR+ODETdqomiQ@1hEJoUkYGf2p zxYmi~gQz9vQytdH0lAfClN)I-xrBa|qv=M~n$996>13LU4ut(# zMfeyz=c#~xQE%x^4Se}>$n$<#;K??T zqeOqKnNG*r?@C!sZjj61aYHe}AFSrfXf;O;K>V)HK%8xlI9eC!X;=e%m33Hd)d0In zY1l5cfxcC7Bm&XEa+6}JDrqed`xCaSnZz)x<_;zMvEO#j?}Ir;cX9@MaU*04QVDhd zzN$(7CXGlc>sRP+B?{Ea64!G%S9Aw9*Du`j$Qi_~VY@>*YbFJ=Ue%T9V(%Rytb zDe#KBqO$8>Wl`N1<@H3Ox?a_b1S5dJ?aL{>2@p-*%Vl$J~qhTG!S`xH%9@ zwwZC#nQG*6ju?~ePewSL+*}kcY4#7dHYbP2nRmk*%zE}!Gi-k~&p07#wVNBrjtzjs zH_{sKZ?Sgxx2-MyPeg?@15Ny7fuw$t0DQl!zTRmohu6W1b03-S-F)T`w~JwVll9Er zVy&XLf_L}UVSV}t{R9umN`5)A(%%M8pOUIQ_Diped9oq?zQVt1g}Nr1A#!j8O(M3_ zfBYgWJAA}{2kntK$t{_UXOt_k@>86}2#N?K30MWuh8^+0upItcKG*A^DL20!<-XF1 zJH}WBeBYYR05gem#{2?&-$!;z>o($a->~agSM0y6v-S(?pxrRA*1iy!YUdAjwxfcj z>{Y?U_O@V5cuDYkxKl7>8^P-K)WCY%v$8satn&`Hrn_6sK3*5IgP+fAAc&bqeg-!7 zFJpj8Y5u3`npw$YvnDxdHi0g!O}biTG1kqCacDNuIGBs5U{NwVRD)3X2{uDi!dVfk z$h?R>q;AAPvNyDYoCvNUV*}GjGOP*ALF8KQ=T zjFzn(_;}lz%5E1?&%&eC!|)T8#;!(|BdSJCCksvNPNh%W=X3+S&3pPKSymuIUlW;F zYiZLv*uN{F=Fs7)6+Ar)(HANu4Xea7Mx~+;R6)8*)u#2Zm-hx%Uag^j_KMl?IPOEG zSA>SVXC#X|lr(lsvfiGp64;61$FNj}!iDAGxc6d1+`r;|+#xYGd{MNs-->QdB00mY zD&eIp6N&S(w=~oZRa!;T&MFuCOU1DbY8*eSZXj;)7aj*2mH^qvGhx5A3^~b~p+65K z{pmbJzS&38!?$I!%0xBwCtU(vSVcaA4zt)3k&9gtm9W}a6JO@??2(AX9?C8H7;CZj zMMnA*u|i$=`MSH?=YPy}Q7BxDyYNTvc^x;7t=h+jKNH|;*zqkShAuvfTR zdq&D>hsZJx-vZVZ$&Qp7po$%zA(@yNXbGeu^%VUHz^t7Yow6R zNq%3c&c3hCfvO7vd~S_Qkvb`^82L{Ld`*4zibz!k=}e#+xrAdRQ>q)2>NqHfJ;hp} zkwCp!13Ch_gx^>@!Azf!^%z}7fr@jbUNcTcgA7K=D3tpx(ymJI9`Xt*jr@grWdW?` z2jQug@D@xUIq4=1@)=+4iAt)h#054a-k}r`5_Iwb<%vVx?@=Fqc|zsD`9{L9!laQd zNb`VHu&h^VB+@caw@s*bbF^h5&}C1lS%?DH43rkQ99LYWTDjo4Lr7VNl3g|-rERHR zg{9gOR%&sWlD%Psv9&1~k9)ZssXlw&%_&qa8)p~p!+ z%0PV^g12kY4ldfDIrx4Qe9yooFpi|sG02&vF_KQFSQQ~8fq^+6sFy)V3xgpB7bPcf zy`rwv9z2^tqhu-gRS5k01)jbH3GlcQuC3*aq(xer@mysc_jI8~A}ww*(#_;#3ywET zr9PTMnU+umEJE5_j4ZG;a@nE;0~5p!fjr{4E-X@^SiF-C z&+joIPo`A1A%R~3o}sMkQRY23zk_Q@aBrvy2Re&mABkh{oRU;Qsdff^l_w<}dn zLTE40H=M5n_I6~*$9jQOHIQ#Myz|!JWESe47PxrxQCF~#v_k*5gtl)6ekBK=B7h=O z4g5V0UJnA#yW$9|GlGvlSq!S|Qt}xuj)Uyz;O%J06ihA2V5AX;emWSk{2j8_8FG6M zR2+E>g=|g-b;h}YzB>ZfZ=z2|;MwAM2N3|sD9FWrq{|_XT^yzEV7~r4@;wdtYXQmx z$_|``zL3dS$mR~*U*s^d4&}Lrce6pxCm_wIkek%#4_VOHzCbqmqyHTTJphl-g0Evi zh=)W*fzJ=n7mMK8H7HvS&`Gq#pGv8e=>Pwr4!cmknUayNI2Oh47_7Ue!_G zGN8IRpMvY3aeWw`%a8u&Af4-|=RZilE%MQj=XB6dP+`bZ9Zg}q9A3frJp=R=WzB=< z8shn$kn^FaLws8CZ8`#NvleX)ycnSME7cPGDTa1R4@&qy0&md<^>97`_YZ(RfHI>^ z27o?;rhz{-QNFaO1DX!s8HzenST<3T4sEmrq@j&6pj}*)V+jadi&Vn>KaurFlxHd4 zyNNXNqrOK`rqQ5&pjnWC8(8znj(fAfOCR(n%64f~&r48`~39P}nkwpB5d`w!^N>X5}+XrHc-=k>UbonA5)-w28C z;!w1~Cwx1aK@Xe-9|~|z7C`5HLz|b^d^Ht1;x1%0htA1J&{^ozAJCmK(1ll_Lna}{ zWggIV=+L2%{;M*&tgC#=J5ZCtNUKYH!7|)u}KYgIr&O?tTfZi+*{n-{e zZ3y(~Tp@OlL8ncHE=`JSOYwYB z=+ci!1Mx4(7^GPb>Es1v!FfgK)={{A8NU-lSO0-E(ZNW68+3IT)D-C)MmouYLN$TD z9FF<=DCE&Ji0=&UwTHf*iucB#e6^sDqu31$cWC@?H?nO@%zXfm~EW8r$)mO^)=3Aiui~zDp>>LYtA_AafU> zL-#-qpMh#Y7GrSzHgxDylqnI)-W+vUi}dcs=LcB<`VmQtKGzu37c$ZvN}&!YHO}L8 z=M2aX;@K)4W21+VtAprci!g%h2Fe9`h%$~q`O|`qp&zw|jM^ycLgZ5dvik*NvEz{I z189S1D1RZ;dpp|T57ax1G0{KO`OQS%PlI-!1{sUj3ok(@K|TMcLm8=! z`|)MIfOo#4trDQ$7e*WPLYi05HVu%6hc-Wsw*L$5R1cIA=P%F)cY-FOKXw3*YN0)9 z;@A_{j)KbIyZ95&-9Q@G&^I5UE+3HoC+Lj3kb%FEZ~Pcy2FkJyG#uqgfpY$Z>rc== z8BzX@DANYiCkFLuiTb@j8%#r6GzV2dnw8NW^+DZG)=6lGHMo8P&pg33d?@h!f$jls z-k}Yfp+Db5-D;t|ub?m2L;F8QKAq5)--4Q<3pXi50(I0POoKzlV zodiDa#e0vC21D5@pgt>+eoo}`8sD9(pcg1tO61oAdh{mhTo(LX3Hpe#F%;LA;QD@CzW^D!jPf1D5uS4xQ-hbFcSvIr^iyISryy+?b?uEhzl9vM zfjnHnI58(=c+~&P@bBn9k0GneLDN9%p+mph0#OyDN(lbk04r|e-!%?5cAXpWVD!ASq`EA27fcg#ry#!AxpkCwA4y!>c(9cGJUo|1SNm0%> zsQ)#T^*#vyR5?656W8D4nOdm#G1RLpcyJC>9sT13c%KzAFa>;w|CV(@`#%65ibEF; z08NHI9SJ?!8v3*Vjt=e}hh7;2sso-C`hR{k1<&T-_hVeohj+%}`70QBX&4h`hAzzn zooazz;oceC+mCVTS)><@-xV-^+yH%*3wrN3^ldZfy)V$GJuntMgYn}R=+!p?U+skM zYXN;416?>3_p{=;OL%@Ls2p@&D(L5grbd2)4vp8T)l6S?z`cpkt$T4V22>gEEyQ~t zu5YNjJc4|l2Q>ILQtWL(k07tJ(4z^VtIOh@hA4L(v_)Rj@h9eOo6&Y1AV)bM z8wU6RF;b~8uV{`wdm21$jeeQOqM9qzXwZ4|*%XkMUY) zzCXhEu`&AG1@J5z`b~H6b|!c`54;-%st^9bgM*yJ{Wjq7H{>}8G7<|}>68yCwQzHst>d`A&q4ri5(H zg+6$TxvB-3`;OnsA-Cx<9vF@Lm+&k@ISb*vwrHotXv;UyM|F|zZRFVlZ5@HO-itPB z2RCDf4&463F7(Mcy9^nm9n^URD1PmrKFU`V zlm+LRK!tHVex5TI^b!=WcMpO`rNE=}NT((0_Y-Nx&sFlEEZ0z$UdU4*?;$A5Ev{i) z!+_VNu=j@b0q$dshG6{8f&Zlerv|zke7mUP=dThg?~L>Tl|q|kK>FE{PXq97DbBy4 z-enAPX~5jzu^w#qTws_&M-x=$bdU_7V4<<9G?zw?bw{ z;$9K_K9BMjgxm~89-Gi6SHT+_GF%*eV*%Pf677EidUFj+L+G;e~aWdL)E@(Z@FMuG5svg?#C}glC>T?M7%Y}N61sz0PuA?j$ zK$}s|QK(-n^uKf<2hYAjyWB^++(9`X;Tsb_hEIlP>fzbtD1RJ|tx&g1s8?0U;5G20 zGrm~@GC39U01+hhpf|>X7xSPy=R$av=--&L3yAHXF|`!f*M0_E(4u{ zUc3PPxd$`_=M6!T7?|s9gVVVM%k{RuAk8!Xf~1nlnQ+$8``c!e0!p;Tq z<|Od8ICz{A$4roky76*>zWWKktD{e@15e|1Us=2p75^S6em-S^Kfu0FmB8aVpt|5& zHKbhvlpYidIXH&C)E|@v=O-aE9YG3d&qvy+L35xB0PRGELEf+_K~_PJwujEFiep32 zTo9IF$voWq9r75&yH6pz`yj*9kZwKXX(O-Ekd5c4Y-aR@nvjopIjINAg5OVYeH`xR zjDH5@+=Vi)!f`X+I}M7LI}gVYWHcdU5wEGINOu*eCa%9nU1y>E&2YqOHW`ECEgVbZ z{vJ?yr27nc%t2n&AeSG|)<9fPC(!P(kj>=()18k3wh+lF&b?jKOP={wu@h*j30NNM%%5!aW2|pDrh#&ci`F&99!bK zccAHbw=B~70osK0TO*(NIr1dX6A)g*t~%NS6hHsIhuh_$FP5M_KT+@2pm%8FdC(bc zK&4QgwBS8QNBfNQ?|}#ZLOyoj7_VRFVVt%Yv>WFiajiVYa9i+R{5tJAv~gCXyAe7d zANX?^ja(D?KSVj2qdhKyGNFCiLuMzTFUODPd*XLa{632|tA+cQ@N9Lw6R+=j;{B93 zK0752O7af?S-ZLOtSjUoB8KJUavWa69si|DK-5cj6$9tML9zTpNq~qw#w@ zcrhKv<@kLF*B^p@;XDr4?&I0HpzOG|8tKETjC4Vrj-ic{p^p8*m)B_j{%F)ppzo0B zhxpdrfqXy2`5VY?G`@En{E0+ggZCPI+o1>WZA^{+mK5(K$Gu#*-U8QG<2Q`UNEG-U zhqQ;IEirY21q{Z0$hSE1AB}SC0bk?ifv<5MKL-DR>#soZ^R*MWz78}EG#nI#`+wp3 zCeU-7=S6*Hqkd3lWIPC2Vm^oVL0cz6yVnE_0WAP+1)T$Z0blY!e~yD*{Q>F;UGoNG z%Xl5S54r~nvZMsYge^fGp%3d|Y?unV@j7&66vm#JL67mydb~3MW77dR4gyU>A@*ZE zAO^=Ocy=k$i`T39q0`zUt#P15NN*d`I}dsX3PC^S$9e#;t4RFXz-Z{fxzM+3aNG;J zjO(94sh}epVEh@sUT_@x^BI1B#@O~P=px3XvvI9B=ooZpcDy$d`CLUk(xM#k<+}x4 zS_1SB>h7a`DxrP4p{)i%76zdmN27nOMZfq8x$gj8G0<)B@?ktracv|BOWSHNc=!O6 z3eQ&n4;z4*gP%>IkE-K)R~R}eHGT*14b*Uq!0!~e7m1@l-@A!C=7Qqa?J%5BThPbq z;P@7K4T228I1%4-v>9aX8pfP`L8+iO?_z$m4LWoybm=|l)|~jpFT=eYkjcxSv3T!y z$XODk`w;nHhZ-J5m>;2TTancs&_YoBST8ZI@5B9OC=-^L|F<{s24zZ!x->$)R-?S% zKn3u8N9e>67_0Wd_r4T|R=SJK2L))(aZHG=+iQ`aw|10C@wR9)&I~Cs_z@M^IR7%;Y zkYtxNk*%_ntPx3wR1{K{5JD)jMUjvt6tZWHvZSKyYf2H>vTu=||NDIZzn9m?%$pt$@3%G&cqs(^Zm%YAF9&*eElgw zzpJ2;whrOAm&B(B$kIgoxdUqR*~Mbg{~#9|&Lmbn>v^<Nt=L{XS(U0HQehYoOz#cx)&xj>&qLY~Ge9?H^Kqr%~dI!am z``PYbocgFV-uX|8Uyl(cjpGV15bqx34>j2LVkl`WzgCCu01_vRe;@5|Z*%LZ62EHy zLH&E5tUJk+j=Xuunv<;luts99^4ZEGrmil3n`gxV_xu1m^fTs5YC_CuoK#PF_r2}D zZ`E;8U3YtDsNkI;o^`SAw~F1yvu(M#msiEC#R+l>_f5b%rSZ?gc*n*^&*P(kIBWnk zm(Pvgc6-nM5HB`$-TmH~FSuttuAH3qny=f;S>dg|-lKb_O`Ukfxu(h*ru{ehg7fb? zUZeb9DCYj=>Kg6u3huA1e~ zd!!fH&hL2Uch?^?=6;DaxkEZx`P0g;vWF4c${~&!&!%GibFz1$GVE$Mj(pogw;-F^ zfjbA{(I@d}QS+qtLq&L1`7-mUCGhNC*Ue*x)5tlMt&P$~8}i(Sg9eK$w@Uxu7c1CI zJ1MtIjv!}YavpZ=_YiS)PRHGp?~|5rU3=FLmcHxyn77ZPp5^*mMcv=I=LPqarn3sr ziEYPxWSraJn${_{iSPMoZaz1XJzjt(+2MFN2(k8+4{{ohe+jid#YU}}Nyob9I`-R~ zP5+?%+K>`Ys{17<2r-wi9ELz+$O5a4)AJB>9_#3I5=6ZE1Kg=>2$XbP685WO2|3>& z<1O0i4lA^~k(|?{bsg{KS53$eu}yE+7KXp*XeJ%Sy4aJ(KCkqQv7Kv-pQnoq^s*Xn z^fwkwjPWDJ_)&OP+e4Md8p?yNnd+YGUR=Y5veESfd{97J%lLD&eS#c=`0L#`b1FUE z&VHZ8rTtUhFY%HzpX2qov>|`q&8DCA?tg;+k92=sYt;F1T?X~|o;2}yB2CI%`Ye3% zrg@zQ_3dx%j>Uh~rG_`TP2YZ$9@D2H%HGrO)B0SGjwZQ&pY(e5Wr91kkqZ7$Hjmt$ zrLo59SCdlWziRH?fmds(E7mI0>TeS~y1-cEaidI>nmemBD&u)QEz9)EUKJ{yRGJlDz? zhgHU>j@WV^PJKqaxeE8B$CowmP^<&3fUDxkviPYre)HvT@@;(A0q?~-dPY3B9v{98 z*Kp}jTv{0Z6t^xn&pH>Dse8LMu!}Yrvy_S6JhAYXT zc=k73UD7`M5!&&ShxP$nO`fri)C_0(UemWpxE!}$wSIpAev_YJy{SIz6{pt1sSC&) z^1ZAtGu6L^OuO`X4cnZ+UpvuF4f?u|5#7Ola^Qz2#18YthtC+h8UoQ6zpci-7W>}} z5l_yt&*Y?M?rp{}t34)nK*VX;jb{llTO)P#b{y|>6WKr-{uIyY z&FZhIy$$%VcFf7LsWR4;CgI9Vcyz4wrV^LTmtDM;oMYq4C;pDp5=d{}bj+n|$>x{s z>%hNFaB<8b*54tFSADJd%w=-6 z<|k9x#WL;AAZs^mm*PLiv^^PG^0_>GF5;PqxS}yV-L8+{)8Fg#c$+%Mk>f6yrLFpq z6@UDT11^#y6&uP+zGvubrt%Er?(15gpeDj*gb2wQ^!_wivS|AcGJK97Te4X%I?0~a zmA6W-;nC~()P6DQI5u5b`A)iQi*s+}-}C9XE&UY{OP$lF6}Y6gK9z-E^`Rquo~6t7 zaFPx5q055WKS!4RWI784^r^Q#9ai2zU%!D^+kcB5V%}62aH@S>a3lPq>^Ql9b$*p| z{cun&Z4INN!|E!+H(qBO5m#oQgAVj@6n73{^L3#z-mHm38?)n<(k6~;@QE_c6>(h| z+}g;w52R-tcQwX&>F^XCZy@(HW7)~LP ztMZrNY57O!s1Rh7k9mw=$iGHE=BR6ueod8Mru-Nbcg-Mm{O$T@aLGozT8;h2dw+G~ z@trZMif>kk?52j z{gGXq{x?mcpm?(z8{C0s%d(r8>-z`KK9)>l*Q$3rywr-HWackZjC=5KA2ty0f{&|f zw)WC%qZNCZj~g#r?|cYPcE_b_F7iSAIpf0hiDnmEf8pQcYtmhgJ2_Y3lJ^bo{`ZP! z?;&&SP5Dz@W64%Xzs8a4G!!FKYrZiCHu4igoO}!h!Ui&CU_Z5}wi^thmrfAty+1ow z8@_R0#Dt@9Q92mKjvu3seA+1;{=vb%Q&v=4Q?z?8AC38hy8J2jGQ`|l754WRyMCAb zQsqz_+cMT{RpR4f}L#jMck0&6I0l5UB2Ltz$RmjB-W6I)9)$m zRN=2f=zbf0-b0o?)(4YxIg?Kg;g3`N^~LbPb}5`{J(S$~+@-ClbnqN~U7@S?eDy0n zyMrBXp|7u`1L*Gwbp2rcI_votYYLyKKehT}?)xI045pLf{9r#W{SfLyCS$hWyZ=HyG1hz7N8*en zQa{0*>*q0ihODPsVLrmPW~fhXV^h&^&d7?FRSM-_cmw0 zyN%aV#%E7z&qVR$5ggk-?bYOY@njdAbXMHh0y@DzZ^H#v`)VfD&W;|V$~z*(j@Zh{4;`&?&+^4`{UM*jw`26BZf_#7=~NZrMs4F z>7JqPAC9A6z}WMGa&9QZ8q25J zy@TC$$48sgpHBUSwf7+VsTA+}V$s(wT6eo(z5arC)br+tV9I%M0t{DH-{!$$*8DSb z^egyv6B`^s_6N!LBRq=lW|1#^ycy1mbO01kbMsS%cibb>TXAGjUeVI-`0;-+?L%jr2XTYFEq_muWx zA5JCy_PcsJ@$~!S%1b-G4`MywD4&=Kbv+mNknIUBHl6RB zqTf7F)mT2Kp98hO*;vM&wkvdTh)&ZOt9r`fy)mATTcH(S{2N}?r~Ob#9|yr|vc|h> zZhCndhH2wFDRtuvV-98D0lLbrAAhr>c!zuvzx+XtcEr!2 zdok%JbhFyr>L2_#_U>lq!{wnFj_sQIYVs{;&ByNLV@usrz%||Q#vJwSA+OK<6BYeG z(m2KQV20;GM`%XgHf*IAjFVrg4>50b-neEro;BeueO#oE=iT=ZeGQ?vKk4rwdg=u; z)E{x)C}~s2H__uXeX0zLEHz|L~H5uKrT8z?`eAkm}5c%T$>J>8WCflQAh-_^pp*1nWi#M=<;Rs} zc3&O$jMc_PW7blgd)3#{I9$ZFBXL~;G2|S`j+@%yy2*HUJpP2i`&;}?{4jMhplkG*tv^1b~W5=9<@Hc9fC_^UUeaSApeB&U1HYQQ}qIFjdiwC z;@0EQFa4~{zWi`SaxYuhZVb+`p)$thQ)5(^Z|>rQquG3OC?tO#zpjMg{PcBW+6jj9 z+jV&Ob~f+|KiO`KtMQ%XPztQ`NQo zO3XcIr>kdk|I4Wp(|kj648J~Qf%A-b^?MHf>xI;b!WYx{o2S-`%>zvJt!ZX)ZddcJ z8!x9x_zyGUgN!U4Bq;{xW>Epc4@--`<#!tgVr#}@gnjchnS~n$Ug^5*OUEb z^)^-S9Q{sBR}EkcUyW}SxVT?d^GytY$_lz;9YmZAvA-g%YbW8ZV)$gS`l=ZFSl{fU zy+`6XY@c0L<6l6#4RG2R=gvFVioN{8UY^qC8qcKsI4a)1zf)gY?NrrJZ;0n$4*Kd# z7tFytN+KohFN04z!7%pz9<-Ftf^X+KUy|;=ptrkVl>2X{^Y_$!o4!oZUd)C1blN+I zXC0J-80Y=u`VL|}f0Z=W`9jwG&c_(ff}`}7+5IKqQF^OEZ;_UB9D7T0InM6*eyA)T zd&k-+Z!WE@EaKv|+IkuO)6M|(-%2-=jM)>$F$0|DXUF(k#JaZ|*Rsl5^SO_tn_PD@ z+pgoDvGjV9j%(55SNyGj_r_^r313epXNfxth%rCbe?RD$eA0sSXnKtGz*{_nD&W}` zjJJp9*884Y5dwjNdcgLZ>!;r!?#0(FaAcs)nch1$;@LD}qgv(; zKE`85@mV=zJ%m61AuVI9--6(r)y94ajD%Rn3~r6Ri?>1-b?n54r4!&a zXe>T`O8PwX#HZt>i{VG*vA%Us*)_=LzUJPirowq#+lajJoPU8_caUk5=loE)5KSkEsAR?8ROJvF>_BSw8XE)9M{bhFGU9q5Th2Y#;x! z)A8)|2k9O*x(U8Cew`iXVb@>bo7khh+I{umtokNv>p5v&^`GNgn~iC#-OuG~G5M?mZoFF@wT&_&zt zz(DyoQ_AqBK3#ClH~KsbTEoMRbC55slnRo5@Gf}|JylX)$lS}h*eki*@pjk$1!t6B zg7}wN8|CqLM`JNpJO9w#6Lc^Y-=?CQ*6=m`+`!H&@Z%<2p&2fyhAXmpKJEXXKATE& zxb9bDJAwXMxIdqIPHAJMdi@GT%KkfHj9)gpKG9SAmC14o{6_A1^e~7{+CdBX7w9v- z*Lp+#6=hA~arsKh0-?X=5Nmzo9Df7H;1>1fQ-2|8F1omCOg1T>=(^WEXZ+G`qKM<$ z)PKQv#PCpcdTjcsc%l5`J=jbyy=#u8F(%h()`aD+s=K$_sM2>OlAL1F(4|5V}bP}=o4EPH68UM`AH+OEHG}fG6fcP#hzHzJst?8&U+2ebp z*W_E!RW*pcVs1(9habrkdzqGNcZqu!O6NIV04tr}3V%bqE5w@2gDHAXBq|$&vJiV) z?^jkxz2%`11W&}?(*tl1erSa!X3+%`5l5Magz4;kh3C{#dYdfm?zkGg-R#`Yt{dk1 zr|A10X?(A`U0qAnI~m?3$1B>YC5`#uo9H%pe>K_1(A`V=@euhV*8h|KR?wxtsOKAI zGRnsquUARmUVD#q9Q*cTFJ5+<5;r@=Pc1CVjcUzVfrPSLrami!8;v z7t(o6x;|&z78%z8#;ciUX$b=tdr!Z{vF#xXUt5YVTS8{s8S`f=U^dLdjo;zglejCt zc=T2Lwb(URT^oBRo2Vzgy9{n^0S`lJSmfF|u)}>Z$NR1L^+7zi1TQ|07te}K7uahx z6#B>yw1;4#`Po(S2k`B6;?%5o^gdi%1d6+_l;bMO8^Y_#Ccr**l~V5)>aVP=6J(yO z-KJ#7pufwYAzRx+4-wbD$<{{FPwWZoBp-7L+4))QvtGkKV{dHy_Q))DyFA5KeVeK5 zBrpSf={Y7X3-OKPJ?gnl9d?2H4GVLluH#Ak)f|-aQr^IuIT!PFd-!lM&%fcg^*np8 zW6VB+wPK20IAII>ULfCxtv{svu<%L`2|08F_lSd%FWuHy< zH=!KFo~|j-kPdE={$RYu(92uKtA|)=q;!Sj%TUqz_u*H5UR*sr_2OIoxXhpL(pK!d zFQb>mA=-|ZGd2%K>5Md|fF&iDB2eJO% znVw#jwsQO;Ep}1s2kKt#OR1xfiyj(XcQrZUx-0%Nn+{o<$?tautI$(joLcYte^R)$ zC?B|4`R{mjF1-zKPpsk9;}Cf5q>4b^^2vc-3Bq1%o6 zH32&7Q!Tg${?_~=y6OiJzdp{l9+6gY{D^Zk`B&_veoa|$@*?R^j)OP1!Up+u%Hlhf zNPlp=8TLCD^BA!v5c3c*jx)3!zvFOH{(7>dBUk7>o`2V;l!X4{orzET7w6*HR~25Q z^Y|7Zz9;(~ERowIVvi~GqMLEBRDKs7T!K5D*Sw$H9_Pq9mSe2_tas zN;m?yaI|7LwhoSME8iFAj)D2gwkx})tSH`n4&M%yu7Wf8Ft7OYDID2b+&Trm#lidF zlJeVdY<`^kFg|Sz-5dwcu9ogseq7lh_(}d#WzFEKy1L=+UFy#T4Yc2jtkd*uGkth8 zc+bKWbex~QBQ9wLS=h)H<2c-S)|K7?Tlm|%5c?y4#-FX>KYTR@U-g2v&=JqRgDYn$ z-|xLVzj!ykGl*|;@_CnO!+%G+e;L1xwb?!L>y*6@56CZZZ4vxDPCd4vC41n-t2lB9 zl)<0>;o1Y{U4O%`$8qg7oO_G%JMrml|NNW0UV2LT9`m?soty8v>8_vSzRh^~4)p}@ zo^nqg^BZ}!@e8@9k+U0ls0Xy@l_|1*VY&JJvPb)pcW{-*q zPfKG}`7Y&UrLnH?nCl;cf^0a8vf$U?=+mb)ol!v)J~9f;pa z7|pi_!VB^-j}m+R7r3^Edh1KetGkqXE9l=-(&+De=T1XW*SAQiEBL}#)8h>36y+n7 zzm7v|InJ*<1AgT;VmZGN1?62+S9u%dJzW#ey>adt1F>iHC1sB|pG|s<4D-mt6tP`D8hk|sL({WBZF6em`^EIuN_YsqhcJ5QF%4EzfS6~fKp(B>tDkf{U3^U^u~#PMV(PKg zzAyvUIX=iv)8fz~IH-=awe)3N8f#&VrGXdmY=8LN`7MtBaqeDwMC#((zDR2U>;o!F zWD(aEf|v_^48J`Ib@A&{&{TOl7$`r>+Sgu4FSf0S3pafaL!z9{Pt94 zbFpj9eGU_-b+gvg2WH^OW9CAu;M^}Tv*dC8tifN4c)na#KAS(sp0cF-WX@Ardw9#Ss1(%&qiw{$|LSw>D&SN z^U6=dHu>q$9U3}*2=d8iCreJ(mXLqe{Si;EmOrBWM!XyApiRj5HVh+YJF;Xohd;}+ Iwr1l00LVQ`ZU6uP literal 0 HcmV?d00001 diff --git a/test/assets/vad-hello-mono-32000.wav b/test/assets/vad-hello-mono-32000.wav deleted file mode 100644 index 1822c3196c5e1b744d07c20bfe65035b76c4db7a..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 275106 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ë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 diff --git a/test/assets/vad-hello-stereo-44100.wav b/test/assets/vad-hello-stereo-44100.wav deleted file mode 100644 index bd130372e7a7e0e14f2cbbad144aaebfb52e297f..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 937862 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

mD3;xa^0U+#m?53R(qjU^+OYr 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

O#Ks156 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

t+2>(v1jgwu?**SzP@v-yxZLj-r(m^Z4|ZH$(h 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

gn=dmp@zLdFY*ImOd%fI}f7!oTm_SEp$HI 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≻IX@_PO(op58Sh;{9!oASziw;vah! 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

-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 z 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 diff --git a/test/common_utils.py b/test/common_utils.py index d3ef58a51f..5d1dc8abe1 100644 --- a/test/common_utils.py +++ b/test/common_utils.py @@ -1,9 +1,12 @@ import os import tempfile +import unittest +from typing import Type, Iterable, Union from contextlib import contextmanager from shutil import copytree import torch +from torch.testing._internal.common_utils import TestCase import torchaudio _TEST_DIR_PATH = os.path.dirname(os.path.realpath(__file__)) @@ -78,3 +81,104 @@ def supports_mp3(backend): BACKENDS_MP3 = filter_backends_with_mp3(BACKENDS) + + +class TestBaseMixin: + dtype = None + device = None + + +_SKIP_IF_NO_CUDA = unittest.skipIf(not torch.cuda.is_available(), reason='CUDA not available') + + +def define_test_suite(testbase: Type[TestBaseMixin], dtype: str, device: str): + if dtype not in ['float32', 'float64']: + raise NotImplementedError(f'Unexpected dtype: {dtype}') + if device not in ['cpu', 'cuda']: + raise NotImplementedError(f'Unexpected device: {device}') + + name = f'Test{testbase.__name__}_{device.upper()}_{dtype.capitalize()}' + attrs = {'dtype': getattr(torch, dtype), 'device': torch.device(device)} + testsuite = type(name, (testbase, TestCase), attrs) + + if device == 'cuda': + testsuite = _SKIP_IF_NO_CUDA(testsuite) + return testsuite + + +def define_test_suites( + scope: dict, + testbases: Iterable[Type[TestBaseMixin]], + dtypes: Iterable[str] = ('float32', 'float64'), + devices: Iterable[str] = ('cpu', 'cuda'), +): + for suite in testbases: + for device in devices: + for dtype in dtypes: + t = define_test_suite(suite, dtype, device) + scope[t.__name__] = t + + +def get_whitenoise( + *, + sample_rate: int = 16000, + duration: float = 1, # seconds + n_channels: int = 1, + seed: int = 0, + dtype: Union[str, torch.dtype] = "float32", + device: Union[str, torch.device] = "cpu", +): + """Generate pseudo audio data with whitenoise + + Args: + sample_rate: Sampling rate + duration: Length of the resulting Tensor in seconds. + n_channels: Number of channels + seed: Seed value used for random number generation. + Note that this function does not modify global random generator state. + dtype: Torch dtype + device: device + Returns: + Tensor: shape of (n_channels, sample_rate * duration) + """ + if isinstance(dtype, str): + dtype = getattr(torch, dtype) + shape = [n_channels, sample_rate * duration] + # According to the doc, folking rng on all CUDA devices is slow when there are many CUDA devices, + # so we only folk on CPU, generate values and move the data to the given device + with torch.random.fork_rng([]): + torch.random.manual_seed(seed) + tensor = torch.randn(shape, dtype=dtype, device='cpu') + tensor /= 2.0 + tensor.clamp_(-1.0, 1.0) + return tensor.to(device=device) + + +def get_sinusoid( + *, + frequency: float = 300, + sample_rate: int = 16000, + duration: float = 1, # seconds + n_channels: int = 1, + dtype: Union[str, torch.dtype] = "float32", + device: Union[str, torch.device] = "cpu", +): + """Generate pseudo audio data with sine wave. + + Args: + frequency: Frequency of sine wave + sample_rate: Sampling rate + duration: Length of the resulting Tensor in seconds. + n_channels: Number of channels + dtype: Torch dtype + device: device + + Returns: + Tensor: shape of (n_channels, sample_rate * duration) + """ + if isinstance(dtype, str): + dtype = getattr(torch, dtype) + pie2 = 2 * 3.141592653589793 + end = pie2 * frequency * duration + theta = torch.linspace(0, end, sample_rate * duration, dtype=dtype, device=device) + return torch.sin(theta, out=None).repeat([n_channels, 1]) diff --git a/test/kaldi_compatibility_cpu_test.py b/test/kaldi_compatibility_cpu_test.py new file mode 100644 index 0000000000..cd85074ac0 --- /dev/null +++ b/test/kaldi_compatibility_cpu_test.py @@ -0,0 +1,5 @@ +from . import common_utils +from .kaldi_compatibility_impl import Kaldi + + +common_utils.define_test_suites(globals(), [Kaldi], devices=['cpu']) diff --git a/test/kaldi_compatibility_cuda_test.py b/test/kaldi_compatibility_cuda_test.py new file mode 100644 index 0000000000..acaa2408f5 --- /dev/null +++ b/test/kaldi_compatibility_cuda_test.py @@ -0,0 +1,5 @@ +from . import common_utils +from .kaldi_compatibility_impl import Kaldi + + +common_utils.define_test_suites(globals(), [Kaldi], devices=['cuda']) diff --git a/test/kaldi_compatibility_impl.py b/test/kaldi_compatibility_impl.py new file mode 100644 index 0000000000..8fbdff75cb --- /dev/null +++ b/test/kaldi_compatibility_impl.py @@ -0,0 +1,104 @@ +"""Test suites for checking numerical compatibility against Kaldi""" +import shutil +import unittest +import subprocess + +import kaldi_io +import torch +import torchaudio.functional as F +import torchaudio.compliance.kaldi + +from . import common_utils + + +def _not_available(cmd): + return shutil.which(cmd) is None + + +def _convert_args(**kwargs): + args = [] + for key, value in kwargs.items(): + key = '--' + key.replace('_', '-') + value = str(value).lower() if value in [True, False] else str(value) + args.append('%s=%s' % (key, value)) + return args + + +def _run_kaldi(command, input_type, input_value): + """Run provided Kaldi command, pass a tensor and get the resulting tensor + + Arguments: + input_type: str + 'ark' or 'scp' + input_value: + Tensor for 'ark' + string for 'scp' (path to an audio file) + """ + key = 'foo' + process = subprocess.Popen(command, stdin=subprocess.PIPE, stdout=subprocess.PIPE) + if input_type == 'ark': + kaldi_io.write_mat(process.stdin, input_value.cpu().numpy(), key=key) + elif input_type == 'scp': + process.stdin.write(f'{key} {input_value}'.encode('utf8')) + else: + raise NotImplementedError('Unexpected type') + process.stdin.close() + result = dict(kaldi_io.read_mat_ark(process.stdout))['foo'] + return torch.from_numpy(result.copy()) # copy supresses some torch warning + + +class Kaldi(common_utils.TestBaseMixin): + def assert_equal(self, output, *, expected, rtol=None, atol=None): + expected = expected.to(dtype=self.dtype, device=self.device) + self.assertEqual(output, expected, rtol=rtol, atol=atol) + + @unittest.skipIf(_not_available('apply-cmvn-sliding'), '`apply-cmvn-sliding` not available') + def test_sliding_window_cmn(self): + """sliding_window_cmn should be numerically compatible with apply-cmvn-sliding""" + kwargs = { + 'cmn_window': 600, + 'min_cmn_window': 100, + 'center': False, + 'norm_vars': False, + } + + tensor = torch.randn(40, 10, dtype=self.dtype, device=self.device) + result = F.sliding_window_cmn(tensor, **kwargs) + command = ['apply-cmvn-sliding'] + _convert_args(**kwargs) + ['ark:-', 'ark:-'] + kaldi_result = _run_kaldi(command, 'ark', tensor) + self.assert_equal(result, expected=kaldi_result) + + @unittest.skipIf(_not_available('compute-fbank-feats'), '`compute-fbank-feats` not available') + def test_fbank(self): + """fbank should be numerically compatible with compute-fbank-feats""" + kwargs = { + 'blackman_coeff': 4.3926, + 'dither': 0.0, + 'energy_floor': 2.0617, + 'frame_length': 0.5625, + 'frame_shift': 0.0625, + 'high_freq': 4253, + 'htk_compat': True, + 'low_freq': 1367, + 'num_mel_bins': 5, + 'preemphasis_coefficient': 0.84, + 'raw_energy': False, + 'remove_dc_offset': True, + 'round_to_power_of_two': True, + 'snip_edges': True, + 'subtract_mean': False, + 'use_energy': True, + 'use_log_fbank': True, + 'use_power': False, + 'vtln_high': 2112, + 'vtln_low': 1445, + 'vtln_warp': 1.0000, + 'window_type': 'hamming', + + } + wave_file = common_utils.get_asset_path('kaldi_file.wav') + waveform = torchaudio.load_wav(wave_file)[0].to(dtype=self.dtype, device=self.device) + result = torchaudio.compliance.kaldi.fbank(waveform, **kwargs) + command = ['compute-fbank-feats'] + _convert_args(**kwargs) + ['scp:-', 'ark:-'] + kaldi_result = _run_kaldi(command, 'scp', wave_file) + self.assert_equal(result, expected=kaldi_result, rtol=1e-4, atol=1e-8) diff --git a/test/test_batch_consistency.py b/test/test_batch_consistency.py index 675a21e029..c10652d9ca 100644 --- a/test/test_batch_consistency.py +++ b/test/test_batch_consistency.py @@ -2,33 +2,36 @@ import unittest import torch +from torch.testing._internal.common_utils import TestCase import torchaudio import torchaudio.functional as F -import common_utils +from . import common_utils -def _test_batch_consistency(functional, tensor, *args, batch_size=1, atol=1e-8, rtol=1e-5, **kwargs): - # run then batch the result - torch.random.manual_seed(42) - expected = functional(tensor.clone(), *args, **kwargs) - expected = expected.repeat([batch_size] + [1] * expected.dim()) - - # batch the input and run - torch.random.manual_seed(42) - pattern = [batch_size] + [1] * tensor.dim() - computed = functional(tensor.repeat(pattern), *args, **kwargs) - - torch.testing.assert_allclose(computed, expected, rtol=rtol, atol=atol) - - -def _test_batch(functional, tensor, *args, atol=1e-8, rtol=1e-5, **kwargs): - _test_batch_consistency(functional, tensor, *args, batch_size=1, atol=atol, rtol=rtol, **kwargs) - _test_batch_consistency(functional, tensor, *args, batch_size=3, atol=atol, rtol=rtol, **kwargs) - - -class TestFunctional(unittest.TestCase): +class TestFunctional(TestCase): """Test functions defined in `functional` module""" + def assert_batch_consistency( + self, functional, tensor, *args, batch_size=1, atol=1e-8, rtol=1e-5, seed=42, **kwargs): + # run then batch the result + torch.random.manual_seed(seed) + expected = functional(tensor.clone(), *args, **kwargs) + expected = expected.repeat([batch_size] + [1] * expected.dim()) + + # batch the input and run + torch.random.manual_seed(seed) + pattern = [batch_size] + [1] * tensor.dim() + computed = functional(tensor.repeat(pattern), *args, **kwargs) + + self.assertEqual(computed, expected, rtol=rtol, atol=atol) + + def assert_batch_consistencies( + self, functional, tensor, *args, atol=1e-8, rtol=1e-5, seed=42, **kwargs): + self.assert_batch_consistency( + functional, tensor, *args, batch_size=1, atol=atol, rtol=rtol, seed=seed, **kwargs) + self.assert_batch_consistency( + functional, tensor, *args, batch_size=3, atol=atol, rtol=rtol, seed=seed, **kwargs) + def test_griffinlim(self): n_fft = 400 ws = 400 @@ -40,7 +43,7 @@ def test_griffinlim(self): n_iter = 32 length = 1000 tensor = torch.rand((1, 201, 6)) - _test_batch( + self.assert_batch_consistencies( F.griffinlim, tensor, window, n_fft, hop, ws, power, normalize, n_iter, momentum, length, 0, atol=5e-5 ) @@ -54,7 +57,7 @@ def test_detect_pitch_frequency(self): for filename in filenames: filepath = common_utils.get_asset_path(filename) waveform, sample_rate = torchaudio.load(filepath) - _test_batch(F.detect_pitch_frequency, waveform, sample_rate) + self.assert_batch_consistencies(F.detect_pitch_frequency, waveform, sample_rate) def test_istft(self): stft = torch.tensor([ @@ -62,34 +65,39 @@ def test_istft(self): [[0., 0.], [0., 0.], [0., 0.], [0., 0.], [0., 0.]], [[0., 0.], [0., 0.], [0., 0.], [0., 0.], [0., 0.]] ]) - _test_batch(F.istft, stft, n_fft=4, length=4) + self.assert_batch_consistencies(F.istft, stft, n_fft=4, length=4) def test_contrast(self): waveform = torch.rand(2, 100) - 0.5 - _test_batch(F.contrast, waveform, enhancement_amount=80.) + self.assert_batch_consistencies(F.contrast, waveform, enhancement_amount=80.) def test_dcshift(self): waveform = torch.rand(2, 100) - 0.5 - _test_batch(F.dcshift, waveform, shift=0.5, limiter_gain=0.05) + self.assert_batch_consistencies(F.dcshift, waveform, shift=0.5, limiter_gain=0.05) def test_overdrive(self): waveform = torch.rand(2, 100) - 0.5 - _test_batch(F.overdrive, waveform, gain=45, colour=30) + self.assert_batch_consistencies(F.overdrive, waveform, gain=45, colour=30) + + def test_phaser(self): + filepath = common_utils.get_asset_path("whitenoise.wav") + waveform, sample_rate = torchaudio.load(filepath) + self.assert_batch_consistencies(F.phaser, waveform, sample_rate) def test_sliding_window_cmn(self): waveform = torch.randn(2, 1024) - 0.5 - _test_batch(F.sliding_window_cmn, waveform, center=True, norm_vars=True) - _test_batch(F.sliding_window_cmn, waveform, center=True, norm_vars=False) - _test_batch(F.sliding_window_cmn, waveform, center=False, norm_vars=True) - _test_batch(F.sliding_window_cmn, waveform, center=False, norm_vars=False) + self.assert_batch_consistencies(F.sliding_window_cmn, waveform, center=True, norm_vars=True) + self.assert_batch_consistencies(F.sliding_window_cmn, waveform, center=True, norm_vars=False) + self.assert_batch_consistencies(F.sliding_window_cmn, waveform, center=False, norm_vars=True) + self.assert_batch_consistencies(F.sliding_window_cmn, waveform, center=False, norm_vars=False) def test_vad(self): - filepath = common_utils.get_asset_path("vad-hello-mono-32000.wav") + filepath = common_utils.get_asset_path("vad-go-mono-32000.wav") waveform, sample_rate = torchaudio.load(filepath) - _test_batch(F.vad, waveform, sample_rate=sample_rate) + self.assert_batch_consistencies(F.vad, waveform, sample_rate=sample_rate) -class TestTransforms(unittest.TestCase): +class TestTransforms(TestCase): """Test suite for classes defined in `transforms` module""" def test_batch_AmplitudeToDB(self): spec = torch.rand((6, 201)) @@ -100,7 +108,7 @@ def test_batch_AmplitudeToDB(self): # Batch then transform computed = torchaudio.transforms.AmplitudeToDB()(spec.repeat(3, 1, 1)) - torch.testing.assert_allclose(computed, expected) + self.assertEqual(computed, expected) def test_batch_Resample(self): waveform = torch.randn(2, 2786) @@ -111,7 +119,7 @@ def test_batch_Resample(self): # Batch then transform computed = torchaudio.transforms.Resample()(waveform.repeat(3, 1, 1)) - torch.testing.assert_allclose(computed, expected) + self.assertEqual(computed, expected) def test_batch_MelScale(self): specgram = torch.randn(2, 31, 2786) @@ -123,7 +131,7 @@ def test_batch_MelScale(self): computed = torchaudio.transforms.MelScale()(specgram.repeat(3, 1, 1, 1)) # shape = (3, 2, 201, 1394) - torch.testing.assert_allclose(computed, expected) + self.assertEqual(computed, expected) def test_batch_InverseMelScale(self): n_mels = 32 @@ -140,7 +148,7 @@ def test_batch_InverseMelScale(self): # Because InverseMelScale runs SGD on randomly initialized values so they do not yield # exactly same result. For this reason, tolerance is very relaxed here. - torch.testing.assert_allclose(computed, expected, atol=1.0, rtol=1e-5) + self.assertEqual(computed, expected, atol=1.0, rtol=1e-5) def test_batch_compute_deltas(self): specgram = torch.randn(2, 31, 2786) @@ -152,7 +160,7 @@ def test_batch_compute_deltas(self): computed = torchaudio.transforms.ComputeDeltas()(specgram.repeat(3, 1, 1, 1)) # shape = (3, 2, 201, 1394) - torch.testing.assert_allclose(computed, expected) + self.assertEqual(computed, expected) def test_batch_mulaw(self): test_filepath = common_utils.get_asset_path('steam-train-whistle-daniel_simon.wav') @@ -167,7 +175,7 @@ def test_batch_mulaw(self): computed = torchaudio.transforms.MuLawEncoding()(waveform_batched) # shape = (3, 2, 201, 1394) - torch.testing.assert_allclose(computed, expected) + self.assertEqual(computed, expected) # Single then transform then batch waveform_decoded = torchaudio.transforms.MuLawDecoding()(waveform_encoded) @@ -177,7 +185,7 @@ def test_batch_mulaw(self): computed = torchaudio.transforms.MuLawDecoding()(computed) # shape = (3, 2, 201, 1394) - torch.testing.assert_allclose(computed, expected) + self.assertEqual(computed, expected) def test_batch_spectrogram(self): test_filepath = common_utils.get_asset_path('steam-train-whistle-daniel_simon.wav') @@ -188,7 +196,7 @@ def test_batch_spectrogram(self): # Batch then transform computed = torchaudio.transforms.Spectrogram()(waveform.repeat(3, 1, 1)) - torch.testing.assert_allclose(computed, expected) + self.assertEqual(computed, expected) def test_batch_melspectrogram(self): test_filepath = common_utils.get_asset_path('steam-train-whistle-daniel_simon.wav') @@ -199,7 +207,7 @@ def test_batch_melspectrogram(self): # Batch then transform computed = torchaudio.transforms.MelSpectrogram()(waveform.repeat(3, 1, 1)) - torch.testing.assert_allclose(computed, expected) + self.assertEqual(computed, expected) def test_batch_mfcc(self): test_filepath = common_utils.get_asset_path('steam-train-whistle-daniel_simon.wav') @@ -210,7 +218,7 @@ def test_batch_mfcc(self): # Batch then transform computed = torchaudio.transforms.MFCC()(waveform.repeat(3, 1, 1)) - torch.testing.assert_allclose(computed, expected, atol=1e-5, rtol=1e-5) + self.assertEqual(computed, expected, atol=1e-4, rtol=1e-5) def test_batch_TimeStretch(self): test_filepath = common_utils.get_asset_path('steam-train-whistle-daniel_simon.wav') @@ -244,7 +252,7 @@ def test_batch_TimeStretch(self): hop_length=512, )(complex_specgrams.repeat(3, 1, 1, 1, 1)) - torch.testing.assert_allclose(computed, expected, atol=1e-5, rtol=1e-5) + self.assertEqual(computed, expected, atol=1e-5, rtol=1e-5) def test_batch_Fade(self): test_filepath = common_utils.get_asset_path('steam-train-whistle-daniel_simon.wav') @@ -257,7 +265,7 @@ def test_batch_Fade(self): # Batch then transform computed = torchaudio.transforms.Fade(fade_in_len, fade_out_len)(waveform.repeat(3, 1, 1)) - torch.testing.assert_allclose(computed, expected) + self.assertEqual(computed, expected) def test_batch_Vol(self): test_filepath = common_utils.get_asset_path('steam-train-whistle-daniel_simon.wav') @@ -268,7 +276,7 @@ def test_batch_Vol(self): # Batch then transform computed = torchaudio.transforms.Vol(gain=1.1)(waveform.repeat(3, 1, 1)) - torch.testing.assert_allclose(computed, expected) + self.assertEqual(computed, expected) if __name__ == '__main__': diff --git a/test/test_compliance_kaldi.py b/test/test_compliance_kaldi.py index 6951ccf59b..2a255a5a4b 100644 --- a/test/test_compliance_kaldi.py +++ b/test/test_compliance_kaldi.py @@ -1,13 +1,13 @@ import math import os -import compliance.utils import torch import torchaudio import torchaudio.compliance.kaldi as kaldi import unittest -import common_utils -from common_utils import AudioBackendScope, BACKENDS +from . import common_utils +from .compliance import utils as compliance_utils +from .common_utils import AudioBackendScope, BACKENDS def extract_window(window, wave, f, frame_length, frame_shift, snip_edges): @@ -50,7 +50,7 @@ class Test_Kaldi(unittest.TestCase): test_filepath = common_utils.get_asset_path('kaldi_file.wav') test_8000_filepath = common_utils.get_asset_path('kaldi_file_8000.wav') kaldi_output_dir = common_utils.get_asset_path('kaldi') - test_filepaths = {prefix: [] for prefix in compliance.utils.TEST_PREFIX} + test_filepaths = {prefix: [] for prefix in compliance_utils.TEST_PREFIX} # separating test files by their types (e.g 'spec', 'fbank', etc.) for f in os.listdir(kaldi_output_dir): @@ -151,7 +151,7 @@ def _compliance_test_helper(self, sound_filepath, filepath_key, expected_num_fil args = f.split('-') args[-1] = os.path.splitext(args[-1])[0] assert len(args) == expected_num_args, 'invalid test kaldi file name' - args = [compliance.utils.parse(arg) for arg in args] + args = [compliance_utils.parse(arg) for arg in args] output = get_output_fn(sound, args) diff --git a/test/test_dataloader.py b/test/test_dataloader.py index 602491ee21..cfcc25e7c4 100644 --- a/test/test_dataloader.py +++ b/test/test_dataloader.py @@ -3,8 +3,8 @@ import torchaudio from torch.utils.data import Dataset, DataLoader -import common_utils -from common_utils import AudioBackendScope, BACKENDS +from . import common_utils +from .common_utils import AudioBackendScope, BACKENDS class TORCHAUDIODS(Dataset): @@ -28,8 +28,9 @@ def __len__(self): return len(self.data) -@unittest.skipIf("sox" not in BACKENDS, "sox not available") class Test_DataLoader(unittest.TestCase): + @unittest.skipIf("sox" not in BACKENDS, "sox not available") + @AudioBackendScope("sox") def test_1(self): expected_size = (2, 1, 16000) ds = TORCHAUDIODS() @@ -39,5 +40,4 @@ def test_1(self): if __name__ == '__main__': - with AudioBackendScope("sox"): - unittest.main() + unittest.main() diff --git a/test/test_datasets.py b/test/test_datasets.py index e42e21e999..96c12884d6 100644 --- a/test/test_datasets.py +++ b/test/test_datasets.py @@ -8,7 +8,7 @@ from torchaudio.datasets.yesno import YESNO from torchaudio.datasets.ljspeech import LJSPEECH -import common_utils +from . import common_utils class TestDatasets(unittest.TestCase): @@ -26,10 +26,12 @@ def test_librispeech(self): data = LIBRISPEECH(self.path, "dev-clean") data[0] + @unittest.skipIf("sox" not in common_utils.BACKENDS, "sox not available") def test_commonvoice(self): data = COMMONVOICE(self.path, url="tatar") data[0] + @unittest.skipIf("sox" not in common_utils.BACKENDS, "sox not available") def test_commonvoice_diskcache(self): data = COMMONVOICE(self.path, url="tatar") data = diskcache_iterator(data) @@ -38,6 +40,7 @@ def test_commonvoice_diskcache(self): # Load data[0] + @unittest.skipIf("sox" not in common_utils.BACKENDS, "sox not available") def test_commonvoice_bg(self): data = COMMONVOICE(self.path, url="tatar") data = bg_iterator(data, 5) diff --git a/test/test_functional.py b/test/test_functional.py index a126bd9581..ac90b7bde5 100644 --- a/test/test_functional.py +++ b/test/test_functional.py @@ -6,13 +6,10 @@ import torchaudio.functional as F import pytest -import common_utils +from . import common_utils -class _LfilterMixin: - device = None - dtype = None - +class Lfilter(common_utils.TestBaseMixin): def test_simple(self): """ Create a very basic signal, @@ -26,23 +23,19 @@ def test_simple(self): a_coeffs = torch.tensor([1, 0, 0, 0], dtype=self.dtype, device=self.device) output_waveform = F.lfilter(waveform, a_coeffs, b_coeffs) - torch.testing.assert_allclose(output_waveform[:, 3:], waveform[:, 0:-3], atol=1e-5, rtol=1e-5) - - -class TestLfilterFloat32CPU(_LfilterMixin, unittest.TestCase): - device = torch.device('cpu') - dtype = torch.float32 - + self.assertEqual(output_waveform[:, 3:], waveform[:, 0:-3], atol=1e-5, rtol=1e-5) -class TestLfilterFloat64CPU(_LfilterMixin, unittest.TestCase): - device = torch.device('cpu') - dtype = torch.float64 + def test_clamp(self): + input_signal = torch.ones(1, 44100 * 1, dtype=self.dtype, device=self.device) + b_coeffs = torch.tensor([1, 0], dtype=self.dtype, device=self.device) + a_coeffs = torch.tensor([1, -0.95], dtype=self.dtype, device=self.device) + output_signal = F.lfilter(input_signal, a_coeffs, b_coeffs, clamp=True) + assert output_signal.max() <= 1 + output_signal = F.lfilter(input_signal, a_coeffs, b_coeffs, clamp=False) + assert output_signal.max() > 1 -@unittest.skipIf(not torch.cuda.is_available(), "CUDA not available") -class TestLfilterFloat32CUDA(_LfilterMixin, unittest.TestCase): - device = torch.device('cuda') - dtype = torch.float32 +common_utils.define_test_suites(globals(), [Lfilter]) class TestComputeDeltas(unittest.TestCase): @@ -179,7 +172,7 @@ def test_istft_of_zeros(self): def test_istft_requires_overlap_windows(self): # the window is size 1 but it hops 20 so there is a gap which throw an error stft = torch.zeros((3, 5, 2)) - self.assertRaises(AssertionError, torchaudio.functional.istft, stft, n_fft=4, + self.assertRaises(RuntimeError, torchaudio.functional.istft, stft, n_fft=4, hop_length=20, win_length=1, window=torch.ones(1)) def test_istft_requires_nola(self): @@ -199,11 +192,11 @@ def test_istft_requires_nola(self): # A window of ones meets NOLA but a window of zeros does not. This should # throw an error. torchaudio.functional.istft(stft, **kwargs_ok) - self.assertRaises(AssertionError, torchaudio.functional.istft, stft, **kwargs_not_ok) + self.assertRaises(RuntimeError, torchaudio.functional.istft, stft, **kwargs_not_ok) def test_istft_requires_non_empty(self): - self.assertRaises(AssertionError, torchaudio.functional.istft, torch.zeros((3, 0, 2)), 2) - self.assertRaises(AssertionError, torchaudio.functional.istft, torch.zeros((0, 3, 2)), 2) + self.assertRaises(RuntimeError, torchaudio.functional.istft, torch.zeros((3, 0, 2)), 2) + self.assertRaises(RuntimeError, torchaudio.functional.istft, torch.zeros((0, 3, 2)), 2) def _test_istft_of_sine(self, amplitude, L, n): # stft of amplitude*sin(2*pi/L*n*x) with the hop length and window size equaling L diff --git a/test/test_io.py b/test/test_io.py index 80968e15ad..0295cb785e 100644 --- a/test/test_io.py +++ b/test/test_io.py @@ -3,7 +3,7 @@ import torchaudio import math import os -from common_utils import AudioBackendScope, BACKENDS, BACKENDS_MP3, create_temp_assets_dir +from .common_utils import AudioBackendScope, BACKENDS, BACKENDS_MP3, create_temp_assets_dir class Test_LoadSave(unittest.TestCase): @@ -171,7 +171,7 @@ def _test_3_load_and_save_is_identity(self): self.assertEqual(sample_rate, sample_rate2) os.unlink(output_path) - @unittest.skipIf(set(["sox", "soundfile"]) not in set(BACKENDS), "sox and soundfile are not available") + @unittest.skipIf(any(be not in BACKENDS for be in ["sox", "soundfile"]), "sox and soundfile are not available") def test_3_load_and_save_is_identity_across_backend(self): with self.subTest(): self._test_3_load_and_save_is_identity_across_backend("sox", "soundfile") diff --git a/test/test_kaldi_io.py b/test/test_kaldi_io.py index bc9903a3ef..942b11de35 100644 --- a/test/test_kaldi_io.py +++ b/test/test_kaldi_io.py @@ -3,7 +3,7 @@ import torch import torchaudio.kaldi_io as kio -import common_utils +from . import common_utils class Test_KaldiIO(unittest.TestCase): diff --git a/test/test_librosa_compatibility.py b/test/test_librosa_compatibility.py index 460f379ce9..665341d945 100644 --- a/test/test_librosa_compatibility.py +++ b/test/test_librosa_compatibility.py @@ -1,8 +1,10 @@ """Test suites for numerical compatibility with librosa""" import os import unittest +from distutils.version import StrictVersion import torch +from torch.testing._internal.common_utils import TestCase import torchaudio import torchaudio.functional as F from torchaudio.common_utils import IMPORT_LIBROSA @@ -14,18 +16,11 @@ import pytest -import common_utils +from . import common_utils -class _LibrosaMixin: - """Automatically skip tests if librosa is not available""" - def setUp(self): - super().setUp() - if not IMPORT_LIBROSA: - raise unittest.SkipTest('Librosa not available') - - -class TestFunctional(_LibrosaMixin, unittest.TestCase): +@unittest.skipIf(not IMPORT_LIBROSA, "Librosa not available") +class TestFunctional(TestCase): """Test suite for functions in `functional` module.""" def test_griffinlim(self): # NOTE: This test is flaky without a fixed random seed @@ -51,25 +46,26 @@ def test_griffinlim(self): momentum=momentum, init=init, length=length) lr_out = torch.from_numpy(lr_out).unsqueeze(0) - torch.testing.assert_allclose(ta_out, lr_out, atol=5e-5, rtol=1e-5) + self.assertEqual(ta_out, lr_out, atol=5e-5, rtol=1e-5) - def _test_create_fb(self, n_mels=40, sample_rate=22050, n_fft=2048, fmin=0.0, fmax=8000.0): + def _test_create_fb(self, n_mels=40, sample_rate=22050, n_fft=2048, fmin=0.0, fmax=8000.0, norm=None): librosa_fb = librosa.filters.mel(sr=sample_rate, n_fft=n_fft, n_mels=n_mels, fmax=fmax, fmin=fmin, htk=True, - norm=None) + norm=norm) fb = F.create_fb_matrix(sample_rate=sample_rate, n_mels=n_mels, f_max=fmax, f_min=fmin, - n_freqs=(n_fft // 2 + 1)) + n_freqs=(n_fft // 2 + 1), + norm=norm) for i_mel_bank in range(n_mels): - torch.testing.assert_allclose(fb[:, i_mel_bank], torch.tensor(librosa_fb[i_mel_bank]), - atol=1e-4, rtol=1e-5) + self.assertEqual( + fb[:, i_mel_bank], torch.tensor(librosa_fb[i_mel_bank]), atol=1e-4, rtol=1e-5) def test_create_fb(self): self._test_create_fb() @@ -79,6 +75,14 @@ def test_create_fb(self): self._test_create_fb(n_mels=56, fmin=800.0, fmax=900.0) self._test_create_fb(n_mels=56, fmin=1900.0, fmax=900.0) self._test_create_fb(n_mels=10, fmin=1900.0, fmax=900.0) + if StrictVersion(librosa.__version__) < StrictVersion("0.7.2"): + return + self._test_create_fb(n_mels=128, sample_rate=44100, norm="slaney") + self._test_create_fb(n_mels=128, fmin=2000.0, fmax=5000.0, norm="slaney") + self._test_create_fb(n_mels=56, fmin=100.0, fmax=9000.0, norm="slaney") + self._test_create_fb(n_mels=56, fmin=800.0, fmax=900.0, norm="slaney") + self._test_create_fb(n_mels=56, fmin=1900.0, fmax=900.0, norm="slaney") + self._test_create_fb(n_mels=10, fmin=1900.0, fmax=900.0, norm="slaney") def test_amplitude_to_DB(self): spec = torch.rand((6, 201)) @@ -94,7 +98,7 @@ def test_amplitude_to_DB(self): lr_out = librosa.core.power_to_db(spec.numpy()) lr_out = torch.from_numpy(lr_out) - torch.testing.assert_allclose(ta_out, lr_out, atol=5e-5, rtol=1e-5) + self.assertEqual(ta_out, lr_out, atol=5e-5, rtol=1e-5) # Amplitude to DB multiplier = 20.0 @@ -103,7 +107,7 @@ def test_amplitude_to_DB(self): lr_out = librosa.core.amplitude_to_db(spec.numpy()) lr_out = torch.from_numpy(lr_out) - torch.testing.assert_allclose(ta_out, lr_out, atol=5e-5, rtol=1e-5) + self.assertEqual(ta_out, lr_out, atol=5e-5, rtol=1e-5) @pytest.mark.parametrize('complex_specgrams', [ @@ -154,73 +158,73 @@ def _load_audio_asset(*asset_paths, **kwargs): return sound, sample_rate -def _test_compatibilities(n_fft, hop_length, power, n_mels, n_mfcc, sample_rate): - sound, sample_rate = _load_audio_asset('sinewave.wav') - sound_librosa = sound.cpu().numpy().squeeze() # (64000) - - # test core spectrogram - spect_transform = torchaudio.transforms.Spectrogram( - n_fft=n_fft, hop_length=hop_length, power=power) - out_librosa, _ = librosa.core.spectrum._spectrogram( - y=sound_librosa, n_fft=n_fft, hop_length=hop_length, power=power) - - out_torch = spect_transform(sound).squeeze().cpu() - torch.testing.assert_allclose(out_torch, torch.from_numpy(out_librosa), atol=1e-5, rtol=1e-5) - - # test mel spectrogram - melspect_transform = torchaudio.transforms.MelSpectrogram( - sample_rate=sample_rate, window_fn=torch.hann_window, - hop_length=hop_length, n_mels=n_mels, n_fft=n_fft) - librosa_mel = librosa.feature.melspectrogram( - y=sound_librosa, sr=sample_rate, n_fft=n_fft, - hop_length=hop_length, n_mels=n_mels, htk=True, norm=None) - librosa_mel_tensor = torch.from_numpy(librosa_mel) - torch_mel = melspect_transform(sound).squeeze().cpu() - torch.testing.assert_allclose( - torch_mel.type(librosa_mel_tensor.dtype), librosa_mel_tensor, atol=5e-3, rtol=1e-5) - - # test s2db - power_to_db_transform = torchaudio.transforms.AmplitudeToDB('power', 80.) - power_to_db_torch = power_to_db_transform(spect_transform(sound)).squeeze().cpu() - power_to_db_librosa = librosa.core.spectrum.power_to_db(out_librosa) - torch.testing.assert_allclose(power_to_db_torch, torch.from_numpy(power_to_db_librosa), atol=5e-3, rtol=1e-5) - - mag_to_db_transform = torchaudio.transforms.AmplitudeToDB('magnitude', 80.) - mag_to_db_torch = mag_to_db_transform(torch.abs(sound)).squeeze().cpu() - mag_to_db_librosa = librosa.core.spectrum.amplitude_to_db(sound_librosa) - torch.testing.assert_allclose(mag_to_db_torch, torch.from_numpy(mag_to_db_librosa), atol=5e-3, rtol=1e-5) - - power_to_db_torch = power_to_db_transform(melspect_transform(sound)).squeeze().cpu() - db_librosa = librosa.core.spectrum.power_to_db(librosa_mel) - db_librosa_tensor = torch.from_numpy(db_librosa) - torch.testing.assert_allclose( - power_to_db_torch.type(db_librosa_tensor.dtype), db_librosa_tensor, atol=5e-3, rtol=1e-5) - - # test MFCC - melkwargs = {'hop_length': hop_length, 'n_fft': n_fft} - mfcc_transform = torchaudio.transforms.MFCC( - sample_rate=sample_rate, n_mfcc=n_mfcc, norm='ortho', melkwargs=melkwargs) - - # librosa.feature.mfcc doesn't pass kwargs properly since some of the - # kwargs for melspectrogram and mfcc are the same. We just follow the - # function body in - # https://librosa.github.io/librosa/_modules/librosa/feature/spectral.html#melspectrogram - # to mirror this function call with correct args: - # - # librosa_mfcc = librosa.feature.mfcc( - # y=sound_librosa, sr=sample_rate, n_mfcc = n_mfcc, - # hop_length=hop_length, n_fft=n_fft, htk=True, norm=None, n_mels=n_mels) - - librosa_mfcc = scipy.fftpack.dct(db_librosa, axis=0, type=2, norm='ortho')[:n_mfcc] - librosa_mfcc_tensor = torch.from_numpy(librosa_mfcc) - torch_mfcc = mfcc_transform(sound).squeeze().cpu() - - torch.testing.assert_allclose( - torch_mfcc.type(librosa_mfcc_tensor.dtype), librosa_mfcc_tensor, atol=5e-3, rtol=1e-5) - - -class TestTransforms(_LibrosaMixin, unittest.TestCase): +@unittest.skipIf(not IMPORT_LIBROSA, "Librosa not available") +class TestTransforms(TestCase): """Test suite for functions in `transforms` module.""" + def assert_compatibilities(self, n_fft, hop_length, power, n_mels, n_mfcc, sample_rate): + sound, sample_rate = _load_audio_asset('sinewave.wav') + sound_librosa = sound.cpu().numpy().squeeze() # (64000) + + # test core spectrogram + spect_transform = torchaudio.transforms.Spectrogram( + n_fft=n_fft, hop_length=hop_length, power=power) + out_librosa, _ = librosa.core.spectrum._spectrogram( + y=sound_librosa, n_fft=n_fft, hop_length=hop_length, power=power) + + out_torch = spect_transform(sound).squeeze().cpu() + self.assertEqual(out_torch, torch.from_numpy(out_librosa), atol=1e-5, rtol=1e-5) + + # test mel spectrogram + melspect_transform = torchaudio.transforms.MelSpectrogram( + sample_rate=sample_rate, window_fn=torch.hann_window, + hop_length=hop_length, n_mels=n_mels, n_fft=n_fft) + librosa_mel = librosa.feature.melspectrogram( + y=sound_librosa, sr=sample_rate, n_fft=n_fft, + hop_length=hop_length, n_mels=n_mels, htk=True, norm=None) + librosa_mel_tensor = torch.from_numpy(librosa_mel) + torch_mel = melspect_transform(sound).squeeze().cpu() + self.assertEqual( + torch_mel.type(librosa_mel_tensor.dtype), librosa_mel_tensor, atol=5e-3, rtol=1e-5) + + # test s2db + power_to_db_transform = torchaudio.transforms.AmplitudeToDB('power', 80.) + power_to_db_torch = power_to_db_transform(spect_transform(sound)).squeeze().cpu() + power_to_db_librosa = librosa.core.spectrum.power_to_db(out_librosa) + self.assertEqual(power_to_db_torch, torch.from_numpy(power_to_db_librosa), atol=5e-3, rtol=1e-5) + + mag_to_db_transform = torchaudio.transforms.AmplitudeToDB('magnitude', 80.) + mag_to_db_torch = mag_to_db_transform(torch.abs(sound)).squeeze().cpu() + mag_to_db_librosa = librosa.core.spectrum.amplitude_to_db(sound_librosa) + self.assertEqual(mag_to_db_torch, torch.from_numpy(mag_to_db_librosa), atol=5e-3, rtol=1e-5) + + power_to_db_torch = power_to_db_transform(melspect_transform(sound)).squeeze().cpu() + db_librosa = librosa.core.spectrum.power_to_db(librosa_mel) + db_librosa_tensor = torch.from_numpy(db_librosa) + self.assertEqual( + power_to_db_torch.type(db_librosa_tensor.dtype), db_librosa_tensor, atol=5e-3, rtol=1e-5) + + # test MFCC + melkwargs = {'hop_length': hop_length, 'n_fft': n_fft} + mfcc_transform = torchaudio.transforms.MFCC( + sample_rate=sample_rate, n_mfcc=n_mfcc, norm='ortho', melkwargs=melkwargs) + + # librosa.feature.mfcc doesn't pass kwargs properly since some of the + # kwargs for melspectrogram and mfcc are the same. We just follow the + # function body in + # https://librosa.github.io/librosa/_modules/librosa/feature/spectral.html#melspectrogram + # to mirror this function call with correct args: + # + # librosa_mfcc = librosa.feature.mfcc( + # y=sound_librosa, sr=sample_rate, n_mfcc = n_mfcc, + # hop_length=hop_length, n_fft=n_fft, htk=True, norm=None, n_mels=n_mels) + + librosa_mfcc = scipy.fftpack.dct(db_librosa, axis=0, type=2, norm='ortho')[:n_mfcc] + librosa_mfcc_tensor = torch.from_numpy(librosa_mfcc) + torch_mfcc = mfcc_transform(sound).squeeze().cpu() + + self.assertEqual( + torch_mfcc.type(librosa_mfcc_tensor.dtype), librosa_mfcc_tensor, atol=5e-3, rtol=1e-5) + def test_basics1(self): kwargs = { 'n_fft': 400, @@ -230,7 +234,7 @@ def test_basics1(self): 'n_mfcc': 40, 'sample_rate': 16000 } - _test_compatibilities(**kwargs) + self.assert_compatibilities(**kwargs) def test_basics2(self): kwargs = { @@ -241,7 +245,7 @@ def test_basics2(self): 'n_mfcc': 20, 'sample_rate': 16000 } - _test_compatibilities(**kwargs) + self.assert_compatibilities(**kwargs) # NOTE: Test passes offline, but fails on TravisCI (and CircleCI), see #372. @unittest.skipIf('CI' in os.environ, 'Test is known to fail on CI') @@ -254,7 +258,7 @@ def test_basics3(self): 'n_mfcc': 50, 'sample_rate': 24000 } - _test_compatibilities(**kwargs) + self.assert_compatibilities(**kwargs) def test_basics4(self): kwargs = { @@ -265,7 +269,7 @@ def test_basics4(self): 'n_mfcc': 40, 'sample_rate': 16000 } - _test_compatibilities(**kwargs) + self.assert_compatibilities(**kwargs) @unittest.skipIf("sox" not in common_utils.BACKENDS, "sox not available") @common_utils.AudioBackendScope("sox") @@ -288,7 +292,7 @@ def test_MelScale(self): S=spec_lr, sr=sample_rate, n_fft=n_fft, hop_length=hop_length, win_length=n_fft, center=True, window='hann', n_mels=n_mels, htk=True, norm=None) # Note: Using relaxed rtol instead of atol - torch.testing.assert_allclose(melspec_ta, torch.from_numpy(melspec_lr[None, ...]), atol=1e-8, rtol=1e-3) + self.assertEqual(melspec_ta, torch.from_numpy(melspec_lr[None, ...]), atol=1e-8, rtol=1e-3) def test_InverseMelScale(self): """InverseMelScale transform is comparable to that of librosa""" @@ -331,7 +335,7 @@ def test_InverseMelScale(self): # https://github.com/pytorch/audio/pull/366 for the discussion of the choice of algorithm # https://github.com/pytorch/audio/pull/448/files#r385747021 for the distribution of P-inf # distance over frequencies. - torch.testing.assert_allclose(spec_ta, spec_lr, atol=threshold, rtol=1e-5) + self.assertEqual(spec_ta, spec_lr, atol=threshold, rtol=1e-5) threshold = 1700.0 # This threshold was choosen empirically, based on the following observations diff --git a/test/test_models.py b/test/test_models.py new file mode 100644 index 0000000000..fe8df9a167 --- /dev/null +++ b/test/test_models.py @@ -0,0 +1,30 @@ +import pytest + +import torch +from torchaudio.models import Wav2Letter + + +class TestWav2Letter: + @pytest.mark.parametrize('batch_size', [2]) + @pytest.mark.parametrize('num_features', [1]) + @pytest.mark.parametrize('num_classes', [40]) + @pytest.mark.parametrize('input_length', [320]) + def test_waveform(self, batch_size, num_features, num_classes, input_length): + model = Wav2Letter() + + x = torch.rand(batch_size, num_features, input_length) + out = model(x) + + assert out.size() == (batch_size, num_classes, 2) + + @pytest.mark.parametrize('batch_size', [2]) + @pytest.mark.parametrize('num_features', [13]) + @pytest.mark.parametrize('num_classes', [40]) + @pytest.mark.parametrize('input_length', [2]) + def test_mfcc(self, batch_size, num_features, num_classes, input_length): + model = Wav2Letter(input_type="mfcc", num_features=13) + + x = torch.rand(batch_size, num_features, input_length) + out = model(x) + + assert out.size() == (batch_size, num_classes, 2) diff --git a/test/test_sox_compatibility.py b/test/test_sox_compatibility.py index 508ec7abfa..dfa57cec47 100644 --- a/test/test_sox_compatibility.py +++ b/test/test_sox_compatibility.py @@ -1,15 +1,16 @@ import unittest import torch +from torch.testing._internal.common_utils import TestCase import torchaudio import torchaudio.functional as F import torchaudio.transforms as T -import common_utils -from common_utils import AudioBackendScope, BACKENDS +from . import common_utils +from .common_utils import AudioBackendScope, BACKENDS -class TestFunctionalFiltering(unittest.TestCase): +class TestFunctionalFiltering(TestCase): @unittest.skipIf("sox" not in BACKENDS, "sox not available") @AudioBackendScope("sox") def test_gain(self): @@ -24,7 +25,7 @@ def test_gain(self): E.append_effect_to_chain("gain", [3]) sox_gain_waveform = E.sox_build_flow_effects()[0] - torch.testing.assert_allclose(waveform_gain, sox_gain_waveform, atol=1e-04, rtol=1e-5) + self.assertEqual(waveform_gain, sox_gain_waveform, atol=1e-04, rtol=1e-5) @unittest.skipIf("sox" not in BACKENDS, "sox not available") @AudioBackendScope("sox") @@ -40,13 +41,13 @@ def test_dither(self): E.append_effect_to_chain("dither", []) sox_dither_waveform = E.sox_build_flow_effects()[0] - torch.testing.assert_allclose(waveform_dithered, sox_dither_waveform, atol=1e-04, rtol=1e-5) + self.assertEqual(waveform_dithered, sox_dither_waveform, atol=1e-04, rtol=1e-5) E.clear_chain() E.append_effect_to_chain("dither", ["-s"]) sox_dither_waveform_ns = E.sox_build_flow_effects()[0] - torch.testing.assert_allclose(waveform_dithered_noiseshaped, sox_dither_waveform_ns, atol=1e-02, rtol=1e-5) + self.assertEqual(waveform_dithered_noiseshaped, sox_dither_waveform_ns, atol=1e-02, rtol=1e-5) @unittest.skipIf("sox" not in BACKENDS, "sox not available") @AudioBackendScope("sox") @@ -69,7 +70,7 @@ def test_vctk_transform_pipeline(self): E.append_effect_to_chain("dither", ["-s"]) wf_vctk_sox = E.sox_build_flow_effects()[0] - torch.testing.assert_allclose(wf_vctk, wf_vctk_sox, rtol=1e-03, atol=1e-03) + self.assertEqual(wf_vctk, wf_vctk_sox, rtol=1e-03, atol=1e-03) @unittest.skipIf("sox" not in BACKENDS, "sox not available") @AudioBackendScope("sox") @@ -89,7 +90,7 @@ def test_lowpass(self): waveform, sample_rate = torchaudio.load(noise_filepath, normalization=True) output_waveform = F.lowpass_biquad(waveform, sample_rate, cutoff_freq) - torch.testing.assert_allclose(output_waveform, sox_output_waveform, atol=1e-4, rtol=1e-5) + self.assertEqual(output_waveform, sox_output_waveform, atol=1e-4, rtol=1e-5) @unittest.skipIf("sox" not in BACKENDS, "sox not available") @AudioBackendScope("sox") @@ -110,7 +111,7 @@ def test_highpass(self): output_waveform = F.highpass_biquad(waveform, sample_rate, cutoff_freq) # TBD - this fails at the 1e-4 level, debug why - torch.testing.assert_allclose(output_waveform, sox_output_waveform, atol=1e-3, rtol=1e-5) + self.assertEqual(output_waveform, sox_output_waveform, atol=1e-3, rtol=1e-5) @unittest.skipIf("sox" not in BACKENDS, "sox not available") @AudioBackendScope("sox") @@ -131,7 +132,7 @@ def test_allpass(self): waveform, sample_rate = torchaudio.load(noise_filepath, normalization=True) output_waveform = F.allpass_biquad(waveform, sample_rate, central_freq, q) - torch.testing.assert_allclose(output_waveform, sox_output_waveform, atol=1e-4, rtol=1e-5) + self.assertEqual(output_waveform, sox_output_waveform, atol=1e-4, rtol=1e-5) @unittest.skipIf("sox" not in BACKENDS, "sox not available") @AudioBackendScope("sox") @@ -153,7 +154,7 @@ def test_bandpass_with_csg(self): waveform, sample_rate = torchaudio.load(noise_filepath, normalization=True) output_waveform = F.bandpass_biquad(waveform, sample_rate, central_freq, q, const_skirt_gain) - torch.testing.assert_allclose(output_waveform, sox_output_waveform, atol=1e-4, rtol=1e-5) + self.assertEqual(output_waveform, sox_output_waveform, atol=1e-4, rtol=1e-5) @unittest.skipIf("sox" not in BACKENDS, "sox not available") @AudioBackendScope("sox") @@ -175,7 +176,7 @@ def test_bandpass_without_csg(self): waveform, sample_rate = torchaudio.load(noise_filepath, normalization=True) output_waveform = F.bandpass_biquad(waveform, sample_rate, central_freq, q, const_skirt_gain) - torch.testing.assert_allclose(output_waveform, sox_output_waveform, atol=1e-4, rtol=1e-5) + self.assertEqual(output_waveform, sox_output_waveform, atol=1e-4, rtol=1e-5) @unittest.skipIf("sox" not in BACKENDS, "sox not available") @AudioBackendScope("sox") @@ -196,7 +197,7 @@ def test_bandreject(self): waveform, sample_rate = torchaudio.load(noise_filepath, normalization=True) output_waveform = F.bandreject_biquad(waveform, sample_rate, central_freq, q) - torch.testing.assert_allclose(output_waveform, sox_output_waveform, atol=1e-4, rtol=1e-5) + self.assertEqual(output_waveform, sox_output_waveform, atol=1e-4, rtol=1e-5) @unittest.skipIf("sox" not in BACKENDS, "sox not available") @AudioBackendScope("sox") @@ -218,7 +219,7 @@ def test_band_with_noise(self): waveform, sample_rate = torchaudio.load(noise_filepath, normalization=True) output_waveform = F.band_biquad(waveform, sample_rate, central_freq, q, noise) - torch.testing.assert_allclose(output_waveform, sox_output_waveform, atol=1e-4, rtol=1e-5) + self.assertEqual(output_waveform, sox_output_waveform, atol=1e-4, rtol=1e-5) @unittest.skipIf("sox" not in BACKENDS, "sox not available") @AudioBackendScope("sox") @@ -240,7 +241,7 @@ def test_band_without_noise(self): waveform, sample_rate = torchaudio.load(noise_filepath, normalization=True) output_waveform = F.band_biquad(waveform, sample_rate, central_freq, q, noise) - torch.testing.assert_allclose(output_waveform, sox_output_waveform, atol=1e-4, rtol=1e-5) + self.assertEqual(output_waveform, sox_output_waveform, atol=1e-4, rtol=1e-5) @unittest.skipIf("sox" not in BACKENDS, "sox not available") @AudioBackendScope("sox") @@ -262,7 +263,7 @@ def test_treble(self): waveform, sample_rate = torchaudio.load(noise_filepath, normalization=True) output_waveform = F.treble_biquad(waveform, sample_rate, gain, central_freq, q) - torch.testing.assert_allclose(output_waveform, sox_output_waveform, atol=1e-4, rtol=1e-5) + self.assertEqual(output_waveform, sox_output_waveform, atol=1e-4, rtol=1e-5) @unittest.skipIf("sox" not in BACKENDS, "sox not available") @AudioBackendScope("sox") @@ -280,7 +281,7 @@ def test_deemph(self): waveform, sample_rate = torchaudio.load(noise_filepath, normalization=True) output_waveform = F.deemph_biquad(waveform, sample_rate) - torch.testing.assert_allclose(output_waveform, sox_output_waveform, atol=1e-4, rtol=1e-5) + self.assertEqual(output_waveform, sox_output_waveform, atol=1e-4, rtol=1e-5) @unittest.skipIf("sox" not in BACKENDS, "sox not available") @AudioBackendScope("sox") @@ -298,7 +299,7 @@ def test_riaa(self): waveform, sample_rate = torchaudio.load(noise_filepath, normalization=True) output_waveform = F.riaa_biquad(waveform, sample_rate) - torch.testing.assert_allclose(output_waveform, sox_output_waveform, atol=1e-4, rtol=1e-5) + self.assertEqual(output_waveform, sox_output_waveform, atol=1e-4, rtol=1e-5) @unittest.skipIf("sox" not in BACKENDS, "sox not available") @AudioBackendScope("sox") @@ -316,7 +317,7 @@ def test_contrast(self): waveform, sample_rate = torchaudio.load(noise_filepath, normalization=True) output_waveform = F.contrast(waveform, enhancement_amount) - torch.testing.assert_allclose(output_waveform, sox_output_waveform, atol=1e-4, rtol=1e-5) + self.assertEqual(output_waveform, sox_output_waveform, atol=1e-4, rtol=1e-5) @unittest.skipIf("sox" not in BACKENDS, "sox not available") @AudioBackendScope("sox") @@ -335,7 +336,7 @@ def test_dcshift_with_limiter(self): waveform, _ = torchaudio.load(noise_filepath, normalization=True) output_waveform = F.dcshift(waveform, shift, limiter_gain) - torch.testing.assert_allclose(output_waveform, sox_output_waveform, atol=1e-4, rtol=1e-5) + self.assertEqual(output_waveform, sox_output_waveform, atol=1e-4, rtol=1e-5) @unittest.skipIf("sox" not in BACKENDS, "sox not available") @AudioBackendScope("sox") @@ -353,7 +354,7 @@ def test_dcshift_without_limiter(self): waveform, _ = torchaudio.load(noise_filepath, normalization=True) output_waveform = F.dcshift(waveform, shift) - torch.testing.assert_allclose(output_waveform, sox_output_waveform, atol=1e-4, rtol=1e-5) + self.assertEqual(output_waveform, sox_output_waveform, atol=1e-4, rtol=1e-5) @unittest.skipIf("sox" not in BACKENDS, "sox not available") @AudioBackendScope("sox") @@ -372,7 +373,51 @@ def test_overdrive(self): waveform, _ = torchaudio.load(noise_filepath, normalization=True) output_waveform = F.overdrive(waveform, gain, colour) - torch.testing.assert_allclose(output_waveform, sox_output_waveform, atol=1e-4, rtol=1e-5) + self.assertEqual(output_waveform, sox_output_waveform, atol=1e-4, rtol=1e-5) + + @unittest.skipIf("sox" not in BACKENDS, "sox not available") + @AudioBackendScope("sox") + def test_phaser_sine(self): + """ + Test phaser effect with sine moduldation, compare to SoX implementation + """ + gain_in = 0.5 + gain_out = 0.8 + delay_ms = 2.0 + decay = 0.4 + speed = 0.5 + noise_filepath = common_utils.get_asset_path('whitenoise.wav') + E = torchaudio.sox_effects.SoxEffectsChain() + E.set_input_file(noise_filepath) + E.append_effect_to_chain("phaser", [gain_in, gain_out, delay_ms, decay, speed, "-s"]) + sox_output_waveform, sr = E.sox_build_flow_effects() + + waveform, sample_rate = torchaudio.load(noise_filepath, normalization=True) + output_waveform = F.phaser(waveform, sample_rate, gain_in, gain_out, delay_ms, decay, speed, sinusoidal=True) + + self.assertEqual(output_waveform, sox_output_waveform, atol=1e-4, rtol=1e-5) + + @unittest.skipIf("sox" not in BACKENDS, "sox not available") + @AudioBackendScope("sox") + def test_phaser_triangle(self): + """ + Test phaser effect with triangle modulation, compare to SoX implementation + """ + gain_in = 0.5 + gain_out = 0.8 + delay_ms = 2.0 + decay = 0.4 + speed = 0.5 + noise_filepath = common_utils.get_asset_path('whitenoise.wav') + E = torchaudio.sox_effects.SoxEffectsChain() + E.set_input_file(noise_filepath) + E.append_effect_to_chain("phaser", [gain_in, gain_out, delay_ms, decay, speed, "-t"]) + sox_output_waveform, sr = E.sox_build_flow_effects() + + waveform, sample_rate = torchaudio.load(noise_filepath, normalization=True) + output_waveform = F.phaser(waveform, sample_rate, gain_in, gain_out, delay_ms, decay, speed, sinusoidal=False) + + self.assertEqual(output_waveform, sox_output_waveform, atol=1e-4, rtol=1e-5) @unittest.skipIf("sox" not in BACKENDS, "sox not available") @AudioBackendScope("sox") @@ -394,7 +439,7 @@ def test_equalizer(self): waveform, sample_rate = torchaudio.load(noise_filepath, normalization=True) output_waveform = F.equalizer_biquad(waveform, sample_rate, center_freq, gain, q) - torch.testing.assert_allclose(output_waveform, sox_output_waveform, atol=1e-4, rtol=1e-5) + self.assertEqual(output_waveform, sox_output_waveform, atol=1e-4, rtol=1e-5) @unittest.skipIf("sox" not in BACKENDS, "sox not available") @AudioBackendScope("sox") @@ -420,7 +465,7 @@ def test_perf_biquad_filtering(self): waveform, torch.tensor([a0, a1, a2]), torch.tensor([b0, b1, b2]) ) - torch.testing.assert_allclose(waveform_lfilter_out, waveform_sox_out, atol=1e-4, rtol=1e-5) + self.assertEqual(waveform_lfilter_out, waveform_sox_out, atol=1e-4, rtol=1e-5) if __name__ == "__main__": diff --git a/test/test_sox_effects.py b/test/test_sox_effects.py index 487d73a53d..213477537e 100644 --- a/test/test_sox_effects.py +++ b/test/test_sox_effects.py @@ -3,14 +3,15 @@ import torchaudio import math -import common_utils -from common_utils import AudioBackendScope, BACKENDS +from . import common_utils +from .common_utils import AudioBackendScope, BACKENDS -@unittest.skipIf("sox" not in BACKENDS, "sox not available") class Test_SoxEffectsChain(unittest.TestCase): test_filepath = common_utils.get_asset_path("steam-train-whistle-daniel_simon.mp3") + @unittest.skipIf("sox" not in BACKENDS, "sox not available") + @AudioBackendScope("sox") def test_single_channel(self): fn_sine = common_utils.get_asset_path("sinewave.wav") E = torchaudio.sox_effects.SoxEffectsChain() @@ -20,6 +21,8 @@ def test_single_channel(self): # check if effects worked # print(x.size()) + @unittest.skipIf("sox" not in BACKENDS, "sox not available") + @AudioBackendScope("sox") def test_rate_channels(self): target_rate = 16000 target_channels = 1 @@ -32,6 +35,8 @@ def test_rate_channels(self): self.assertEqual(sr, target_rate) self.assertEqual(x.size(0), target_channels) + @unittest.skipIf("sox" not in BACKENDS, "sox not available") + @AudioBackendScope("sox") def test_lowpass_speed(self): speed = .8 si, _ = torchaudio.info(self.test_filepath) @@ -44,6 +49,8 @@ def test_lowpass_speed(self): # check if effects worked self.assertEqual(x.size(1), int((si.length / si.channels) / speed)) + @unittest.skipIf("sox" not in BACKENDS, "sox not available") + @AudioBackendScope("sox") def test_ulaw_and_siginfo(self): si_out = torchaudio.sox_signalinfo_t() ei_out = torchaudio.sox_encodinginfo_t() @@ -61,6 +68,8 @@ def test_ulaw_and_siginfo(self): self.assertLess(x.unique().size(0), 2**8 + 1) self.assertEqual(x.numel(), si_in.length) + @unittest.skipIf("sox" not in BACKENDS, "sox not available") + @AudioBackendScope("sox") def test_band_chorus(self): si_in, ei_in = torchaudio.info(self.test_filepath) ei_in.encoding = torchaudio.get_sox_encoding_t(1) @@ -75,6 +84,8 @@ def test_band_chorus(self): self.assertEqual(x.size(0), si_in.channels) self.assertGreaterEqual(x.size(1) * x.size(0), si_in.length) + @unittest.skipIf("sox" not in BACKENDS, "sox not available") + @AudioBackendScope("sox") def test_synth(self): si_in, ei_in = torchaudio.info(self.test_filepath) len_in_seconds = si_in.length / si_in.channels / si_in.rate @@ -88,6 +99,8 @@ def test_synth(self): self.assertEqual(x.size(0), si_in.channels) self.assertEqual(si_in.length, x.size(0) * x.size(1)) + @unittest.skipIf("sox" not in BACKENDS, "sox not available") + @AudioBackendScope("sox") def test_gain(self): E = torchaudio.sox_effects.SoxEffectsChain() E.set_input_file(self.test_filepath) @@ -111,6 +124,8 @@ def test_gain(self): E.clear_chain() self.assertLess(x.abs().max().item(), 1.) + @unittest.skipIf("sox" not in BACKENDS, "sox not available") + @AudioBackendScope("sox") def test_tempo_or_speed(self): tempo = .8 si, _ = torchaudio.info(self.test_filepath) @@ -144,6 +159,8 @@ def test_tempo_or_speed(self): # check if effect worked self.assertAlmostEqual(x.size(1), math.ceil((si.length / si.channels) / speed), delta=1) + @unittest.skipIf("sox" not in BACKENDS, "sox not available") + @AudioBackendScope("sox") def test_trim(self): x_orig, _ = torchaudio.load(self.test_filepath) offset = "10000s" @@ -157,6 +174,8 @@ def test_trim(self): # check if effect worked self.assertTrue(x.allclose(x_orig[:, offset_int:(offset_int + num_frames_int)], rtol=1e-4, atol=1e-4)) + @unittest.skipIf("sox" not in BACKENDS, "sox not available") + @AudioBackendScope("sox") def test_silence_contrast(self): si, _ = torchaudio.info(self.test_filepath) E = torchaudio.sox_effects.SoxEffectsChain() @@ -167,6 +186,8 @@ def test_silence_contrast(self): # check if effect worked self.assertLess(x.numel(), si.length) + @unittest.skipIf("sox" not in BACKENDS, "sox not available") + @AudioBackendScope("sox") def test_reverse(self): x_orig, _ = torchaudio.load(self.test_filepath) E = torchaudio.sox_effects.SoxEffectsChain() @@ -177,6 +198,8 @@ def test_reverse(self): rev_idx = torch.LongTensor(range(x_orig.size(1))[::-1]) self.assertTrue(x_orig.allclose(x_rev[:, rev_idx], rtol=1e-5, atol=2e-5)) + @unittest.skipIf("sox" not in BACKENDS, "sox not available") + @AudioBackendScope("sox") def test_compand_fade(self): E = torchaudio.sox_effects.SoxEffectsChain() E.set_input_file(self.test_filepath) @@ -186,6 +209,8 @@ def test_compand_fade(self): # check if effect worked # print(x.size()) + @unittest.skipIf("sox" not in BACKENDS, "sox not available") + @AudioBackendScope("sox") def test_biquad_delay(self): si, _ = torchaudio.info(self.test_filepath) E = torchaudio.sox_effects.SoxEffectsChain() @@ -197,6 +222,8 @@ def test_biquad_delay(self): # check if effect worked self.assertTrue(x.size(1) == (si.length / si.channels) + 15000) + @unittest.skipIf("sox" not in BACKENDS, "sox not available") + @AudioBackendScope("sox") def test_invalid_effect_name(self): E = torchaudio.sox_effects.SoxEffectsChain() E.set_input_file(self.test_filepath) @@ -204,6 +231,8 @@ def test_invalid_effect_name(self): with self.assertRaises(LookupError): E.append_effect_to_chain("special", [""]) + @unittest.skipIf("sox" not in BACKENDS, "sox not available") + @AudioBackendScope("sox") def test_unimplemented_effect(self): E = torchaudio.sox_effects.SoxEffectsChain() E.set_input_file(self.test_filepath) @@ -211,6 +240,8 @@ def test_unimplemented_effect(self): with self.assertRaises(NotImplementedError): E.append_effect_to_chain("spectrogram", [""]) + @unittest.skipIf("sox" not in BACKENDS, "sox not available") + @AudioBackendScope("sox") def test_invalid_effect_options(self): E = torchaudio.sox_effects.SoxEffectsChain() E.set_input_file(self.test_filepath) @@ -219,6 +250,8 @@ def test_invalid_effect_options(self): with self.assertRaises(RuntimeError): E.sox_build_flow_effects() + @unittest.skipIf("sox" not in BACKENDS, "sox not available") + @AudioBackendScope("sox") def test_fade(self): x_orig, _ = torchaudio.load(self.test_filepath) fade_in_len = 44100 @@ -235,6 +268,8 @@ def test_fade(self): # check if effect worked self.assertTrue(x.allclose(fade(x_orig), rtol=1e-4, atol=1e-4)) + @unittest.skipIf("sox" not in BACKENDS, "sox not available") + @AudioBackendScope("sox") def test_vol(self): x_orig, _ = torchaudio.load(self.test_filepath) @@ -249,10 +284,12 @@ def test_vol(self): # check if effect worked self.assertTrue(x.allclose(z, rtol=1e-4, atol=1e-4)) + @unittest.skipIf("sox" not in BACKENDS, "sox not available") + @AudioBackendScope("sox") def test_vad(self): sample_files = [ - common_utils.get_asset_path("vad-hello-stereo-44100.wav"), - common_utils.get_asset_path("vad-hello-mono-32000.wav") + common_utils.get_asset_path("vad-go-stereo-44100.wav"), + common_utils.get_asset_path("vad-go-mono-32000.wav") ] for sample_file in sample_files: @@ -269,5 +306,4 @@ def test_vad(self): if __name__ == '__main__': - with AudioBackendScope("sox"): - unittest.main() + unittest.main() diff --git a/test/test_transforms.py b/test/test_transforms.py index 9c0313ba7c..02faa68992 100644 --- a/test/test_transforms.py +++ b/test/test_transforms.py @@ -2,14 +2,15 @@ import unittest import torch +from torch.testing._internal.common_utils import TestCase import torchaudio import torchaudio.transforms as transforms import torchaudio.functional as F -import common_utils +from . import common_utils -class Tester(unittest.TestCase): +class Tester(TestCase): # create a sinewave signal for testing sample_rate = 16000 @@ -49,7 +50,7 @@ def test_AmplitudeToDB(self): mag_to_db_torch = mag_to_db_transform(torch.abs(waveform)) power_to_db_torch = power_to_db_transform(torch.pow(waveform, 2)) - torch.testing.assert_allclose(mag_to_db_torch, power_to_db_torch) + self.assertEqual(mag_to_db_torch, power_to_db_torch) def test_melscale_load_save(self): specgram = torch.ones(1, 1000, 100) @@ -63,7 +64,7 @@ def test_melscale_load_save(self): fb_copy = melscale_transform_copy.fb self.assertEqual(fb_copy.size(), (1000, 128)) - torch.testing.assert_allclose(fb, fb_copy) + self.assertEqual(fb, fb_copy) def test_melspectrogram_load_save(self): waveform = self.waveform.float() @@ -79,10 +80,10 @@ def test_melspectrogram_load_save(self): fb = mel_spectrogram_transform.mel_scale.fb fb_copy = mel_spectrogram_transform_copy.mel_scale.fb - torch.testing.assert_allclose(window, window_copy) + self.assertEqual(window, window_copy) # the default for n_fft = 400 and n_mels = 128 self.assertEqual(fb_copy.size(), (201, 128)) - torch.testing.assert_allclose(fb, fb_copy) + self.assertEqual(fb, fb_copy) def test_mel2(self): top_db = 80. @@ -205,7 +206,7 @@ def test_compute_deltas_transform_same_as_functional(self, atol=1e-6, rtol=1e-8) computed_transform = transform(specgram) computed_functional = F.compute_deltas(specgram, win_length=win_length) - torch.testing.assert_allclose(computed_functional, computed_transform, atol=atol, rtol=rtol) + self.assertEqual(computed_functional, computed_transform, atol=atol, rtol=rtol) def test_compute_deltas_twochannel(self): specgram = torch.tensor([1., 2., 3., 4.]).repeat(1, 2, 1) @@ -214,7 +215,7 @@ def test_compute_deltas_twochannel(self): transform = transforms.ComputeDeltas(win_length=3) computed = transform(specgram) assert computed.shape == expected.shape, (computed.shape, expected.shape) - torch.testing.assert_allclose(computed, expected, atol=1e-6, rtol=1e-8) + self.assertEqual(computed, expected, atol=1e-6, rtol=1e-8) if __name__ == '__main__': diff --git a/test/torchscript_consistency_cpu_test.py b/test/torchscript_consistency_cpu_test.py new file mode 100644 index 0000000000..51a3a477f0 --- /dev/null +++ b/test/torchscript_consistency_cpu_test.py @@ -0,0 +1,5 @@ +from .common_utils import define_test_suites +from .torchscript_consistency_impl import Functional, Transforms + + +define_test_suites(globals(), [Functional, Transforms], devices=['cpu']) diff --git a/test/torchscript_consistency_cuda_test.py b/test/torchscript_consistency_cuda_test.py new file mode 100644 index 0000000000..0899ba2066 --- /dev/null +++ b/test/torchscript_consistency_cuda_test.py @@ -0,0 +1,5 @@ +from .common_utils import define_test_suites +from .torchscript_consistency_impl import Functional, Transforms + + +define_test_suites(globals(), [Functional, Transforms], devices=['cuda']) diff --git a/test/test_torchscript_consistency.py b/test/torchscript_consistency_impl.py similarity index 74% rename from test/test_torchscript_consistency.py rename to test/torchscript_consistency_impl.py index 5f0b12c76b..a4d3cc79cf 100644 --- a/test/test_torchscript_consistency.py +++ b/test/torchscript_consistency_impl.py @@ -6,36 +6,21 @@ import torchaudio.functional as F import torchaudio.transforms as T -import common_utils +from . import common_utils -def _assert_functional_consistency(func, tensor, device, shape_only=False): - tensor = tensor.to(device) - ts_func = torch.jit.script(func) - output = func(tensor) - ts_output = ts_func(tensor) - - if shape_only: - assert ts_output.shape == output.shape, (ts_output.shape, output.shape) - else: - torch.testing.assert_allclose(ts_output, output) - - -def _assert_transforms_consistency(transform, tensor, device): - tensor = tensor.to(device) - transform = transform.to(device) - ts_transform = torch.jit.script(transform) - output = transform(tensor) - ts_output = ts_transform(tensor) - torch.testing.assert_allclose(ts_output, output) - - -class _FunctionalTestMixin: +class Functional(common_utils.TestBaseMixin): """Implements test for `functinoal` modul that are performed for different devices""" - device = None - def _assert_consistency(self, func, tensor, shape_only=False): - return _assert_functional_consistency(func, tensor, self.device, shape_only=shape_only) + tensor = tensor.to(device=self.device, dtype=self.dtype) + + ts_func = torch.jit.script(func) + output = func(tensor) + ts_output = ts_func(tensor) + if shape_only: + ts_output = ts_output.shape + output = output.shape + self.assertEqual(ts_output, output) def test_spectrogram(self): def func(tensor): @@ -48,7 +33,7 @@ def func(tensor): normalize = False return F.spectrogram(tensor, pad, window, n_fft, hop, ws, power, normalize) - tensor = torch.rand((1, 1000)) + tensor = common_utils.get_whitenoise() self._assert_consistency(func, tensor) def test_griffinlim(self): @@ -80,8 +65,7 @@ def func(tensor): self._assert_consistency(func, tensor) def test_detect_pitch_frequency(self): - filepath = common_utils.get_asset_path('steam-train-whistle-daniel_simon.mp3') - waveform, _ = torchaudio.load(filepath) + waveform = common_utils.get_sinusoid(sample_rate=44100) def func(tensor): sample_rate = 44100 @@ -99,7 +83,8 @@ def func(_): f_max = 20.0 n_mels = 10 sample_rate = 16000 - return F.create_fb_matrix(n_stft, f_min, f_max, n_mels, sample_rate) + norm = "slaney" + return F.create_fb_matrix(n_stft, f_min, f_max, n_mels, sample_rate, norm) dummy = torch.zeros(1, 1) self._assert_consistency(func, dummy) @@ -142,8 +127,8 @@ def func(tensor): qc = 256 return F.mu_law_encoding(tensor, qc) - tensor = torch.rand((1, 10)) - self._assert_consistency(func, tensor) + waveform = common_utils.get_whitenoise() + self._assert_consistency(func, waveform) def test_mu_law_decoding(self): def func(tensor): @@ -159,7 +144,7 @@ def func(tensor): return F.complex_norm(tensor, power) tensor = torch.randn(1, 2, 1025, 400, 2) - _assert_functional_consistency(func, tensor, self.device) + self._assert_consistency(func, tensor) def test_mask_along_axis(self): def func(tensor): @@ -193,26 +178,28 @@ def test_dither_TPDF(self): def func(tensor): return F.dither(tensor, 'TPDF') - tensor = torch.rand((2, 1000)) + tensor = common_utils.get_whitenoise(n_channels=2) self._assert_consistency(func, tensor, shape_only=True) def test_dither_RPDF(self): def func(tensor): return F.dither(tensor, 'RPDF') - tensor = torch.rand((2, 1000)) + tensor = common_utils.get_whitenoise(n_channels=2) self._assert_consistency(func, tensor, shape_only=True) def test_dither_GPDF(self): def func(tensor): return F.dither(tensor, 'GPDF') - tensor = torch.rand((2, 1000)) + tensor = common_utils.get_whitenoise(n_channels=2) self._assert_consistency(func, tensor, shape_only=True) def test_lfilter(self): - filepath = common_utils.get_asset_path('whitenoise.wav') - waveform, _ = torchaudio.load(filepath, normalization=True) + if self.dtype == torch.float64: + raise unittest.SkipTest("This test is known to fail for float64") + + waveform = common_utils.get_whitenoise() def func(tensor): # Design an IIR lowpass filter using scipy.signal filter design @@ -252,8 +239,10 @@ def func(tensor): self._assert_consistency(func, waveform) def test_lowpass(self): - filepath = common_utils.get_asset_path('whitenoise.wav') - waveform, _ = torchaudio.load(filepath, normalization=True) + if self.dtype == torch.float64: + raise unittest.SkipTest("This test is known to fail for float64") + + waveform = common_utils.get_whitenoise(sample_rate=44100) def func(tensor): sample_rate = 44100 @@ -263,8 +252,10 @@ def func(tensor): self._assert_consistency(func, waveform) def test_highpass(self): - filepath = common_utils.get_asset_path('whitenoise.wav') - waveform, _ = torchaudio.load(filepath, normalization=True) + if self.dtype == torch.float64: + raise unittest.SkipTest("This test is known to fail for float64") + + waveform = common_utils.get_whitenoise(sample_rate=44100) def func(tensor): sample_rate = 44100 @@ -274,8 +265,10 @@ def func(tensor): self._assert_consistency(func, waveform) def test_allpass(self): - filepath = common_utils.get_asset_path('whitenoise.wav') - waveform, _ = torchaudio.load(filepath, normalization=True) + if self.dtype == torch.float64: + raise unittest.SkipTest("This test is known to fail for float64") + + waveform = common_utils.get_whitenoise(sample_rate=44100) def func(tensor): sample_rate = 44100 @@ -286,8 +279,10 @@ def func(tensor): self._assert_consistency(func, waveform) def test_bandpass_with_csg(self): - filepath = common_utils.get_asset_path("whitenoise.wav") - waveform, _ = torchaudio.load(filepath, normalization=True) + if self.dtype == torch.float64: + raise unittest.SkipTest("This test is known to fail for float64") + + waveform = common_utils.get_whitenoise(sample_rate=44100) def func(tensor): sample_rate = 44100 @@ -298,9 +293,11 @@ def func(tensor): self._assert_consistency(func, waveform) - def test_bandpass_withou_csg(self): - filepath = common_utils.get_asset_path("whitenoise.wav") - waveform, _ = torchaudio.load(filepath, normalization=True) + def test_bandpass_without_csg(self): + if self.dtype == torch.float64: + raise unittest.SkipTest("This test is known to fail for float64") + + waveform = common_utils.get_whitenoise(sample_rate=44100) def func(tensor): sample_rate = 44100 @@ -312,8 +309,10 @@ def func(tensor): self._assert_consistency(func, waveform) def test_bandreject(self): - filepath = common_utils.get_asset_path("whitenoise.wav") - waveform, _ = torchaudio.load(filepath, normalization=True) + if self.dtype == torch.float64: + raise unittest.SkipTest("This test is known to fail for float64") + + waveform = common_utils.get_whitenoise(sample_rate=44100) def func(tensor): sample_rate = 44100 @@ -324,8 +323,10 @@ def func(tensor): self._assert_consistency(func, waveform) def test_band_with_noise(self): - filepath = common_utils.get_asset_path("whitenoise.wav") - waveform, _ = torchaudio.load(filepath, normalization=True) + if self.dtype == torch.float64: + raise unittest.SkipTest("This test is known to fail for float64") + + waveform = common_utils.get_whitenoise(sample_rate=44100) def func(tensor): sample_rate = 44100 @@ -337,8 +338,10 @@ def func(tensor): self._assert_consistency(func, waveform) def test_band_without_noise(self): - filepath = common_utils.get_asset_path("whitenoise.wav") - waveform, _ = torchaudio.load(filepath, normalization=True) + if self.dtype == torch.float64: + raise unittest.SkipTest("This test is known to fail for float64") + + waveform = common_utils.get_whitenoise(sample_rate=44100) def func(tensor): sample_rate = 44100 @@ -350,8 +353,10 @@ def func(tensor): self._assert_consistency(func, waveform) def test_treble(self): - filepath = common_utils.get_asset_path("whitenoise.wav") - waveform, _ = torchaudio.load(filepath, normalization=True) + if self.dtype == torch.float64: + raise unittest.SkipTest("This test is known to fail for float64") + + waveform = common_utils.get_whitenoise(sample_rate=44100) def func(tensor): sample_rate = 44100 @@ -363,8 +368,10 @@ def func(tensor): self._assert_consistency(func, waveform) def test_deemph(self): - filepath = common_utils.get_asset_path("whitenoise.wav") - waveform, _ = torchaudio.load(filepath, normalization=True) + if self.dtype == torch.float64: + raise unittest.SkipTest("This test is known to fail for float64") + + waveform = common_utils.get_whitenoise(sample_rate=44100) def func(tensor): sample_rate = 44100 @@ -373,8 +380,10 @@ def func(tensor): self._assert_consistency(func, waveform) def test_riaa(self): - filepath = common_utils.get_asset_path("whitenoise.wav") - waveform, _ = torchaudio.load(filepath, normalization=True) + if self.dtype == torch.float64: + raise unittest.SkipTest("This test is known to fail for float64") + + waveform = common_utils.get_whitenoise(sample_rate=44100) def func(tensor): sample_rate = 44100 @@ -383,8 +392,10 @@ def func(tensor): self._assert_consistency(func, waveform) def test_equalizer(self): - filepath = common_utils.get_asset_path("whitenoise.wav") - waveform, _ = torchaudio.load(filepath, normalization=True) + if self.dtype == torch.float64: + raise unittest.SkipTest("This test is known to fail for float64") + + waveform = common_utils.get_whitenoise(sample_rate=44100) def func(tensor): sample_rate = 44100 @@ -396,8 +407,10 @@ def func(tensor): self._assert_consistency(func, waveform) def test_perf_biquad_filtering(self): - filepath = common_utils.get_asset_path("whitenoise.wav") - waveform, _ = torchaudio.load(filepath, normalization=True) + if self.dtype == torch.float64: + raise unittest.SkipTest("This test is known to fail for float64") + + waveform = common_utils.get_whitenoise() def func(tensor): a = torch.tensor([0.7, 0.2, 0.6], device=tensor.device, dtype=tensor.dtype) @@ -442,8 +455,7 @@ def func(tensor): self._assert_consistency(func, b) def test_contrast(self): - filepath = common_utils.get_asset_path("whitenoise.wav") - waveform, _ = torchaudio.load(filepath, normalization=True) + waveform = common_utils.get_whitenoise() def func(tensor): enhancement_amount = 80. @@ -452,8 +464,7 @@ def func(tensor): self._assert_consistency(func, waveform) def test_dcshift(self): - filepath = common_utils.get_asset_path("whitenoise.wav") - waveform, _ = torchaudio.load(filepath, normalization=True) + waveform = common_utils.get_whitenoise() def func(tensor): shift = 0.5 @@ -463,8 +474,7 @@ def func(tensor): self._assert_consistency(func, waveform) def test_overdrive(self): - filepath = common_utils.get_asset_path("whitenoise.wav") - waveform, _ = torchaudio.load(filepath, normalization=True) + waveform = common_utils.get_whitenoise() def func(tensor): gain = 30. @@ -473,13 +483,31 @@ def func(tensor): self._assert_consistency(func, waveform) + def test_phaser(self): + waveform = common_utils.get_whitenoise(sample_rate=44100) -class _TransformsTestMixin: - """Implements test for Transforms that are performed for different devices""" - device = None + def func(tensor): + gain_in = 0.5 + gain_out = 0.8 + delay_ms = 2.0 + decay = 0.4 + speed = 0.5 + sample_rate = 44100 + return F.phaser(tensor, sample_rate, gain_in, gain_out, delay_ms, decay, speed, sinusoidal=True) + self._assert_consistency(func, waveform) + + +class Transforms(common_utils.TestBaseMixin): + """Implements test for Transforms that are performed for different devices""" def _assert_consistency(self, transform, tensor): - _assert_transforms_consistency(transform, tensor, self.device) + tensor = tensor.to(device=self.device, dtype=self.dtype) + transform = transform.to(device=self.device, dtype=self.dtype) + + ts_transform = torch.jit.script(transform) + output = transform(tensor) + ts_output = ts_transform(tensor) + self.assertEqual(ts_output, output) def test_Spectrogram(self): tensor = torch.rand((1, 1000)) @@ -506,17 +534,16 @@ def test_MFCC(self): self._assert_consistency(T.MFCC(), tensor) def test_Resample(self): - tensor = torch.rand((2, 1000)) - sample_rate = 100. - sample_rate_2 = 50. - self._assert_consistency(T.Resample(sample_rate, sample_rate_2), tensor) + sr1, sr2 = 16000, 8000 + tensor = common_utils.get_whitenoise(sample_rate=sr1) + self._assert_consistency(T.Resample(float(sr1), float(sr2)), tensor) def test_ComplexNorm(self): tensor = torch.rand((1, 2, 201, 2)) self._assert_consistency(T.ComplexNorm(), tensor) def test_MuLawEncoding(self): - tensor = torch.rand((1, 10)) + tensor = common_utils.get_whitenoise() self._assert_consistency(T.MuLawEncoding(), tensor) def test_MuLawDecoding(self): @@ -534,8 +561,7 @@ def test_TimeStretch(self): ) def test_Fade(self): - test_filepath = common_utils.get_asset_path('steam-train-whistle-daniel_simon.wav') - waveform, _ = torchaudio.load(test_filepath) + waveform = common_utils.get_whitenoise() fade_in_len = 3000 fade_out_len = 3000 self._assert_consistency(T.Fade(fade_in_len, fade_out_len), waveform) @@ -549,8 +575,7 @@ def test_TimeMasking(self): self._assert_consistency(T.TimeMasking(time_mask_param=30, iid_masks=False), tensor) def test_Vol(self): - test_filepath = common_utils.get_asset_path('steam-train-whistle-daniel_simon.wav') - waveform, _ = torchaudio.load(test_filepath) + waveform = common_utils.get_whitenoise() self._assert_consistency(T.Vol(1.1), waveform) def test_SlidingWindowCmn(self): @@ -558,32 +583,6 @@ def test_SlidingWindowCmn(self): self._assert_consistency(T.SlidingWindowCmn(), tensor) def test_Vad(self): - filepath = common_utils.get_asset_path("vad-hello-mono-32000.wav") + filepath = common_utils.get_asset_path("vad-go-mono-32000.wav") waveform, sample_rate = torchaudio.load(filepath) self._assert_consistency(T.Vad(sample_rate=sample_rate), waveform) - - -class TestFunctionalCPU(_FunctionalTestMixin, unittest.TestCase): - """Test suite for Functional module on CPU""" - device = torch.device('cpu') - - -@unittest.skipIf(not torch.cuda.is_available(), 'CUDA not available') -class TestFunctionalCUDA(_FunctionalTestMixin, unittest.TestCase): - """Test suite for Functional module on GPU""" - device = torch.device('cuda') - - -class TestTransformsCPU(_TransformsTestMixin, unittest.TestCase): - """Test suite for Transforms module on CPU""" - device = torch.device('cpu') - - -@unittest.skipIf(not torch.cuda.is_available(), 'CUDA not available') -class TestTransformsCUDA(_TransformsTestMixin, unittest.TestCase): - """Test suite for Transforms module on GPU""" - device = torch.device('cuda') - - -if __name__ == '__main__': - unittest.main() diff --git a/torchaudio/__init__.py b/torchaudio/__init__.py index e748a34bc2..a08eaf6964 100644 --- a/torchaudio/__init__.py +++ b/torchaudio/__init__.py @@ -193,8 +193,8 @@ def save_encinfo(filepath: str, # save data to file src = src.contiguous() - import _torch_sox - _torch_sox.write_audio_file(filepath, src, signalinfo, encodinginfo, filetype) + from . import _torchaudio + _torchaudio.write_audio_file(filepath, src, signalinfo, encodinginfo, filetype) def info(filepath: str) -> Tuple[SignalInfo, EncodingInfo]: @@ -236,8 +236,8 @@ def sox_signalinfo_t() -> SignalInfo: >>> si.length = 0 """ - import _torch_sox - return _torch_sox.sox_signalinfo_t() + from . import _torchaudio + return _torchaudio.sox_signalinfo_t() @_audio_backend_guard("sox") @@ -271,8 +271,8 @@ def sox_encodinginfo_t() -> EncodingInfo: """ - import _torch_sox - ei = _torch_sox.sox_encodinginfo_t() + from . import _torchaudio + ei = _torchaudio.sox_encodinginfo_t() sdo = get_sox_option_t(2) # sox_default_option ei.reverse_bytes = sdo ei.reverse_nibbles = sdo @@ -292,12 +292,12 @@ def get_sox_encoding_t(i: int = None) -> EncodingInfo: sox_encoding_t: A sox_encoding_t type for output encoding """ - import _torch_sox + from . import _torchaudio if i is None: # one can see all possible values using the .__members__ attribute - return _torch_sox.sox_encoding_t + return _torchaudio.sox_encoding_t else: - return _torch_sox.sox_encoding_t(i) + return _torchaudio.sox_encoding_t(i) @_audio_backend_guard("sox") @@ -312,11 +312,11 @@ def get_sox_option_t(i: int = 2) -> Any: sox_option_t: A sox_option_t type """ - import _torch_sox + from . import _torchaudio if i is None: - return _torch_sox.sox_option_t + return _torchaudio.sox_option_t else: - return _torch_sox.sox_option_t(i) + return _torchaudio.sox_option_t(i) @_audio_backend_guard("sox") @@ -332,14 +332,14 @@ def get_sox_bool(i: int = 0) -> Any: sox_bool: A sox_bool type """ - import _torch_sox + from . import _torchaudio if i is None: - return _torch_sox.sox_bool + return _torchaudio.sox_bool else: - return _torch_sox.sox_bool(i) + return _torchaudio.sox_bool(i) -_SOX_INITIALIZED = False +_SOX_INITIALIZED: Optional[bool] = False # This variable has a micro lifecycle. (False -> True -> None) # False: Not initialized # True: Initialized @@ -370,8 +370,8 @@ def initialize_sox() -> int: if _SOX_INITIALIZED is None: raise RuntimeError('SoX effects chain has been already shut down. Can not initialize again.') if not _SOX_INITIALIZED: - import _torch_sox - code = _torch_sox.initialize_sox() + from . import _torchaudio + code = _torchaudio.initialize_sox() if code == _SOX_SUCCESS_CODE: _SOX_INITIALIZED = True atexit.register(shutdown_sox) @@ -394,8 +394,8 @@ def shutdown_sox() -> int: """ global _SOX_INITIALIZED if _SOX_INITIALIZED: - import _torch_sox - code = _torch_sox.shutdown_sox() + from . import _torchaudio + code = _torchaudio.shutdown_sox() if code == _SOX_INITIALIZED: _SOX_INITIALIZED = None return code diff --git a/torchaudio/_sox_backend.py b/torchaudio/_sox_backend.py index 802bd0fe17..3478d30d50 100644 --- a/torchaudio/_sox_backend.py +++ b/torchaudio/_sox_backend.py @@ -35,8 +35,8 @@ def load(filepath: str, if offset < 0: raise ValueError("Expected positive offset value") - import _torch_sox - sample_rate = _torch_sox.read_audio_file( + from . import _torchaudio + sample_rate = _torchaudio.read_audio_file( filepath, out, channels_first, @@ -68,5 +68,5 @@ def save(filepath: str, src: Tensor, sample_rate: int, precision: int = 16, chan def info(filepath: str) -> Tuple[SignalInfo, EncodingInfo]: r"""See torchaudio.info""" - import _torch_sox - return _torch_sox.get_info(filepath) + from . import _torchaudio + return _torchaudio.get_info(filepath) diff --git a/torchaudio/compliance/kaldi.py b/torchaudio/compliance/kaldi.py index e9189b2172..8115c3a25f 100644 --- a/torchaudio/compliance/kaldi.py +++ b/torchaudio/compliance/kaldi.py @@ -33,6 +33,10 @@ WINDOWS = [HAMMING, HANNING, POVEY, RECTANGULAR, BLACKMAN] +def _get_epsilon(device, dtype): + return EPSILON.to(device=device, dtype=dtype) + + def _next_power_of_2(x: int) -> int: r"""Returns the smallest power of 2 that is greater than x """ @@ -60,7 +64,7 @@ def _get_strided(waveform: Tensor, window_size: int, window_shift: int, snip_edg if snip_edges: if num_samples < window_size: - return torch.empty((0, 0)) + return torch.empty((0, 0), dtype=waveform.dtype, device=waveform.device) else: m = 1 + (num_samples - window_size) // window_shift else: @@ -83,24 +87,27 @@ def _get_strided(waveform: Tensor, window_size: int, window_shift: int, snip_edg def _feature_window_function(window_type: str, window_size: int, - blackman_coeff: float) -> Tensor: + blackman_coeff: float, + device: torch.device, + dtype: int, + ) -> Tensor: r"""Returns a window function with the given type and size """ if window_type == HANNING: - return torch.hann_window(window_size, periodic=False) + return torch.hann_window(window_size, periodic=False, device=device, dtype=dtype) elif window_type == HAMMING: - return torch.hamming_window(window_size, periodic=False, alpha=0.54, beta=0.46) + return torch.hamming_window(window_size, periodic=False, alpha=0.54, beta=0.46, device=device, dtype=dtype) elif window_type == POVEY: # like hanning but goes to zero at edges - return torch.hann_window(window_size, periodic=False).pow(0.85) + return torch.hann_window(window_size, periodic=False, device=device, dtype=dtype).pow(0.85) elif window_type == RECTANGULAR: - return torch.ones(window_size) + return torch.ones(window_size, device=device, dtype=dtype) elif window_type == BLACKMAN: a = 2 * math.pi / (window_size - 1) - window_function = torch.arange(window_size) + window_function = torch.arange(window_size, device=device, dtype=dtype) # can't use torch.blackman_window as they use different coefficients return (blackman_coeff - 0.5 * torch.cos(a * window_function) + - (0.5 - blackman_coeff) * torch.cos(2 * a * window_function)) + (0.5 - blackman_coeff) * torch.cos(2 * a * window_function)).to(device=device, dtype=dtype) else: raise Exception('Invalid window type ' + window_type) @@ -110,12 +117,12 @@ def _get_log_energy(strided_input: Tensor, energy_floor: float) -> Tensor: r"""Returns the log energy of size (m) for a strided_input (m,*) """ + device, dtype = strided_input.device, strided_input.dtype log_energy = torch.max(strided_input.pow(2).sum(1), epsilon).log() # size (m) if energy_floor == 0.0: return log_energy - else: - return torch.max(log_energy, - torch.tensor(math.log(energy_floor))) + return torch.max( + log_energy, torch.tensor(math.log(energy_floor), device=device, dtype=dtype)) def _get_waveform_and_window_properties(waveform: Tensor, @@ -160,12 +167,15 @@ def _get_window(waveform: Tensor, Returns: (Tensor, Tensor): strided_input of size (m, ``padded_window_size``) and signal_log_energy of size (m) """ + device, dtype = waveform.device, waveform.dtype + epsilon = _get_epsilon(device, dtype) + # size (m, window_size) strided_input = _get_strided(waveform, window_size, window_shift, snip_edges) if dither != 0.0: # Returns a random number strictly between 0 and 1 - x = torch.max(EPSILON, torch.rand(strided_input.shape)) + x = torch.max(epsilon, torch.rand(strided_input.shape, device=device, dtype=dtype)) rand_gauss = torch.sqrt(-2 * x.log()) * torch.cos(2 * math.pi * x) strided_input = strided_input + rand_gauss * dither @@ -177,7 +187,7 @@ def _get_window(waveform: Tensor, if raw_energy: # Compute the log energy of each row/frame before applying preemphasis and # window function - signal_log_energy = _get_log_energy(strided_input, EPSILON, energy_floor) # size (m) + signal_log_energy = _get_log_energy(strided_input, epsilon, energy_floor) # size (m) if preemphasis_coefficient != 0.0: # strided_input[i,j] -= preemphasis_coefficient * strided_input[i, max(0, j-1)] for all i,j @@ -187,7 +197,7 @@ def _get_window(waveform: Tensor, # Apply window_function to each row/frame window_function = _feature_window_function( - window_type, window_size, blackman_coeff).unsqueeze(0) # size (1, window_size) + window_type, window_size, blackman_coeff, device, dtype).unsqueeze(0) # size (1, window_size) strided_input = strided_input * window_function # size (m, window_size) # Pad columns with zero until we reach size (m, padded_window_size) @@ -198,7 +208,7 @@ def _get_window(waveform: Tensor, # Compute energy after window function (not the raw one) if not raw_energy: - signal_log_energy = _get_log_energy(strided_input, EPSILON, energy_floor) # size (m) + signal_log_energy = _get_log_energy(strided_input, epsilon, energy_floor) # size (m) return strided_input, signal_log_energy @@ -541,12 +551,14 @@ def fbank(waveform: Tensor, Tensor: A fbank identical to what Kaldi would output. The shape is (m, ``num_mel_bins + use_energy``) where m is calculated in _get_strided """ + device, dtype = waveform.device, waveform.dtype + waveform, window_shift, window_size, padded_window_size = _get_waveform_and_window_properties( waveform, channel, sample_frequency, frame_shift, frame_length, round_to_power_of_two, preemphasis_coefficient) if len(waveform) < min_duration * sample_frequency: # signal is too short - return torch.empty(0) + return torch.empty(0, device=device, dtype=dtype) # strided_input, size (m, padded_window_size) and signal_log_energy, size (m) strided_input, signal_log_energy = _get_window( @@ -563,6 +575,7 @@ def fbank(waveform: Tensor, # size (num_mel_bins, padded_window_size // 2) mel_energies, _ = get_mel_banks(num_mel_bins, padded_window_size, sample_frequency, low_freq, high_freq, vtln_low, vtln_high, vtln_warp) + mel_energies = mel_energies.to(device=device, dtype=dtype) # pad right column with zeros and add dimension, size (1, num_mel_bins, padded_window_size // 2 + 1) mel_energies = torch.nn.functional.pad(mel_energies, (0, 1), mode='constant', value=0).unsqueeze(0) @@ -571,7 +584,7 @@ def fbank(waveform: Tensor, mel_energies = (power_spectrum * mel_energies).sum(dim=2) if use_log_fbank: # avoid log of zero (which should be prevented anyway by dithering) - mel_energies = torch.max(mel_energies, EPSILON).log() + mel_energies = torch.max(mel_energies, _get_epsilon(device, dtype)).log() # if use_energy then add it as the last column for htk_compat == true else first column if use_energy: @@ -737,7 +750,9 @@ def _get_LR_indices_and_weights(orig_freq: float, output_samples_in_unit: int, window_width: float, lowpass_cutoff: float, - lowpass_filter_width: int) -> Tuple[Tensor, Tensor]: + lowpass_filter_width: int, + device: torch.device, + dtype: int) -> Tuple[Tensor, Tensor]: r"""Based on LinearResample::SetIndexesAndWeights where it retrieves the weights for resampling as well as the indices in which they are valid. LinearResample (LR) means that the output signal is at linearly spaced intervals (i.e the output signal has a @@ -785,7 +800,7 @@ def _get_LR_indices_and_weights(orig_freq: float, which correspond with min_input_index, size (``output_samples_in_unit``, ``max_weight_width``)). """ assert lowpass_cutoff < min(orig_freq, new_freq) / 2 - output_t = torch.arange(0., output_samples_in_unit) / new_freq + output_t = torch.arange(0., output_samples_in_unit, device=device, dtype=dtype) / new_freq min_t = output_t - window_width max_t = output_t + window_width @@ -795,7 +810,7 @@ def _get_LR_indices_and_weights(orig_freq: float, max_weight_width = num_indices.max() # create a group of weights of size (output_samples_in_unit, max_weight_width) - j = torch.arange(max_weight_width).unsqueeze(0) + j = torch.arange(max_weight_width, device=device, dtype=dtype).unsqueeze(0) input_index = min_input_index.unsqueeze(1) + j delta_t = (input_index / orig_freq) - output_t.unsqueeze(1) @@ -890,6 +905,8 @@ def resample_waveform(waveform: Tensor, Returns: Tensor: The waveform at the new frequency """ + device, dtype = waveform.device, waveform.dtype + assert waveform.dim() == 2 assert orig_freq > 0.0 and new_freq > 0.0 @@ -903,9 +920,9 @@ def resample_waveform(waveform: Tensor, output_samples_in_unit = int(new_freq) // base_freq window_width = lowpass_filter_width / (2.0 * lowpass_cutoff) - first_indices, weights = _get_LR_indices_and_weights(orig_freq, new_freq, output_samples_in_unit, - window_width, lowpass_cutoff, lowpass_filter_width) - weights = weights.to(waveform.device) # TODO Create weights on device directly + first_indices, weights = _get_LR_indices_and_weights( + orig_freq, new_freq, output_samples_in_unit, + window_width, lowpass_cutoff, lowpass_filter_width, device, dtype) assert first_indices.dim() == 1 # TODO figure a better way to do this. conv1d reaches every element i*stride + padding @@ -918,9 +935,9 @@ def resample_waveform(waveform: Tensor, window_size = weights.size(1) tot_output_samp = _get_num_LR_output_samples(wave_len, orig_freq, new_freq) output = torch.zeros((num_channels, tot_output_samp), - device=waveform.device) + device=device, dtype=dtype) # eye size: (num_channels, num_channels, 1) - eye = torch.eye(num_channels, device=waveform.device).unsqueeze(2) + eye = torch.eye(num_channels, device=device, dtype=dtype).unsqueeze(2) for i in range(first_indices.size(0)): wave_to_conv = waveform first_index = int(first_indices[i].item()) diff --git a/torchaudio/torch_sox.cpp b/torchaudio/csrc/sox.cpp similarity index 98% rename from torchaudio/torch_sox.cpp rename to torchaudio/csrc/sox.cpp index 5f5a182ebc..3ae81bef19 100644 --- a/torchaudio/torch_sox.cpp +++ b/torchaudio/csrc/sox.cpp @@ -1,6 +1,4 @@ -#include - -#include +#include #include #include @@ -70,12 +68,6 @@ void read_audio( } } // namespace -struct SoxEffect { - SoxEffect() : ename(""), eopts({""}) { } - std::string ename; - std::vector eopts; -}; - std::tuple get_info( const std::string& file_name ) { @@ -195,7 +187,7 @@ void write_audio_file( } int initialize_sox() { - /* Initializion for sox effects. Only initialize once */ + /* Initialization for sox effects. Only initialize once */ return sox_init(); } @@ -389,7 +381,7 @@ int build_flow_effects(const std::string& file_name, } // namespace audio } // namespace torch -PYBIND11_MODULE(_torch_sox, m) { +PYBIND11_MODULE(_torchaudio, m) { py::class_(m, "SoxEffect") .def(py::init<>()) .def("__repr__", [](const torch::audio::SoxEffect &self) { diff --git a/torchaudio/torch_sox.h b/torchaudio/csrc/sox.h similarity index 88% rename from torchaudio/torch_sox.h rename to torchaudio/csrc/sox.h index 9714fc90ba..8d851c9b21 100644 --- a/torchaudio/torch_sox.h +++ b/torchaudio/csrc/sox.h @@ -1,4 +1,10 @@ +#include + #include +#include +#include + +#include namespace at { struct Tensor; @@ -9,7 +15,7 @@ namespace torch { namespace audio { /// Reads an audio file from the given `path` into the `output` `Tensor` and /// returns the sample rate of the audio file. /// Throws `std::runtime_error` if the audio file could not be opened, or an -/// error ocurred during reading of the audio data. +/// error occurred during reading of the audio data. int read_audio_file( const std::string& file_name, at::Tensor output, @@ -18,24 +24,24 @@ int read_audio_file( int64_t offset, sox_signalinfo_t* si, sox_encodinginfo_t* ei, - const char* ft) + const char* ft); /// Writes the data of a `Tensor` into an audio file at the given `path`, with /// a certain extension (e.g. `wav`or `mp3`) and sample rate. /// Throws `std::runtime_error` when the audio file could not be opened for -/// writing, or an error ocurred during writing of the audio data. +/// writing, or an error occurred during writing of the audio data. void write_audio_file( const std::string& file_name, - at::Tensor& tensor, + const at::Tensor& tensor, sox_signalinfo_t* si, sox_encodinginfo_t* ei, - const char* file_type) + const char* file_type); /// Reads an audio file from the given `path` and returns a tuple of /// sox_signalinfo_t and sox_encodinginfo_t, which contain information about /// the audio file such as sample rate, length, bit precision, encoding and more. /// Throws `std::runtime_error` if the audio file could not be opened, or an -/// error ocurred during reading of the audio data. +/// error occurred during reading of the audio data. std::tuple get_info( const std::string& file_name); diff --git a/torchaudio/functional.py b/torchaudio/functional.py index cb5156596d..f59c46eb14 100644 --- a/torchaudio/functional.py +++ b/torchaudio/functional.py @@ -2,6 +2,7 @@ import math from typing import Optional, Tuple +import warnings import torch from torch import Tensor @@ -34,6 +35,7 @@ "contrast", "dcshift", "overdrive", + "phaser", 'mask_along_axis', 'mask_along_axis_iid', 'sliding_window_cmn', @@ -48,7 +50,7 @@ def istft( win_length: Optional[int] = None, window: Optional[Tensor] = None, center: bool = True, - pad_mode: str = "reflect", + pad_mode: Optional[str] = None, normalized: bool = False, onesided: bool = True, length: Optional[int] = None, @@ -93,8 +95,7 @@ def istft( center (bool, optional): Whether ``input`` was padded on both sides so that the :math:`t`-th frame is centered at time :math:`t \times \text{hop\_length}`. (Default: ``True``) - pad_mode (str, optional): Controls the padding method used when ``center`` is True. (Default: - ``"reflect"``) + pad_mode: This argument was ignored and to be removed. normalized (bool, optional): Whether the STFT was normalized. (Default: ``False``) onesided (bool, optional): Whether the STFT is onesided. (Default: ``True``) length (int or None, optional): The amount to trim the signal by (i.e. the @@ -103,105 +104,16 @@ def istft( Returns: Tensor: Least squares estimation of the original signal of size (..., signal_length) """ - stft_matrix_dim = stft_matrix.dim() - assert 3 <= stft_matrix_dim, "Incorrect stft dimension: %d" % (stft_matrix_dim) - assert stft_matrix.numel() > 0 - - if stft_matrix_dim == 3: - # add a channel dimension - stft_matrix = stft_matrix.unsqueeze(0) - - # pack batch - shape = stft_matrix.size() - stft_matrix = stft_matrix.view(-1, shape[-3], shape[-2], shape[-1]) - - dtype = stft_matrix.dtype - device = stft_matrix.device - fft_size = stft_matrix.size(1) - assert (onesided and n_fft // 2 + 1 == fft_size) or ( - not onesided and n_fft == fft_size - ), ( - "one_sided implies that n_fft // 2 + 1 == fft_size and not one_sided implies n_fft == fft_size. " - + "Given values were onesided: %s, n_fft: %d, fft_size: %d" - % ("True" if onesided else False, n_fft, fft_size) - ) - - # use stft defaults for Optionals - if win_length is None: - win_length = n_fft - - if hop_length is None: - hop_length = int(win_length // 4) - - # There must be overlap - assert 0 < hop_length <= win_length - assert 0 < win_length <= n_fft - - if window is None: - window = torch.ones(win_length, device=device, dtype=dtype) - - assert window.dim() == 1 and window.size(0) == win_length - - if win_length != n_fft: - # center window with pad left and right zeros - left = (n_fft - win_length) // 2 - window = torch.nn.functional.pad(window, (left, n_fft - win_length - left)) - assert window.size(0) == n_fft - # win_length and n_fft are synonymous from here on - - stft_matrix = stft_matrix.transpose(1, 2) # size (channel, n_frame, fft_size, 2) - stft_matrix = torch.irfft( - stft_matrix, 1, normalized, onesided, signal_sizes=(n_fft,) - ) # size (channel, n_frame, n_fft) - - assert stft_matrix.size(2) == n_fft - n_frame = stft_matrix.size(1) - - ytmp = stft_matrix * window.view(1, 1, n_fft) # size (channel, n_frame, n_fft) - # each column of a channel is a frame which needs to be overlap added at the right place - ytmp = ytmp.transpose(1, 2) # size (channel, n_fft, n_frame) - - # this does overlap add where the frames of ytmp are added such that the i'th frame of - # ytmp is added starting at i*hop_length in the output - y = torch.nn.functional.fold( - ytmp, (1, (n_frame - 1) * hop_length + n_fft), (1, n_fft), stride=(1, hop_length) - ).squeeze(2) - - # do the same for the window function - window_sq = ( - window.pow(2).view(n_fft, 1).repeat((1, n_frame)).unsqueeze(0) - ) # size (1, n_fft, n_frame) - window_envelop = torch.nn.functional.fold( - window_sq, (1, (n_frame - 1) * hop_length + n_fft), (1, n_fft), stride=(1, hop_length) - ).squeeze(2) # size (1, 1, expected_signal_len) - - expected_signal_len = n_fft + hop_length * (n_frame - 1) - assert y.size(2) == expected_signal_len - assert window_envelop.size(2) == expected_signal_len - - half_n_fft = n_fft // 2 - # we need to trim the front padding away if center - start = half_n_fft if center else 0 - end = -half_n_fft if length is None else start + length - - y = y[:, :, start:end] - window_envelop = window_envelop[:, :, start:end] - - # check NOLA non-zero overlap condition - window_envelop_lowest = window_envelop.abs().min() - assert window_envelop_lowest > 1e-11, "window overlap add min: %f" % ( - window_envelop_lowest - ) - - y = (y / window_envelop).squeeze(1) # size (channel, expected_signal_len) - - # unpack batch - y = y.view(shape[:-3] + y.shape[-1:]) - - if stft_matrix_dim == 3: # remove the channel dimension - y = y.squeeze(0) - - return y + warnings.warn( + 'istft has been moved to PyTorch and will be removed from torchaudio, ' + 'please use torch.istft instead.') + if pad_mode is not None: + warnings.warn( + 'The parameter `pad_mode` was ignored in isftft, and is thus being deprecated. ' + 'Please set `pad_mode` to None to suppress this warning.') + return torch.istft( + input=stft_matrix, n_fft=n_fft, hop_length=hop_length, win_length=win_length, window=window, + center=center, normalized=normalized, onesided=onesided, length=length) def spectrogram( @@ -241,7 +153,7 @@ def spectrogram( # pack batch shape = waveform.size() - waveform = waveform.view(-1, shape[-1]) + waveform = waveform.reshape(-1, shape[-1]) # default values are consistent with librosa.core.spectrum._spectrogram spec_f = torch.stft( @@ -249,7 +161,7 @@ def spectrogram( ) # unpack batch - spec_f = spec_f.view(shape[:-1] + spec_f.shape[-3:]) + spec_f = spec_f.reshape(shape[:-1] + spec_f.shape[-3:]) if normalized: spec_f /= window.pow(2.).sum().sqrt() @@ -310,11 +222,11 @@ def griffinlim( torch.Tensor: waveform of (..., time), where time equals the ``length`` parameter if given. """ assert momentum < 1, 'momentum=%s > 1 can be unstable' % momentum - assert momentum > 0, 'momentum=%s < 0' % momentum + assert momentum >= 0, 'momentum=%s < 0' % momentum # pack batch shape = specgram.size() - specgram = specgram.view([-1] + list(shape[-2:])) + specgram = specgram.reshape([-1] + list(shape[-2:])) specgram = specgram.pow(1 / power) @@ -348,7 +260,9 @@ def griffinlim( True, 'reflect', False, True) # Update our phase estimates - angles = rebuilt - tprev.mul_(momentum / (1 + momentum)) + angles = rebuilt + if momentum: + angles = angles - tprev.mul_(momentum / (1 + momentum)) angles = angles.div_(complex_norm(angles).add_(1e-16).unsqueeze(-1).expand_as(angles)) # Return the final phase estimates @@ -360,7 +274,7 @@ def griffinlim( length=length) # unpack batch - waveform = waveform.view(shape[:-2] + waveform.shape[-1:]) + waveform = waveform.reshape(shape[:-2] + waveform.shape[-1:]) return waveform @@ -421,7 +335,8 @@ def create_fb_matrix( f_min: float, f_max: float, n_mels: int, - sample_rate: int + sample_rate: int, + norm: Optional[str] = None ) -> Tensor: r"""Create a frequency bin conversion matrix. @@ -431,6 +346,8 @@ def create_fb_matrix( f_max (float): Maximum frequency (Hz) n_mels (int): Number of mel filterbanks sample_rate (int): Sample rate of the audio waveform + norm (Optional[str]): If 'slaney', divide the triangular mel weights by the width of the mel band + (area normalization). (Default: ``None``) Returns: Tensor: Triangular filter banks (fb matrix) of size (``n_freqs``, ``n_mels``) @@ -439,6 +356,10 @@ def create_fb_matrix( size (..., ``n_freqs``), the applied result would be ``A * create_fb_matrix(A.size(-1), ...)``. """ + + if norm is not None and norm != "slaney": + raise ValueError("norm must be one of None or 'slaney'") + # freq bins # Equivalent filterbank construction by Librosa all_freqs = torch.linspace(0, sample_rate // 2, n_freqs) @@ -458,6 +379,12 @@ def create_fb_matrix( down_slopes = (-1.0 * slopes[:, :-2]) / f_diff[:-1] # (n_freqs, n_mels) up_slopes = slopes[:, 2:] / f_diff[1:] # (n_freqs, n_mels) fb = torch.max(zero, torch.min(down_slopes, up_slopes)) + + if norm is not None and norm == "slaney": + # Slaney-style mel is scaled to be approx constant energy per channel + enorm = 2.0 / (f_pts[2:n_mels + 2] - f_pts[:n_mels]) + fb *= enorm.unsqueeze(0) + return fb @@ -623,7 +550,7 @@ def phase_vocoder( # pack batch shape = complex_specgrams.size() - complex_specgrams = complex_specgrams.view([-1] + list(shape[-3:])) + complex_specgrams = complex_specgrams.reshape([-1] + list(shape[-3:])) time_steps = torch.arange(0, complex_specgrams.size(-2), @@ -663,7 +590,7 @@ def phase_vocoder( complex_specgrams_stretch = torch.stack([real_stretch, imag_stretch], dim=-1) # unpack batch - complex_specgrams_stretch = complex_specgrams_stretch.view(shape[:-3] + complex_specgrams_stretch.shape[1:]) + complex_specgrams_stretch = complex_specgrams_stretch.reshape(shape[:-3] + complex_specgrams_stretch.shape[1:]) return complex_specgrams_stretch @@ -671,25 +598,27 @@ def phase_vocoder( def lfilter( waveform: Tensor, a_coeffs: Tensor, - b_coeffs: Tensor + b_coeffs: Tensor, + clamp: bool = True, ) -> Tensor: r"""Perform an IIR filter by evaluating difference equation. Args: - waveform (Tensor): audio waveform of dimension of `(..., time)`. Must be normalized to -1 to 1. - a_coeffs (Tensor): denominator coefficients of difference equation of dimension of `(n_order + 1)`. - Lower delays coefficients are first, e.g. `[a0, a1, a2, ...]`. + waveform (Tensor): audio waveform of dimension of ``(..., time)``. Must be normalized to -1 to 1. + a_coeffs (Tensor): denominator coefficients of difference equation of dimension of ``(n_order + 1)``. + Lower delays coefficients are first, e.g. ``[a0, a1, a2, ...]``. Must be same size as b_coeffs (pad with 0's as necessary). - b_coeffs (Tensor): numerator coefficients of difference equation of dimension of `(n_order + 1)`. - Lower delays coefficients are first, e.g. `[b0, b1, b2, ...]`. + b_coeffs (Tensor): numerator coefficients of difference equation of dimension of ``(n_order + 1)``. + Lower delays coefficients are first, e.g. ``[b0, b1, b2, ...]``. Must be same size as a_coeffs (pad with 0's as necessary). + clamp (bool, optional): If ``True``, clamp the output signal to be in the range [-1, 1] (Default: ``True``) Returns: - Tensor: Waveform with dimension of `(..., time)`. Output will be clipped to -1 to 1. + Tensor: Waveform with dimension of ``(..., time)``. """ # pack batch shape = waveform.size() - waveform = waveform.view(-1, shape[-1]) + waveform = waveform.reshape(-1, shape[-1]) assert (a_coeffs.size(0) == b_coeffs.size(0)) assert (len(waveform.size()) == 2) @@ -729,10 +658,13 @@ def lfilter( o0.addmv_(windowed_output_signal, a_coeffs_flipped, alpha=-1) padded_output_waveform[:, i_sample + n_order - 1] = o0 - output = torch.clamp(padded_output_waveform[:, (n_order - 1):], min=-1., max=1.) + output = padded_output_waveform[:, (n_order - 1):] + + if clamp: + output = torch.clamp(output, min=-1., max=1.) # unpack batch - output = output.view(shape[:-1] + output.shape[-1:]) + output = output.reshape(shape[:-1] + output.shape[-1:]) return output @@ -1296,6 +1228,135 @@ def overdrive( return output_waveform.clamp(min=-1, max=1).view(actual_shape) +def phaser( + waveform: Tensor, + sample_rate: int, + gain_in: float = 0.4, + gain_out: float = 0.74, + delay_ms: float = 3.0, + decay: float = 0.4, + mod_speed: float = 0.5, + sinusoidal: bool = True +) -> Tensor: + r"""Apply a phasing effect to the audio. Similar to SoX implementation. + + Args: + waveform (Tensor): audio waveform of dimension of `(..., time)` + sample_rate (int): sampling rate of the waveform, e.g. 44100 (Hz) + gain_in (float): desired input gain at the boost (or attenuation) in dB + Allowed range of values are 0 to 1 + gain_out (float): desired output gain at the boost (or attenuation) in dB + Allowed range of values are 0 to 1e9 + delay_ms (float): desired delay in milli seconds + Allowed range of values are 0 to 5.0 + decay (float): desired decay relative to gain-in + Allowed range of values are 0 to 0.99 + mod_speed (float): modulation speed in Hz + Allowed range of values are 0.1 to 2 + sinusoidal (bool): If ``True``, uses sinusoidal modulation (preferable for multiple instruments) + If ``False``, uses triangular modulation (gives single instruments a sharper phasing effect) + (Default: ``True``) + + Returns: + Tensor: Waveform of dimension of `(..., time)` + + References: + http://sox.sourceforge.net/sox.html + Scott Lehman, Effects Explained, http://harmony-central.com/Effects/effects-explained.html + """ + actual_shape = waveform.shape + device, dtype = waveform.device, waveform.dtype + + # convert to 2D (channels,time) + waveform = waveform.view(-1, actual_shape[-1]) + + delay_buf_len = int((delay_ms * .001 * sample_rate) + .5) + delay_buf = torch.zeros(waveform.shape[0], delay_buf_len, dtype=dtype, device=device) + + mod_buf_len = int(sample_rate / mod_speed + .5) + mod_buf = torch.zeros(mod_buf_len, dtype=dtype, device=device) + + if sinusoidal: + wave_type = 'SINE' + else: + wave_type = 'TRIANGLE' + + mod_buf = _generate_wave_table(wave_type=wave_type, + data_type='INT', + table_size=mod_buf_len, + min=1., + max=float(delay_buf_len), + phase=math.pi / 2) + + delay_pos = 0 + mod_pos = 0 + + output_waveform = torch.zeros_like(waveform, dtype=dtype, device=device) + + for i in range(waveform.shape[-1]): + idx = int((delay_pos + mod_buf[mod_pos]) % delay_buf_len) + temp = (waveform[:, i] * gain_in) + (delay_buf[:, idx] * decay) + mod_pos = (mod_pos + 1) % mod_buf_len + delay_pos = (delay_pos + 1) % delay_buf_len + delay_buf[:, delay_pos] = temp + output_waveform[:, i] = temp * gain_out + + return output_waveform.clamp(min=-1, max=1).view(actual_shape) + + +def _generate_wave_table( + wave_type: str, + data_type: str, + table_size: int, + min: float, + max: float, + phase: float +) -> Tensor: + r"""A helper fucntion for phaser. Generates a table with given parameters + + Args: + wave_type (str): SINE or TRIANGULAR + data_type (str): desired data_type ( `INT` or `FLOAT` ) + table_size (int): desired table size + min (float): desired min value + max (float): desired max value + phase (float): desired phase + + Returns: + Tensor: A 1D tensor with wave table values + """ + + phase_offset = int(phase / math.pi / 2 * table_size + 0.5) + + t = torch.arange(table_size).to(torch.int32) + + point = (t + phase_offset) % table_size + + d = torch.zeros_like(point).to(torch.float64) + + if wave_type == 'SINE': + d = (torch.sin(point.to(torch.float64) / table_size * 2 * math.pi) + 1) / 2 + elif wave_type == 'TRIANGLE': + d = point.to(torch.float64) * 2 / table_size + value = 4 * point / table_size + d[value == 0] = d[value == 0] + 0.5 + d[value == 1] = 1.5 - d[value == 1] + d[value == 2] = 1.5 - d[value == 2] + d[value == 3] = d[value == 3] - 1.5 + + d = d * (max - min) + min + + if data_type == 'INT': + mask = d < 0 + d[mask] = d[mask] - 0.5 + d[~mask] = d[~mask] + 0.5 + d = d.to(torch.int32) + elif data_type == 'FLOAT': + d = d.to(torch.float32) + + return d + + def mask_along_axis_iid( specgrams: Tensor, mask_param: int, @@ -1305,7 +1366,6 @@ def mask_along_axis_iid( r""" Apply a mask along ``axis``. Mask will be applied from indices ``[v_0, v_0 + v)``, where ``v`` is sampled from ``uniform(0, mask_param)``, and ``v_0`` from ``uniform(0, max_v - v)``. - All examples will have the same mask interval. Args: specgrams (Tensor): Real spectrograms (batch, channel, freq, time) @@ -1362,7 +1422,7 @@ def mask_along_axis( # pack batch shape = specgram.size() - specgram = specgram.view([-1] + list(shape[-2:])) + specgram = specgram.reshape([-1] + list(shape[-2:])) value = torch.rand(1) * mask_param min_value = torch.rand(1) * (specgram.size(axis) - value) @@ -1379,7 +1439,7 @@ def mask_along_axis( raise ValueError('Only Frequency and Time masking are supported') # unpack batch - specgram = specgram.view(shape[:-2] + specgram.shape[-2:]) + specgram = specgram.reshape(shape[:-2] + specgram.shape[-2:]) return specgram @@ -1416,7 +1476,7 @@ def compute_deltas( # pack batch shape = specgram.size() - specgram = specgram.view(1, -1, shape[-1]) + specgram = specgram.reshape(1, -1, shape[-1]) assert win_length >= 3 @@ -1432,7 +1492,7 @@ def compute_deltas( output = torch.nn.functional.conv1d(specgram, kernel, groups=specgram.shape[1]) / denom # unpack batch - output = output.view(shape) + output = output.reshape(shape) return output @@ -1466,10 +1526,11 @@ def _add_noise_shaping( error[n] = dithered[n] - original[n] noise_shaped_waveform[n] = dithered[n] + error[n-1] """ - waveform = waveform.view(-1, waveform.size()[-1]) + wf_shape = waveform.size() + waveform = waveform.reshape(-1, wf_shape[-1]) dithered_shape = dithered_waveform.size() - dithered_waveform = dithered_waveform.view(-1, dithered_shape[-1]) + dithered_waveform = dithered_waveform.reshape(-1, dithered_shape[-1]) error = dithered_waveform - waveform @@ -1480,7 +1541,7 @@ def _add_noise_shaping( error[index] = error_offset[:waveform.size()[1]] noise_shaped = dithered_waveform + error - return noise_shaped.view(dithered_shape[:-1] + noise_shaped.shape[-1:]) + return noise_shaped.reshape(dithered_shape[:-1] + noise_shaped.shape[-1:]) def _apply_probability_distribution( @@ -1513,7 +1574,7 @@ def _apply_probability_distribution( # pack batch shape = waveform.size() - waveform = waveform.view(-1, shape[-1]) + waveform = waveform.reshape(-1, shape[-1]) channel_size = waveform.size()[0] - 1 time_size = waveform.size()[-1] - 1 @@ -1554,7 +1615,7 @@ def _apply_probability_distribution( quantised_signal = quantised_signal_scaled / down_scaling # unpack batch - return quantised_signal.view(shape[:-1] + quantised_signal.shape[-1:]) + return quantised_signal.reshape(shape[:-1] + quantised_signal.shape[-1:]) def dither( @@ -1732,7 +1793,7 @@ def detect_pitch_frequency( """ # pack batch shape = list(waveform.size()) - waveform = waveform.view([-1] + shape[-1:]) + waveform = waveform.reshape([-1] + shape[-1:]) nccf = _compute_nccf(waveform, sample_rate, frame_time, freq_low) indices = _find_max_per_frame(nccf, sample_rate, freq_high) @@ -1743,7 +1804,7 @@ def detect_pitch_frequency( freq = sample_rate / (EPSILON + indices.to(torch.float)) # unpack batch - freq = freq.view(shape[:-1] + list(freq.shape[-1:])) + freq = freq.reshape(shape[:-1] + list(freq.shape[-1:])) return freq diff --git a/torchaudio/models/__init__.py b/torchaudio/models/__init__.py new file mode 100644 index 0000000000..1abdac6271 --- /dev/null +++ b/torchaudio/models/__init__.py @@ -0,0 +1 @@ +from .wav2letter import * diff --git a/torchaudio/models/wav2letter.py b/torchaudio/models/wav2letter.py new file mode 100644 index 0000000000..3466e42dd2 --- /dev/null +++ b/torchaudio/models/wav2letter.py @@ -0,0 +1,74 @@ +from typing import Optional + +from torch import Tensor +from torch import nn + +__all__ = ["Wav2Letter"] + + +class Wav2Letter(nn.Module): + r"""Wav2Letter model architecture from the `"Wav2Letter: an End-to-End ConvNet-based Speech Recognition System" + `_ paper. + + :math:`\text{padding} = \frac{\text{ceil}(\text{kernel} - \text{stride})}{2}` + + Args: + num_classes (int, optional): Number of classes to be classified. (Default: ``40``) + input_type (str, optional): Wav2Letter can use as input: ``waveform``, ``power_spectrum`` + or ``mfcc`` (Default: ``waveform``). + num_features (int, optional): Number of input features that the network will receive (Default: ``1``). + """ + + def __init__(self, num_classes: int = 40, + input_type: str = "waveform", + num_features: int = 1) -> None: + super(Wav2Letter, self).__init__() + + acoustic_num_features = 250 if input_type == "waveform" else num_features + acoustic_model = nn.Sequential( + nn.Conv1d(in_channels=acoustic_num_features, out_channels=250, kernel_size=48, stride=2, padding=23), + nn.ReLU(inplace=True), + nn.Conv1d(in_channels=250, out_channels=250, kernel_size=7, stride=1, padding=3), + nn.ReLU(inplace=True), + nn.Conv1d(in_channels=250, out_channels=250, kernel_size=7, stride=1, padding=3), + nn.ReLU(inplace=True), + nn.Conv1d(in_channels=250, out_channels=250, kernel_size=7, stride=1, padding=3), + nn.ReLU(inplace=True), + nn.Conv1d(in_channels=250, out_channels=250, kernel_size=7, stride=1, padding=3), + nn.ReLU(inplace=True), + nn.Conv1d(in_channels=250, out_channels=250, kernel_size=7, stride=1, padding=3), + nn.ReLU(inplace=True), + nn.Conv1d(in_channels=250, out_channels=250, kernel_size=7, stride=1, padding=3), + nn.ReLU(inplace=True), + nn.Conv1d(in_channels=250, out_channels=250, kernel_size=7, stride=1, padding=3), + nn.ReLU(inplace=True), + nn.Conv1d(in_channels=250, out_channels=2000, kernel_size=32, stride=1, padding=16), + nn.ReLU(inplace=True), + nn.Conv1d(in_channels=2000, out_channels=2000, kernel_size=1, stride=1, padding=0), + nn.ReLU(inplace=True), + nn.Conv1d(in_channels=2000, out_channels=num_classes, kernel_size=1, stride=1, padding=0), + nn.ReLU(inplace=True) + ) + + if input_type == "waveform": + waveform_model = nn.Sequential( + nn.Conv1d(in_channels=num_features, out_channels=250, kernel_size=250, stride=160, padding=45), + nn.ReLU(inplace=True) + ) + self.acoustic_model = nn.Sequential(waveform_model, acoustic_model) + + if input_type in ["power_spectrum", "mfcc"]: + self.acoustic_model = acoustic_model + + def forward(self, x: Tensor) -> Tensor: + r""" + Args: + x (Tensor): Tensor of dimension (batch_size, num_features, input_length). + + Returns: + Tensor: Predictor tensor of dimension (batch_size, number_of_classes, input_length). + """ + + x = self.acoustic_model(x) + x = nn.functional.log_softmax(x, dim=1) + return x diff --git a/torchaudio/sox_effects.py b/torchaudio/sox_effects.py index 472d291902..d1eb04e53f 100644 --- a/torchaudio/sox_effects.py +++ b/torchaudio/sox_effects.py @@ -16,8 +16,8 @@ def effect_names() -> List[str]: >>> EFFECT_NAMES = torchaudio.sox_effects.effect_names() """ - import _torch_sox - return _torch_sox.get_effect_names() + from . import _torchaudio + return _torchaudio.get_effect_names() @_audio_backend_guard("sox") @@ -29,8 +29,8 @@ def SoxEffect(): name of effect, and eopts (List[str]) which is a list of effect options. """ - import _torch_sox - return _torch_sox.SoxEffect() + from . import _torchaudio + return _torchaudio.SoxEffect() class SoxEffectsChain(object): @@ -150,15 +150,15 @@ def sox_build_flow_effects(self, # print("effect options:", [x.eopts for x in self.chain]) torchaudio.initialize_sox() - import _torch_sox - sr = _torch_sox.build_flow_effects(self.input_file, - out, - self.channels_first, - self.out_siginfo, - self.out_encinfo, - self.filetype, - self.chain, - self.MAX_EFFECT_OPTS) + from . import _torchaudio + sr = _torchaudio.build_flow_effects(self.input_file, + out, + self.channels_first, + self.out_siginfo, + self.out_encinfo, + self.filetype, + self.chain, + self.MAX_EFFECT_OPTS) torchaudio._audio_normalization(out, self.normalization) diff --git a/torchaudio/transforms.py b/torchaudio/transforms.py index 29da721869..f34f5c468e 100644 --- a/torchaudio/transforms.py +++ b/torchaudio/transforms.py @@ -247,7 +247,7 @@ def forward(self, specgram: Tensor) -> Tensor: # pack batch shape = specgram.size() - specgram = specgram.view(-1, shape[-2], shape[-1]) + specgram = specgram.reshape(-1, shape[-2], shape[-1]) if self.fb.numel() == 0: tmp_fb = F.create_fb_matrix(specgram.size(1), self.f_min, self.f_max, self.n_mels, self.sample_rate) @@ -260,7 +260,7 @@ def forward(self, specgram: Tensor) -> Tensor: mel_specgram = torch.matmul(specgram.transpose(1, 2), self.fb).transpose(1, 2) # unpack batch - mel_specgram = mel_specgram.view(shape[:-2] + mel_specgram.shape[-2:]) + mel_specgram = mel_specgram.reshape(shape[:-2] + mel_specgram.shape[-2:]) return mel_specgram @@ -395,6 +395,8 @@ def __init__(self, pad: int = 0, n_mels: int = 128, window_fn: Callable[..., Tensor] = torch.hann_window, + power: Optional[float] = 2., + normalized: bool = False, wkwargs: Optional[dict] = None) -> None: super(MelSpectrogram, self).__init__() self.sample_rate = sample_rate @@ -402,13 +404,15 @@ def __init__(self, self.win_length = win_length if win_length is not None else n_fft self.hop_length = hop_length if hop_length is not None else self.win_length // 2 self.pad = pad + self.power = power + self.normalized = normalized self.n_mels = n_mels # number of mel frequency bins self.f_max = f_max self.f_min = f_min self.spectrogram = Spectrogram(n_fft=self.n_fft, win_length=self.win_length, hop_length=self.hop_length, - pad=self.pad, window_fn=window_fn, power=2., - normalized=False, wkwargs=wkwargs) + pad=self.pad, window_fn=window_fn, power=self.power, + normalized=self.normalized, wkwargs=wkwargs) self.mel_scale = MelScale(self.n_mels, self.sample_rate, self.f_min, self.f_max, self.n_fft // 2 + 1) def forward(self, waveform: Tensor) -> Tensor: @@ -485,7 +489,7 @@ def forward(self, waveform: Tensor) -> Tensor: # pack batch shape = waveform.size() - waveform = waveform.view(-1, shape[-1]) + waveform = waveform.reshape(-1, shape[-1]) mel_specgram = self.MelSpectrogram(waveform) if self.log_mels: @@ -498,7 +502,7 @@ def forward(self, waveform: Tensor) -> Tensor: mfcc = torch.matmul(mel_specgram.transpose(1, 2), self.dct_mat).transpose(1, 2) # unpack batch - mfcc = mfcc.view(shape[:-1] + mfcc.shape[-2:]) + mfcc = mfcc.reshape(shape[:-1] + mfcc.shape[-2:]) return mfcc @@ -779,6 +783,7 @@ class _AxisMasking(torch.nn.Module): mask_param (int): Maximum possible length of the mask. axis (int): What dimension the mask is applied on. iid_masks (bool): Applies iid masks to each of the examples in the batch dimension. + This option is applicable only when the input tensor is 4D. """ __constants__ = ['mask_param', 'axis', 'iid_masks'] @@ -798,7 +803,6 @@ def forward(self, specgram: Tensor, mask_value: float = 0.) -> Tensor: Returns: Tensor: Masked spectrogram of dimensions (..., freq, time). """ - # if iid_masks flag marked and specgram has a batch dimension if self.iid_masks and specgram.dim() == 4: return F.mask_along_axis_iid(specgram, self.mask_param, mask_value, self.axis + 1) @@ -812,10 +816,10 @@ class FrequencyMasking(_AxisMasking): Args: freq_mask_param (int): maximum possible length of the mask. Indices uniformly sampled from [0, freq_mask_param). - iid_masks (bool, optional): whether to apply the same mask to all - the examples/channels in the batch. (Default: ``False``) + iid_masks (bool, optional): whether to apply different masks to each + example/channel in the batch. (Default: ``False``) + This option is applicable only when the input tensor is 4D. """ - def __init__(self, freq_mask_param: int, iid_masks: bool = False) -> None: super(FrequencyMasking, self).__init__(freq_mask_param, 1, iid_masks) @@ -826,10 +830,10 @@ class TimeMasking(_AxisMasking): Args: time_mask_param (int): maximum possible length of the mask. Indices uniformly sampled from [0, time_mask_param). - iid_masks (bool, optional): whether to apply the same mask to all - the examples/channels in the batch. (Default: ``False``) + iid_masks (bool, optional): whether to apply different masks to each + example/channel in the batch. (Default: ``False``) + This option is applicable only when the input tensor is 4D. """ - def __init__(self, time_mask_param: int, iid_masks: bool = False) -> None: super(TimeMasking, self).__init__(time_mask_param, 2, iid_masks) From ca14c17d107fc5aa8e13ccdcb181d8cf5eb23360 Mon Sep 17 00:00:00 2001 From: Moto Hira Date: Mon, 1 Jun 2020 09:23:36 -0700 Subject: [PATCH 06/73] Remove unnecessary config file from torchaudio Summary: Turned out .use_external_sox is not necessary for building torchaudio in fbcode. Reviewed By: vincentqb Differential Revision: D21792939 fbshipit-source-id: c0fb5173c6533e67114f50ddc8e9425bd129574f --- .use_external_sox | 0 1 file changed, 0 insertions(+), 0 deletions(-) delete mode 100644 .use_external_sox diff --git a/.use_external_sox b/.use_external_sox deleted file mode 100644 index e69de29bb2..0000000000 From 74bf3974d8385f45ba810d9fb04a17760f7218d4 Mon Sep 17 00:00:00 2001 From: Ji Chen Date: Fri, 5 Jun 2020 08:46:10 -0700 Subject: [PATCH 07/73] Import torchaudio 20200605 Summary: import torchaudio 0.5.0 in fbcode using import_audio.sh: Reviewed By: vincentqb Differential Revision: D21884426 fbshipit-source-id: b6f2cc308e597caef2dd767c315b167c09fb0d4c --- README.md | 108 +- .../setup_helpers/build_third_party.sh | 24 +- .../setup_helpers/build_third_party_helper.sh | 118 +- build_tools/setup_helpers/extension.py | 27 +- docs/source/datasets.rst | 8 + docs/source/functional.rst | 10 + packaging/build_wheel.sh | 2 +- packaging/torchaudio/build.sh | 2 +- test/assets/genres/noise/noise.0000.wav | Bin 0 -> 223532 bytes test/assets/kaldi_test_fbank_args.json | 88 ++ test/assets/kaldi_test_mfcc_args.json | 117 ++ test/kaldi_compatibility_impl.py | 46 +- test/test_batch_consistency.py | 6 + test/test_datasets.py | 5 + test/test_sox_compatibility.py | 118 ++ test/test_transforms.py | 3 + test/torchscript_consistency_impl.py | 32 + torchaudio/compliance/kaldi.py | 6 +- torchaudio/datasets/__init__.py | 2 + torchaudio/datasets/gtzan.py | 1054 +++++++++++++++++ torchaudio/functional.py | 193 +++ 21 files changed, 1867 insertions(+), 102 deletions(-) create mode 100644 test/assets/genres/noise/noise.0000.wav create mode 100644 test/assets/kaldi_test_fbank_args.json create mode 100644 test/assets/kaldi_test_mfcc_args.json create mode 100644 torchaudio/datasets/gtzan.py diff --git a/README.md b/README.md index fc3326075a..94f993ddaa 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,9 @@ torchaudio: an audio library for PyTorch ======================================== -[![Build Status](https://travis-ci.org/pytorch/audio.svg?branch=master)](https://travis-ci.org/pytorch/audio) +[![Build Status](https://circleci.com/gh/pytorch/audio.svg?style=svg)](https://app.circleci.com/pipelines/github/pytorch/audio) +[![Coverage](https://codecov.io/gh/pytorch/audio/branch/master/graph/badge.svg)](https://codecov.io/gh/pytorch/audio) +[![Documentation](https://img.shields.io/badge/dynamic/json.svg?label=docs&url=https%3A%2F%2Fpypi.org%2Fpypi%2Ftorchaudio%2Fjson&query=%24.info.version&colorB=brightgreen&prefix=v)](https://pytorch.org/audio/) The aim of torchaudio is to apply [PyTorch](https://github.com/pytorch/pytorch) to the audio domain. By supporting PyTorch, torchaudio follows the same philosophy @@ -26,30 +28,26 @@ to use and feel like a natural extension. Dependencies ------------ -* pytorch (nightly version needed for development) -* libsox v14.3.2 or above +* PyTorch (See below for the compatible versions) +* libsox v14.3.2 or above (only required when building from source) * [optional] vesis84/kaldi-io-for-python commit cb46cb1f44318a5d04d4941cf39084c5b021241e or above -Quick install on -OSX (Homebrew): -```bash -brew install sox -``` -Linux (Ubuntu): -```bash -sudo apt-get install sox libsox-dev libsox-fmt-all -``` -Anaconda -```bash -conda install -c conda-forge sox -``` +The following is the corresponding ``torchaudio`` versions and supported Python versions. + +| ``torch`` | ``torchaudio`` | ``python`` | +| ------------------------ | ------------------------ | ------------------------------- | +| ``master`` / ``nightly`` | ``master`` / ``nightly`` | ``>=3.6`` | +| ``1.5.0`` | ``0.5.0`` | ``>=3.5`` | +| ``1.4.0`` | ``0.4.0`` | ``==2.7``, ``>=3.5``, ``<=3.8`` | + Installation ------------ -### Binaries +### Binary Distibutions To install the latest version using anaconda, run: + ``` conda install -c pytorch torchaudio ``` @@ -64,26 +62,48 @@ pip install torchaudio -f https://download.pytorch.org/whl/torch_stable.html torch from PyPI. If you need a different torch configuration, preinstall torch before running this command.) -At the moment, there is no automated nightly build process, but we occasionally -build nightlies based on PyTorch nightlies by hand following the instructions in -[packaging](packaging). To install the latest nightly via pip, run: +### Nightly build + +Note that nightly build is build on PyTorch's nightly build. Therefore, you need to install the latest PyTorch when you use nightly build of torchaudio. + +**pip** ``` pip install numpy pip install --pre torchaudio -f https://download.pytorch.org/whl/nightly/torch_nightly.html ``` -To install the latest nightly via conda, run: +**conda** ``` conda install -y -c pytorch-nightly torchaudio ``` - ### From Source If your system configuration is not among the supported configurations -above, you can build from source. +above, you can build torchaudio from source. + +This will require libsox v14.3.2 or above. + +
Click here for the examples on how to install SoX + +OSX (Homebrew): +```bash +brew install sox +``` + +Linux (Ubuntu): +```bash +sudo apt-get install sox libsox-dev libsox-fmt-all +``` + +Anaconda +```bash +conda install -c conda-forge sox +``` + +
```bash # Linux @@ -93,6 +113,48 @@ python setup.py install MACOSX_DEPLOYMENT_TARGET=10.9 CC=clang CXX=clang++ python setup.py install ``` +Alternatively, the build process can build SoX (and codecs such as libmad, lame and flac) statically and torchaudio can link them, by setting environment variable `BUILD_SOX=1`. +The build process will fetch and build SoX, liblame, libmad, flac before building extension. + +```bash +# Linux +BUILD_SOX=1 python setup.py install + +# OSX +BUILD_SOX=1 MACOSX_DEPLOYMENT_TARGET=10.9 CC=clang CXX=clang++ python setup.py install +``` + +This is known to work on linux and unix distributions such as Ubuntu and CentOS 7 and macOS. +If you try this on a new system and found a solution to make it work, feel free to share it by opening and issue. + +#### Troubleshooting + +
checking build system type... ./config.guess: unable to guess system type + +Since the configuration file for codecs are old, they cannot correctly detect the new environments, such as Jetson Aarch. You need to replace the `config.guess` file in `./third_party/tmp/lame-3.99.5/config.guess` and/or `./third_party/tmp/libmad-0.15.1b/config.guess` with [the latest one](https://github.com/gcc-mirror/gcc/blob/master/config.guess). + +See also: [#658](https://github.com/pytorch/audio/issues/658) + +
+ +
Undefined reference to `tgetnum' when using `BUILD_SOX` + +If while building from within an anaconda environment you come across errors similar to the following: + +``` +../bin/ld: console.c:(.text+0xc1): undefined reference to `tgetnum' +``` + +Install `ncurses` from `conda-forge` before running `python setup.py install`: + +``` +# Install ncurses from conda-forge +conda install -c conda-forge ncurses +``` + +
+ + Quick Usage ----------- diff --git a/build_tools/setup_helpers/build_third_party.sh b/build_tools/setup_helpers/build_third_party.sh index c5e8f8115d..9577776cc9 100755 --- a/build_tools/setup_helpers/build_third_party.sh +++ b/build_tools/setup_helpers/build_third_party.sh @@ -1,5 +1,6 @@ #!/bin/bash -# Build third party libraries in `/third_party/build` or in `/third_party/build`. +# Build third party libraries (SoX, lame, libmad, and flac) +# Usage: ./build_thid_parth.sh [prefix] [download_only?=false] set -e @@ -10,6 +11,7 @@ prefix="${1:-}" if [ -z "${prefix}" ]; then prefix="${root_dir}" fi +download_only="${2:-false}" tp_dir="${prefix}/third_party" tmp_dir="${tp_dir}/tmp" @@ -20,17 +22,29 @@ mkdir -p "${tmp_dir}" "${build_dir}" . "${this_dir}/build_third_party_helper.sh" if ! found_lame "${build_dir}" ; then - build_lame "${tmp_dir}" "${build_dir}" + get_lame "${tmp_dir}" + if [ "${download_only}" = "false" ]; then + build_lame "${tmp_dir}" "${build_dir}" + fi fi if ! found_flac "${build_dir}" ; then - build_flac "${tmp_dir}" "${build_dir}" + get_flac "${tmp_dir}" + if [ "${download_only}" = "false" ]; then + build_flac "${tmp_dir}" "${build_dir}" + fi fi if ! found_mad "${build_dir}" ; then - build_mad "${tmp_dir}" "${build_dir}" + get_mad "${tmp_dir}" + if [ "${download_only}" = "false" ]; then + build_mad "${tmp_dir}" "${build_dir}" + fi fi if ! found_sox "${build_dir}" ; then - build_sox "${tmp_dir}" "${build_dir}" + get_sox "${tmp_dir}" + if [ "${download_only}" = "false" ]; then + build_sox "${tmp_dir}" "${build_dir}" + fi fi diff --git a/build_tools/setup_helpers/build_third_party_helper.sh b/build_tools/setup_helpers/build_third_party_helper.sh index a31fafe718..7cca812409 100644 --- a/build_tools/setup_helpers/build_third_party_helper.sh +++ b/build_tools/setup_helpers/build_third_party_helper.sh @@ -57,23 +57,34 @@ found_sox() { all_found "$1" 'include/sox.h' 'lib/libsox.a' } -build_lame() { +LAME="lame-3.99.5" +LAME_ARCHIVE="${LAME}.tar.gz" + +get_lame() { work_dir="$1" - install_dir="$2" - package="lame-3.99.5" - url="https://downloads.sourceforge.net/project/lame/lame/3.99/lame-3.99.5.tar.gz" + url="https://downloads.sourceforge.net/project/lame/lame/3.99/${LAME_ARCHIVE}" ( cd "${work_dir}" - if [ ! -d "${package}" ]; then - if [ ! -f "${package}.tar.gz" ]; then + if [ ! -d "${LAME}" ]; then + if [ ! -f "${LAME_ARCHIVE}" ]; then printf "Fetching liblame from %s\n" "${url}" - curl $CURL_OPTS -o "${package}.tar.gz" "${url}" + curl $CURL_OPTS -O "${url}" fi - tar xfp "${package}.tar.gz" fi + ) +} + +build_lame() { + work_dir="$1" + install_dir="$2" + ( + cd "${work_dir}" + if [ ! -d "${LAME}" ]; then + tar xfp "${LAME_ARCHIVE}" + fi + cd "${LAME}" # build statically printf "Building liblame\n" - cd "${package}" if [ ! -f Makefile ]; then ./configure ${CONFIG_OPTS} \ --disable-shared --enable-static --prefix="${install_dir}" CFLAGS=-fPIC CXXFLAGS=-fPIC \ @@ -84,23 +95,34 @@ build_lame() { ) } -build_flac() { +FLAC="flac-1.3.2" +FLAC_ARCHIVE="${FLAC}.tar.xz" + +get_flac() { work_dir="$1" - install_dir="$2" - package="flac-1.3.2" - url="https://downloads.sourceforge.net/project/flac/flac-src/flac-1.3.2.tar.xz" + url="https://downloads.sourceforge.net/project/flac/flac-src/${FLAC_ARCHIVE}" ( cd "${work_dir}" - if [ ! -d "${package}" ]; then - if [ ! -f "${package}.tar.xz" ]; then + if [ ! -d "${FLAC}" ]; then + if [ ! -f "${FLAC_ARCHIVE}" ]; then printf "Fetching flac from %s\n" "${url}" - curl $CURL_OPTS -o "${package}.tar.xz" "${url}" + curl $CURL_OPTS -O "${url}" fi - tar xfp "${package}.tar.xz" fi + ) +} + +build_flac() { + work_dir="$1" + install_dir="$2" + ( + cd "${work_dir}" + if [ ! -d "${FLAC}" ]; then + tar xfp "${FLAC_ARCHIVE}" + fi + cd "${FLAC}" # build statically printf "Building flac\n" - cd "${package}" if [ ! -f Makefile ]; then ./configure ${CONFIG_OPTS} \ --disable-shared --enable-static --prefix="${install_dir}" CFLAGS=-fPIC CXXFLAGS=-fPIC \ @@ -111,23 +133,34 @@ build_flac() { ) } -build_mad() { +LIBMAD="libmad-0.15.1b" +LIBMAD_ARCHIVE="${LIBMAD}.tar.gz" + +get_mad() { work_dir="$1" - install_dir="$2" - package="libmad-0.15.1b" - url="https://downloads.sourceforge.net/project/mad/libmad/0.15.1b/libmad-0.15.1b.tar.gz" + url="https://downloads.sourceforge.net/project/mad/libmad/0.15.1b/${LIBMAD_ARCHIVE}" ( cd "${work_dir}" - if [ ! -d "${package}" ]; then - if [ ! -f "${package}.tar.gz" ]; then + if [ ! -d "${LIBMAD}" ]; then + if [ ! -f "${LIBMAD_ARCHIVE}" ]; then printf "Fetching mad from %s\n" "${url}" - curl $CURL_OPTS -o "${package}.tar.gz" "${url}" + curl $CURL_OPTS -O "${url}" fi - tar xfp "${package}.tar.gz" fi + ) +} + +build_mad() { + work_dir="$1" + install_dir="$2" + ( + cd "${work_dir}" + if [ ! -d "${LIBMAD}" ]; then + tar xfp "${LIBMAD_ARCHIVE}" + fi + cd "${LIBMAD}" # build statically printf "Building mad\n" - cd "${package}" if [ ! -f Makefile ]; then # See https://stackoverflow.com/a/12864879/23845 sed -i.bak 's/-march=i486//' configure @@ -140,23 +173,34 @@ build_mad() { ) } -build_sox() { +SOX="sox-14.4.2" +SOX_ARCHIVE="${SOX}.tar.bz2" + +get_sox() { work_dir="$1" - install_dir="$2" - package="sox-14.4.2" - url="https://downloads.sourceforge.net/project/sox/sox/14.4.2/sox-14.4.2.tar.bz2" + url="https://downloads.sourceforge.net/project/sox/sox/14.4.2/${SOX_ARCHIVE}" ( cd "${work_dir}" - if [ ! -d "${package}" ]; then - if [ ! -f "${package}.tar.bz2" ]; then + if [ ! -d "${SOX}" ]; then + if [ ! -f "${SOX_ARCHIVE}" ]; then printf "Fetching SoX from %s\n" "${url}" - curl $CURL_OPTS -o "${package}.tar.bz2" "${url}" + curl $CURL_OPTS -O "${url}" fi - tar xfp "${package}.tar.bz2" fi + ) +} + +build_sox() { + work_dir="$1" + install_dir="$2" + ( + cd "${work_dir}" + if [ ! -d "${SOX}" ]; then + tar xfp "${SOX_ARCHIVE}" + fi + cd "${SOX}" # build statically - printf "Building sox\n" - cd "${package}" + printf "Building SoX\n" if [ ! -f Makefile ]; then # --without-png makes OS X build less hazardous; somehow the build # finds png and enables it. We don't want it; we'd need to package diff --git a/build_tools/setup_helpers/extension.py b/build_tools/setup_helpers/extension.py index 65e48dfc10..dcf61ab259 100644 --- a/build_tools/setup_helpers/extension.py +++ b/build_tools/setup_helpers/extension.py @@ -1,3 +1,4 @@ +import os import platform import subprocess from pathlib import Path @@ -18,9 +19,21 @@ _TP_BASE_DIR = _ROOT_DIR / 'third_party' _TP_INSTALL_DIR = _TP_BASE_DIR / 'build' -# Temporary fix for building in fbcode -# at the moment, we have to use external sox in fbcode -_BUILD_DEPS = not (_ROOT_DIR / '.use_external_sox').exists() + +def _get_build_sox(): + val = os.environ.get('BUILD_SOX', '0') + trues = ['1', 'true', 'TRUE', 'on', 'ON', 'yes', 'YES'] + falses = ['0', 'false', 'FALSE', 'off', 'OFF', 'no', 'NO'] + if val in trues: + return True + if val not in falses: + print( + f'WARNING: Unexpected environment variable value `BUILD_SOX={val}`. ' + f'Expected one of {trues + falses}') + return False + + +_BUILD_SOX = _get_build_sox() def _get_eca(debug): @@ -52,14 +65,14 @@ def _get_include_dirs(): dirs = [ str(_ROOT_DIR), ] - if _BUILD_DEPS: + if _BUILD_SOX: dirs.append(str(_TP_INSTALL_DIR / 'include')) return dirs def _get_extra_objects(): objs = [] - if _BUILD_DEPS: + if _BUILD_SOX: # NOTE: The order of the library listed bellow matters. # # (the most important thing is that dependencies come after a library @@ -71,7 +84,7 @@ def _get_extra_objects(): def _get_libraries(): - return [] if _BUILD_DEPS else ['sox'] + return [] if _BUILD_SOX else ['sox'] def _build_codecs(): @@ -106,6 +119,6 @@ def get_ext_modules(debug=False): class BuildExtension(TorchBuildExtension): def build_extension(self, ext): - if ext.name == _EXT_NAME and _BUILD_DEPS: + if ext.name == _EXT_NAME and _BUILD_SOX: _configure_third_party() super().build_extension(ext) diff --git a/docs/source/datasets.rst b/docs/source/datasets.rst index 27d4b20a34..8ba05dc670 100644 --- a/docs/source/datasets.rst +++ b/docs/source/datasets.rst @@ -33,6 +33,14 @@ COMMONVOICE :special-members: +GTZAN +~~~~~ + +.. autoclass:: GTZAN + :members: __getitem__ + :special-members: + + LIBRISPEECH ~~~~~~~~~~~ diff --git a/docs/source/functional.rst b/docs/source/functional.rst index 5f68666539..12ee165060 100644 --- a/docs/source/functional.rst +++ b/docs/source/functional.rst @@ -113,6 +113,11 @@ Functions to perform common audio operations. .. autofunction:: treble_biquad +:hidden:`bass_biquad` +~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +.. autofunction:: bass_biquad + :hidden:`deemph_biquad` ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ @@ -143,6 +148,11 @@ Functions to perform common audio operations. .. autofunction:: phaser +:hidden:`flanger` +~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +.. autofunction:: flanger + :hidden:`mask_along_axis` ~~~~~~~~~~~~~~~~~~~~~~~~~ diff --git a/packaging/build_wheel.sh b/packaging/build_wheel.sh index 73cec89ff5..d08196cb20 100755 --- a/packaging/build_wheel.sh +++ b/packaging/build_wheel.sh @@ -15,5 +15,5 @@ if [[ "$OSTYPE" == "msys" ]]; then python_tag="$(echo "cp$PYTHON_VERSION" | tr -d '.')" python setup.py bdist_wheel --plat-name win_amd64 --python-tag $python_tag else - python setup.py bdist_wheel + BUILD_SOX=1 python setup.py bdist_wheel fi diff --git a/packaging/torchaudio/build.sh b/packaging/torchaudio/build.sh index e2b53ddcf4..99c17b6913 100644 --- a/packaging/torchaudio/build.sh +++ b/packaging/torchaudio/build.sh @@ -1,4 +1,4 @@ #!/usr/bin/env bash set -ex -python setup.py install --single-version-externally-managed --record=record.txt +BUILD_SOX=1 python setup.py install --single-version-externally-managed --record=record.txt diff --git a/test/assets/genres/noise/noise.0000.wav b/test/assets/genres/noise/noise.0000.wav new file mode 100644 index 0000000000000000000000000000000000000000..cf1cbcde22e41b56c4a02a8a5b13dbedd5dc3b3a GIT binary patch literal 223532 zcmZsC1y~zh*KJ%#NQe?3XmI!9Zl$GAFLmnf?OS(msk^&ST3Vn`N};&BJ3*5`LPFf< zmXF)}e*e99c+NaCbN1e6t+m$y!o$p)85L!@846k)x+rqP_I+l0AP@-r=gVRd2o#YD z0zp7}pmj<6l0biA{@()tARz6Z0RYo;;6HazkQ#u2G{9694FCrz{|xn?r&Dp-KTm=G z49K53$e*O?JMjOxnvR)%{`ai?Q&070X#cD-l|Oy{TWKnHYSpP($bZ)U|HVy5Oykr1 ziJn@0dhP$a+Ek?Gf3NsIF;2x#tu=*aiqrqZKb<#)<6mTdSD0e^7va?W6tjPsPHQ;z zdOaZe=+VQ`u9;-+ItL`BN39 zl$+uN{&V#&>%SeCMmt@3n#;d@{^I(}bz0-U-T2%4|JLL$^Jxat9RH&GZ(XMKm{x0= z`(KU!?cTqBnCAG`i_<8koT&Z75BA4}i2tzr@AzrXQ@xyW*L2Ol>il)<^!*g7X-`b? znRfU8+rz2af4Tj=n)b}Jj?>rEwWhr@9X+kww64>LrB&i|J^VhJI!%AV%kUltt0S%6rIBQZ}q8tFzx;+Zz}%x zE}yP7t;W>#RJQ8RnDY1(j;Y-_9RmWP{$wHl+^hbu75|x6{uwxs1VI0ZQvErDL2wZM zPc#f9{gVj=2>>0C4u}hI{^&CTsDL0)J>d8UQxV_*dIQLSZh!)s4ax_CL8hP~!16ye zSAuAu2>=V?0lh#!KnI-zMSzxp?tnS~9Ox790*C+~1>FH`fSo`ys77lEat1F0#2|a% zwst>Y1>Dr)LAl^vS})K}&@I3Tyc2v8j0D{VL4fXtO5$5BvF`2inu%4xnCZ3I{`ywFR0_>M&IS*bXYtbc1Oi zN8k&P2`bkf)~H|uz;yuiXT=A9473ooRhz8kYtvLP?HkZlup6i!hSY$8V$d>eI_Q&9 z3n7Dy)fn(uAXsw?JOSCRoeN>A@tUtdDkqYlXcw8nH#Y6>6uk2LDupfqjZqvO&dp**EA)?P^pNXq`3*whL%MQsi899OQ|n zS!~D5M{_g^<(r3$$gm=RHf#rmO?S;6nUcB61+rw1iu_}UXzMlBp#K_g*Pa} zKu1tDYIA5A>YVg4Y)E(xwuK}VcPU$h1f^JBC!dSJ<5xqm@CV8QnHe@f4aUe(!LU*A z2kkXnGxr1{5*w=-K>BG!ip!dN7$VFWx>uzK9T9q>(t$WN8sV>{gL32t!1-`f>U~)A zWSpv5&4+bEzNqlyFPdL2!Taqsp%7|2-myUTUl^}BmU{2*|DJdpROY)ySFBvO!cqp0 zIPDeo_O$h9xMQ$KMA}5`_;Pu9dua9(qw|e`- zL%kAoM7w)@T+&W927fR^j2rV9RaU6B$eoeVNb{kSHS6$Q*~cf^%(KSA5Ha;3RY%8O z>zCEt3KvuA`aMDW#{6aH#cfpDII({pZcJ-r(o%JxZjxcCXw^A4AxFfr!p2bKWwIvv zJD`b)1BTmPdWw3tHU~;RC zcOQx`voDV59x4It?U6I>4 z&cgUggSFCrmgAsYG~c#oV&AM8R@9P5HF`}6s97%CdPcBog1=iF)V9dGhg6*vjoS+z zHgt4qvuTb01}~v^reKTE>Wd+KzaE=-oYCk^>b{wPHrZY@Li<^FLfnQd?|p`JCUAp{yW;Y_ z{bsf-MLpK_0)5rqmJSKNNRN$P0asABjkpAKyS4jPpdi>2+oZw-@llPR{k4$|#?7Wn z1XZEQ72Q^0mC3>+23EQrVPJNcYA zwv#^{OMuP~{LIRn;pMET-mqd1-Q4?;hShQDvxa5BB6>$4&-Wycn?M)EN9wHfNOX9? zxXIHUKhHUW&(?F∾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%0DPcrvB_V?H(?12bv9mZM3bjb-c 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∈{AO{|fw{rXu z+KE;rj*Q4AU(!d9Z5xr=__TDW?<=e|X=632!)8Y}taNb((a@PtDgKsKmp!?TpdB_) zJYns*hp*atL{v5(xqPH74nG~9Txg^rbVEIU} zP0-(K-4_pVQs`nTNo+tFg4+|>hl5{o{9>E|4+|ZvNBU9`{y{d@(JxR-rvu(*jlMU#c7RwQ-m-4n? z!t!(rKvcyrjP=;A8mEW^*yI?%*&3@<1_zh`xwfRY9hY~;cT(jl?v&bjtx6?SjldN|WipCI3Gw-(92xfz_Rjbt=|v-{?H`9P7D@@L7vd}SboJ_HlC@q9|GRlK!BGq&d}R-VT!3&A1N4W+s=Umjp7lK~4c%Nn>y}UBd{yl z(sRo5EPoZIb%5KI`|V8HLh8|~@!S=r4Er50qU)-mYto;(-9zqLRM_(o2;xus@s52y zw^M&xs9amUL5mT-mqmdglVeKVs4xt=n5Yl2i#duH;WnF}4sWfm7Oin8w|heF_{~ST zbq_0j>8KV1@LBLc?4s!8{JZW6NT>0hj~@+&s?-5a6!MW<}x5CUKp z=fYD)r~w=3?b02nXPs2g52YEt4>lUyuh>cGHQ$_Y!?pyuLpW+&Jo_S_nja#W^nSZ<LwjkdSx(V*Z1zF&j?O)jiBHq~!vWMmmiFwXNA@yM`i3qt$eI*bN2 zI-luVjh2wMQu+obP4jwcc-aYULtld)5fhtia#EP#`+CV=`pRYocmD%uV zNd#=3U(?3qkfo~S6TjRSgeDM=#;Mr*zDYI{eBQUGj62n=?XCgBK_vQ+a2EHpa51HA zwq@86%}M@0&zP1EVXFX`k>(gvGv--yhBiIe13>&Fv| z^X3?Jq6^GR)I8B04c<9u&mxHVbox!Nd&d0DysuA}8z$yk77H;p&ou!f<5c%Wyd&sNwqVfMJvm@0qjo$mZM=b`Sa=7MoU)H32Gmwm=I z*_Y+VdT8UJq7hbbkWFL8@->y9>T11n&IuAy?jr23N(Ah&p^I|Z!s=k|qXlmnTGusD zJI)u>J$vAKLGF?Uoh%S{vPUD`h`DTu#U7@g4-NNjwb%r>lK&d?CUPtBoZDz`wd;mq z6u%BTh&xy7Gq4C3^qvSw{TbVWci@&J!Fg7cKH47S?;61U6EnVT+|KFk%Wn% z99@Xxv$Ds?EQc_M1gs{SS#&qV+bEd`!Yt5t5#5yYDQExinF~E#VCov*CO4@w`L5Sj zhcA+6gwv9`1siCOhwl4xEH2=R1lX3p4I-J$q8(OCe;sl#DL*0mg&nk1cXE_!`~I^? z>}eHZ??34Pf)38<_~F)2?+GfCPY14a4l-}*HSKonkjCqe-{fCWvTPBhZVVS1(jHW1 zpWWO%#D zo^*Wk?RF{}xS)-8bLRwiG0;oAUSHo~7pZ+DC%8ZAS%FXvx(@W3pYU`L!?5?whiM0t z@yb&Be)J#dor%GTKY@7nOzo$;KRVN$TE!60FBSrU`5=z)m)2#D7e}~PL!3S`Yya}^ z@G=}e+x{VR;F7e%bV77+L>f{CU(P(|@=2H3euWBean-rm_1Z^IZsi!52c*M)xU&yp_AQ`>`ZHrL3Os zgR6YgKegpKVy(GH|D<_^yS8~RI}5XdvR&Mosj@z6K9}&$c`@5{sVG=@@HJlo6a2P(IaBv7-|La)W-6 zPpjPWA`)FRy(>pk9 zg?5A=PENvlc`P!;{77g0UXzztP=6pB82ov811Jid*(UI+g&)*!wra3kDd-!f+ngZ& zNI1Z&^s`qJ{%~dfFECDHykJY`6tM%+=-<_42j!*OoQg_@o&;HXsK6(^k4pO*)60aI z6P$9Ez}6|xZ{m8#n>hI7nWp6u13#7Vxy{LT(b!@47tu#-e+{*9S7J56Pi&S8w>Fzo zhGVjYu7=HxTPN4oZnkWX7-5ZBJ(0N&b^tz_PwOGMDgNS~v~K4pjm=<3BJQ!>slMY8 z1|GIqMPpj*6Nh)6q1wq=&1v0A%SypzV+l&dw?)5i>FIt>MUV?qlN^5W-VY5k>%8{s zZM>&?#~mKpRWq#_GxO(q`+x+Z#dT|Iw@O%j*(}!?JT{3>9V^EjL0=eN;b>;KKD6sbg7o`{O~sX8G!xaE~qA^16(N!%u8jTo2{X zSmac1-39P@A0~4Tvi;EO0G1}+>NFu;Tyoai;tw=M(YmE4nWkZ?bMI6G z_3PIPX^*VRS0wX`y{vHUH#(H|yn^MTGh%nEy+$)fkeCIEu7=~&4q!XEksCfmsm+in z2-RXxXAEJJ9Nc=nCluObv>*i9IkxYdIxUZbdDu8=m;e1+WzP~|H%&_FnR%{51AgaO zyE+jdHWWm>(N652(V`aTF?hn$Yf1I_DKke}n;QZOe$KYq=FBN(h;zv*ANEMjzi$@h z>Yz@-*lAts-?bw|pf3;ZY&}!ai|#kQ$*eGs0^nDm3enZLWjJ|D2Bil6!r`R3)AM)q zy|SsJVmh5cMmLdTMpR?iib@0Rt$lMI>;N998QAIf#5Rk5}SR{mE2lFCE9!bM&!-X z*om~Jhk2b!cZ(mgV^IXc2fm>jD&ke~azSNNE{W8Qyrq4S<++6W;CTOArgZFg=4JJl zx+^G{KVNOlTf$aw=9CvU zS6Dh1$c*|uSAgPlH*7)(?7K>wli=O6hUWN4I5*^Q^2dUn7C@OV<_W|SWttiP_*dL2 z-e6t@`~dsX_{Oih1^2WmJ2u8%<0$YBPK%dh+B!Fpr?hn!<>dwx)R`(AH7tfNc;KE&C9J!^Sz^nmwcIIu$uyOxuIe`>Y{2z7rv{T^QF zw3oBTuq2p5Zy0thzB2`E1;TPjAADAr3DCK??k120&D#fA;y8Q$2w_go=>ROcK_pS% z$M}$!3ta6V{77!Ngq@;Ld+)(@8tDL>o!m9*Ue)o=CEKdiR5P&wlt8;~)uR~>84m@U zzJgA7=E~KR<$$$By@ihBoebb*mrf92m0OV4y+dKPjCM2{anA@w1t61FesPVaxr0x- z-qYNX_~5R{zWJ{$;q~b(FHZQ4_@PJU9;WWL8uVVaG-=*5%RMIHpLH%2#1`IuANv43 ze-~u0(~Rfkg6q@VC%RM{ofFe;Lxb{-Z7EaiM}gx>2_cKal=WR^?n9OOWka&6RfaF4 zW>6*_KS<-A)jBIfeRora(97H&m<@b=uerd1*h!#fZBrH-SOb;rU3V-6v~Zob-w#e4 z?j+&PtsgF*2@8CLogl0^X{Yt|S>WPZwd|42l=DCbWmd^*#ny=RFk&Nv;m<-c)D{P% z^Ry&8ga6MV52tLM-~toyiZ{)UF)_RQ)w}V)n40w>YEV zj+0i0=KnylCf)5{wQpn(CDoKeMeh}Bff4nAMF$n(euMH%F`uYtmtdU&H+vivtr$P! z4-4HZ2J+W_{yXpm%+~jlsa>rmtpm5_P>$NhhFD?|i7aE*w8!LXLR;;fSU%)|nr^AV z)4@F74S_xBc6k=V?2)-doGP)$oF2p(TqUP@la8|1Ltf6(3#bm)Wexqt+kmrC3mRy& zCzS`#LjRXyh5dK`m+Jd1FA@O~pYcUKTiF!W(Kd#zGa{keF6f*x*Le@-@Gxn%r*zPJ zmFYWjWu1tpAH6AS5Wk3AhFK<8nLh`Q_w`h&$38)SAIH;5S;WcW7Xx$u|D(#_u>cdY_#-Zxv*| zep}L#u!l&RcYQ_wSQ_QKy@@%)>l8Stt$*PrGGHPKHyYVIkFEcVIc1k!F<$&#a((_m zR43~g=#uk`(W7SN&@#}qdDkh~tX8IPOqQeKZ+4JI>^YYJ+Q zChEp&Eo5?k@1&5YcdCiwelp2o@ElYRQM;D&ugou9~wA8 z@0wXF18b8>=hRR??`IC4_w0O`nFBk=N+ws8)-E*zp?1y~IB)lKoLPzT{GLDT-p*ge zOOI?;dplsMc>lsR)=pXeLoHX-mclsgQIyEyVQ5z6TR@^btYS3<>gDO_gOJLqY&Yp= zaL?s=GTw2n+}bi#Vw=$?o!T^dQrQZ^QeSe{2$wGGvU)u+B&-5$vw5Nrx%{<%_t!&+ zDS=_q%`AZ*BRxBXGwA8&vB{b*FT%-#=1;~J$U|WS(;pNBT$2~tcpcCS|I2)U&y!>l zE&*3#vv^+pgYnk{c3pcY!%j6#34{4!Kf8y+zsOl(ouRvE4O8o=y;A_Wv@229Z=T<{ z902TuhzWpQB}>TL%y<6DVI1Wz1kA);FS>`jI2qaiCVIFA5Ji4XdX7l#9p8srX#UVqlr8M3=(@!QuRsHElaBRm>)15Cm+dBA29U0 zLItVJ8_35pd&Bywi>emOc_4jFVH$Hlc0D^|YW$hh3`5kFzQ9;h*wC zT&@(i0Ol?gu(hnE&e0BYt$)tC4;B;NaeuiifmB%OJpj!R)L+@F(Ja+G=m@VU;Ery) zBW`?~`Bki?@`syU{-TIX&B}hA$hYxe5CpruuGDp9pB1&leU5a&5 z+CTSFU=(GzdYj~Xh$8=b%Ue`QZB@W!+X&mKG1in*ZB!9#>M=x6p3x!1zlaSn7IgLv z%~$E!lBw|Vf{CRY2eq-%Q2a^$PM*&z~HNIm!R7^gI)3&mReJwppa5mc)sDtL<$z#hz2Gim_DXPeeHP zN?uuJ>c6VCC!eV+tCj$T@+bYcbuSo4AZ=W<)FN&O%CtErZkq>~SPl2qAd-8jyq19K zFOdU*cT`(P#{TOu_+XQ)N*!j^MkDJ&E9BAm^?LuXUHxZP3Ei*^u%@Z_k?^t8O@N9) zh1vdW;yb#ZK_TCtp^|s>Z~o$c(CVE!lFSv z_rLK9-a6!k1y3elvX+f~h^F9Ac+W~Ge00l$ukC7VPdy5dS+9~Lmlr3xTf{f?y7?!+ zF6j=q7yf4C#I#}OhiH?d8N?V+3)uFJNOqW77BH(S%%YvB9{Ow3p;;F||GS=cT@V3c z+WP1KUIU;;>pDXnbDlHg&U03lEt+o$-f^3LcwL`oG!}xi#NriEa~qTY_hBW3DD84ilI=MrhqwXj1WZ z#sk-dUfYZfum$MjL(6-yQ*hmn%D-OI8k4a$qPAPezD`Og_|8w~9;?--L4*6^J$a!h z1<_BRKF7z6(P7W}?vTfj>%uxNDo6239fdepYp*=tHGgWHqU8Xr=i=YaizA=soZ_>% zd!duu3W>i|K3dD#O`voh4!>dr?O4t>lw^+Y8-5;pQbUJqvV4X3DQyk?oz#W#gVn(H zIR)e~%&#D)eC-fq_`E?c#qdHKBiqFScu&DGv)7N79iZikY4|IarzF0*wUg?weIA=# zW{j>Mo;x%stcGvW1UMVLI$c#l-`+0xV9lCQLh&}QF4`Nj9Y#;I?zR6D=X?`FrUu5}N40p+`O??{=Gb2(#Zg0;E%{GkEg{$58l0DhtFyj^pD zR_Oy4dSqT>vI3Y&He7Z2<=i$EF*sa~K;?`l$F(^o_nq#WFBOuPP*2zcy}o-M_lejN z;4q2!CD$wYzoFN ze8C#Jm+_lyp?3GAJAU&0zF!r2wah%PwWH^z50pClrRkNT3-SwXQ0;)r4ZcD|wZ6>E z?wA$b%-TUX58W_qL!RgvLqevl*!M_*Vq5VC@k^T^yBzaY!y)x$;8|^W(Rbt8j0uuX!KL0U=?vrApniEinlwQw1` zY&+2*iK-g-C)$~`qq&-L#x04mJ51B(mf91Wld5qIv+4}ihaRCl?YL>mb}2V)6A)ZK zTQ2k~NjY4mRU|Js;PQ(HA4+CU5Q6M*5g~5-(V-EMa|@>KmdRXt#VNseLK5ZOWli#g z()}2X_ZxRVxBc9sU2(5$s9yXezh6os!zy41ZjoZ7{KBD7uv&#*gXjC$h96-XI4qXE z+~%wFUGk&KB8m6gXwDv1J0V5W&#yL{a(qtD>)enEU;xB>K=R-@7DvnWHCtJ5^XZj0 z#H%Ye2rK5JFsi|u!=nP%W!HXZd23l4#m6~W0HzT?w2|OfX_i5hU$gt+|P%%QSJLry~8a;&=b?5zY{D0FJF4Y zlrhpqTfpbIcVNR)+nWDtU1sjA*P^!r_SHDF?gwr0m{C9^d}j|&6zLOderp~3`h89@ zcGV{q=wUr(d-^zKQs_bFXZj74jsCDj2dd|YwXQ*Ol0|8IVo#QLkbOJ*b1RXzLBAin z#gJY2Pz5Dj=(ciM%@06blYdvWr7hNE>r}*xuJsO8!N)$Y7N3Z|XCp{F?O%r0dzgqn zbjgW9Ur$t~m7d`t#>z}6cQE*3LiflG;UmGFJ}=7Jh5um*af1S^&AG_+LJ4%hjH^yk zM~*$|yavdxvvL=<*i0eDhshSx|JsLZg446v_|J!(dzA$6VR}9IgRr$B!sgu&zGsJ% zYCM3`VgwJGceGMl6Te1#!hAli8y30M)cKmnaB5V1dWpzxR(bCc%PJc`z~QFI;+yY+ z+ap(wDEP2s?wfv#{1kL3e$nVv*LSLgwiMIjak}FbR3!YMW7T6<>?54r$6>m<aeM^7C+71vgMD(7XR0so8<4lD2ecZ%&JtO zbAiUOPm?qL0GswR-SZ><7Yme*k-aOXq8Ao_Y_EC3A84BULN*_7i@KpZ7`l!O;dX;^ z!BHsxclEMeZoz#s0j`GMu%$gi^p%eHP`cjkzCC~|g=;J_aO(`RvE53w+xoo2!d7bh zyK@-yNL#f@0vs5V;(yi~$jB7!I%A%xpKKZZ8pQ_#5;~o;wxCr-yD7KE+J2XR&#`a_JMN!9|YEcRk>WQ~I*-^*yzSF{RWO=0f!8-f0A62tM2#JHgBbyEwE{)A}j>paj za&%lR(+F(wdB&#>o5TIva5hi;J3Qu~%Gw&Ghq0=b0Q{%PV_d*6vAY*PW@4J`oC*By1FCKZYd3>Sg+hG_-DJmIb3r^IfkzjZQ}=$IwcQN=3ursTy=_& zayT2@M}#zXMpG2$A!(|$Dugy~2QUy`VO(GsZ(?E17B-jPH%0~7I~`v9R^7qp439V2 z2sSaJ5>J4TvF8Gt`Wvm;aRZI}r!>20olcznzvxs;#F9QL5!VGrJ(;@FM5XD#ISx2X zxdvudE~3mmj_V6)fd2Gy)_|o(Nx8&?w_scWY??N($^StkQX3Mw+G!atN_e|*#{`cX zCObJL>t#Jzks}X&^tI;d%88lE57|XwKdags4kV&f2Zt|5BT_KVxjEkpW1RXUE7NBR zxs0F4hh#9-}0(N zR}CVov(lFnS0OV0Q;gkEj^}KBVNe1nB=&7@1^NNx*I$3fy>9ImF9S}z2yu5L{tHhi<4|J0jOI1&7_V`6!ZabQ7IV#Rd;=4@jCm2~>yqrE{)%Z!t_d0Nf)a74^6T&=|JoVVnJ^?04$K zZnZXk)h+t4#GZw78P`F>&O+yQ4akR3e_O9vZ44t2h1Od%sf210bFkpW@174hN89g% zGdlj6yd6HH)U|Z)?Px%^FH(&3rW)i^?*8iR?tkV}y#cz_jy0M-_Bqj8dyJMZJ1q+N08^@Phm3GcB4^(Y=B(;M5?xY#<^6(yPmhQ3&Lk}ChVogH}){L+pHG% zEs{c*e+S&NQ#7CK<9Djcc_)aR7I)KlO_=Y0kgy)oN_{ZPad^AiLevzEWHpf26%y6| z``W(16VWj9Qqe=Naji+k*Zg+bX}1KTGB1Yc*Y1ZhO#^*=bjJfCyU^W67!Im7w}FE?u}naaYJ z#ms{peIr3iUBP`si*SpqpZLjs4Q-F?(CGh2Km5`)*F#^smxLuWWz}v+{jW(PYXKgW zpPDOlnUzO0N?_LZ-TK%DM=QV3)6K3@FU~gL@v>6u=aKq|&;4#9 z8TAsJ0Y9gW z!i9hpS)C5?V{Wi*N|xyX&@=lPM|&Q;7Szjp;gK9S zhCZ#|5|YMw+Fm<*Kl(=rGbj+|rA((`omNGqb#$pK$@4sGI!`P8Ru&;j1R){Es@Jhm zslU9}dj}~&x=zyv(VE{LUQT6}d8@(XjDh**IM9=;`F+R?^-_DiNfBXBJY_CcGM}5{L)+*e}D)y%&s0Z}AxQnt|ehS7< zUHG_z4;=@CDUl@lHq^F)zY>agHR7N}0Of;bHROfT&xtfhEcV%Rj0YJEbR$o|8)p%l z09)CPHF1)iAi}tdO&#~A^S0pKu|DF&uos%8%}-oWS{{{ei~%hn9kf%An;`fpowddA zHtq%pGU+Iogz%!^t*-lDVMQ>);6MGoIinG;jY~0eweg@mO<}Sl*@p@TCbqyUL~DUR zl2-rSvR0_!J1tdSYuKRnd*wwW3f~R0rha*mrZbV!4pAcAD_OFITr_;Fe(~Kj)k@7< zp%L2QbZ;hpnGLnEUCM2lyv&bndc5?1xHqA$T_;BRqHm8niFE#!!gs%(Y5nStn`puR z^%)~7LZw}2SPRM56+3}aVLomiIft?!rvJ0RSB^T=6FI&rdu8ZaM?jB(b%G@~|MPY? ze+LM|5eq##VPT(VMd7X?UjuaiMxDoer>FAyzZ8|ezc=)V2}QQwr5YAfWE34G7(&>ie9;q8vAGko7G;l+{K;evtP zj;Z7Ks!5fv+Mo7I^!pJ>Xd47H!p&^6s zpT+MYT=rRoesijZYz?m%iaRM$Vn0m9$ei(AxHz`^)LhY6hg ziqRqLc-;%9-JG4EvH%n`9MNA?;R^E#Kp1+jfp+mJZl?Z--@%FtjU{%cW|1s*pu;_u z|1m3grE>Y!j|o_iwH(Gr)uO?7_-sc*JGVWuZH96P6;;{~&d1?x#+LD$1k>|&ZNB1Ph29@3zAA%lD* z5WQOm4_Nd~FP4r`O1?ivt!5nS`)Xc@^e?+@Atc3w<(t*I9wqhFlzNq+uTG(LHwV59 z#rFTtFeO-QH_fQTtoHg>*-cnM*6_9pN2XIEABRL@8{G%y_fD$;x1f&gM~xf)Gm|9e z3~{{23ku2^ZxVX{)pHN@y!Ct!(dItv`RTqH{LvgY<1*f4TutCxW9|!}J{4&(5s3F+ zuSk!z?jxGpruIL%i-7+mKh-_(Sd8GitkgLbzqbiRVASsr2MMb!zGL6(5kq;=R4p;% zTZnY%74(>28<5xf#ZVpYOU(y{@_e3lf*X9*JXy^G9>aV>p~3UL3R&89 zmZq78l-0l4Ez;en4-+4M*rc|h-+J5zSHLqnwkmMY$789odopiuD1FJ8g^i!<>G2n; z464i-H2~qo*dC1XY$GJ<{h`zs?!VN<_EGv0;*6+7$LFq69&yoy+lbF_GOKF%g6dK~ z8MPJxqrh@Lp{@^`3SYPV!XM`zrHO{Vf+vmcA->!QcwaGqFhJuwp^T zUxv7=V{Ohgk)|kwXe+%7}f>l=FnfH()u+TJf~pr)WWLn{lu zx+ZZ#X;-vpw?{4029g_D<8HAt$Y)AN=U>s=hIhG6l5tVfagRcei2{s7E2 z&iaYxD*v5@{vwhBW#G;{E@KhP<#>TSLT?>P+`X>C8| zwxGwxF~@rYMl(U|jAB0Q_oqCb&#}p7E{U_2j}#*jA%ewYKiP@A&@KrP1AW`O10$X4 zLxCp7ovcNRTKsBp9kAy6Kc9xo4w>ItYjc;MSh0d0;&{nw8S&b#kf`3mYF zRUDw6nlz16G?Ydj{;SW;^_i2u$foEaK)|qD7QsT85uCHX!~HE0hWDtqKVM|3LRMkR zf7Pegt9cfIIa_B&=MjII??Xqg>2>sC$}ZOx3^_8yAS`gx05Uv!S*o*yFO-}S$&O9$Zn_PT0pp}LoH zKl%~ylz2m>$CO`!@8C|y2?DW@OgQ9?RBm>NgryWdp*!ktkdJ|w%Hb8<0^4bK=fTmF zEc1c}bYgogxR-nn2(UP;`O0*FBx>i%ye;h< z=PF~ZEr=LAoM>rjLE7u^*k!X^HezlzY+cY2-_o&bwKse`QGHxCFs;#N$2nP%&?5S)=yCUd z-tF$`le^7NxNI#y-%(oJH*&!#ASevrCAhBDA*_9-JENSE)k6&^RRU%XNgdZ}b-a1n zl;J%Gq=UG7X{g&(FwA@4){$g6s1T^yfs7xj=S}(`tu0JB9!IRg%e^a^vLO`5AE1dG zvUXgh+7OFVXCm61E>Ea@$cC%r-}QxWiqj-n6BBYS^UTaACWhnj~HnHdZfA=G95np&purr~`~H{?{?D(pJ<%gnn? z>z7g+x6ry*`eE{8o4Z1Ud%XHMTkVqYuONV=b^b8qnbLel!do1s4BM7)pZd)>KKI5T zm2PZF?T5{x`}dYQ{DrC=7Q_n^xUJ#<^(S8|`FBgeSTg!qKf%HnzoI{K>H2*#SK~7?M1SwVSWHjk?F&Uhs;3PGf8F z6a3!LKXIvViOpA2MfCQXQps0yUs4&5;4Q)4v8CJNKREjyb`RH#Nk_d}8jkB&z zWuDo_n5L5mcndjh=vT`6qSY1+1t(bF*d0@BYosO;iU;zBmwngCZcIP2Dz5jF zU7{3?&zUHXc|lZYFDyL7{H`=-)Y9j8PmOqG)k0SAqVm+wzVbs>dq zV1@>GM-KWkrM0bRMrX~%Ig2V@(;vE>$ACu)lK%s2G7AsrQhtKpQsfTokR=Sf|2sSQ zTq~n*0lEy+X}OVmN7vm}09jx=7a5sQWT93QkZrov`Xt2G7+fMXJW$w`e=;AQ*DZKv zF2Nb*L)HJWGK~WN{l4ETLGugLhOSYMa|1gq4nUVp$N6Yn#7T8g)nU<+Tb)k)>K+;F zZ~#B1#yg09pu?gK1c#QiSj76dbY_ISz!G#<9R4#~F>U7^I6Bb&UA(+C(_JdN<5I#u z$2@OaaQ3X?P`d=jK%Et@6YXE=XDn9LLeinII99o0DW;T(bDYezHT%63?7Z&a(5~RL zR&jD<(HVS?ogdGd;~jX*tbBG{&xN1G>x;RA=uI>;*Nwfql=Inl5FngC@;rp8JlA*Z zyRz#@;hDr#w*%Ng08qBx>?x1Y?_H5AJvY3cHxFg!gi!^`|0u$SMY{SbZut`$$3M;G z9sL`80JxP})2ZO1X|tPO(Dl%(~kw>Ds4 zuy=-QzebUXy~0s8Zd3J6UWqQM2|;^5URFwRcnEsag~StwF0$QXYK9h$exeXm#&H6~ zsqTky=Q?@cDjqfQ-~@maR|eO@rEi74;2I>LuV0e+*x(!$h^mvtzkLqLY5&!J8IDJrtJckZPcszGbejK8$F3;Y z23k(d#@qwPQCaqX>ohEk_@v!)#27)<@nJQskd(Qe^V^w8nLoMBJz&gMsnA6#7WAg7 zj+Alq+ZPDzUT{-^F9#k~oUJ=8yNXV$yEwyq9vE#&dF)#i{ML45n?Vj7xn7)8yS3fF zSWKR%{#Q>OE+8y-%Zc!px(W$ov z%sgem2;e7=WoWL@7fyI_1pneQj~q zW+C~7{S5&VfY*JrDy?frAI%>XzKcyAj^OO0zK~#fRUtPCv%rUJgGmK&3*9jChMzx| zq3!mLrJZtK3S-4CZGh!o2yq-t=(tJd%^tU%{-y5QPpT|Crt}~cA^dbn<&TqH%ucay z*=-ySOo{Jw^*s_+(WtZ<#UFt$t{CCP^??X)Fy?TBLxMf<7nchcY|&3H^#ROH$3)H% z5F8rFX%MgtM|M7TVNAht)3UwGrquVLHW%LY(pFPB{fONPYAJd z?CNRl5f%sX+qMoggXc_%aDT}|^6bn8k~6e*%iD>)z#=*eelOL5%Y_~97Ig8+PU1vq zC^!XG3rVe}*=>h8MS8l{%4RDQD;JYm+n0BL^nwB&>R8x)KOq&-ax>RL^F@Xi=F8m5 zhn9H1EU@Lv#+DCp zIlc>k8r93jG)8Y)#&BLgGvegy?Q?TN-{~{uY4rZ^zxlshIVjce{uu$I{V%&PFJB9= zAE$;n2ihZ~8HrZs`}4)?nj0FqKH(Nx^2Y4uJ|BD)#m+ck<;i|N=7#T>l~6S@K;<+x zqDYC>+Sc!OnbdghUYJrE6POy7n)qJGFf>744yoqT;;vh@pc2 zyIYIeW;qoQP?jBhWtIc)xJY2Rf^18#fP5&g2077>`zCXg-fPN=%Op%c@Ynbc=z~ls zBt&>0lG^k|{=P>dTQ7RiCgt3zu2pwv?<()>qDd#(9vLYMPNJM)ZrN7tF|u&Lp&G(? zHR*1*9oouJuRKC(Nm?SQnQ7tNe3`F(<--1CPvy(jw)}1m>R;4I68>S@nCAE}jNAQx zw5g0{lB=^B79R*~+OUSWlROnb%@LRh&!a#t1gj7TPLP!3?yA<7gjiYsFgWP6AeT>D zD(vP>kFHxBjBIzCm-PvPr*?}jhCiLS0@|Ueu)i-k%ydE| zO81m4uC#6n!@ff&VAc&Bg!~y!%R6e=#I2b7B+7eQ z<-Cb8Y5fiE;a z?`PRX^!2$1{<@TuiJ8pdpzzktHx7{Xoj=0f%{gjD+3r*g@9TFDq21LD;$r1Xw23BP zGnn*n4aaPl*)*W7tS>*&G3=3L-r?W$H=z5E&1UU)y9M@pr*mzt%qjGp=@7TY8^=b@ z)>nj{5bnrcGX0<-8nav$Q0yETT3J0dB|B(%&IBy7(?{8F8E)6XbO!)Zjf3R{=e&XB zWHZy!L_tL^+D>_eXojo#YY+Q5^({^-fLAbC%-5u3+08m; z)8s^RYnDb?6v~{(m;np=8#|&Mirq`yCiPy5Q8NzVry;Fih=quX3iyLMX;1BFK*2Ye z=W@FU{=Mb1K{?P&S@f(3!>@!KF24c`BFuW|A5yl|m5u=?jt>hvmi843My$_I6pod? z&hUCEzb;v)q&36F!v_VF3reo#LCn(^{XM@c4h~%1PO_6tFnS-y|RnqHEU&(TtnM)EaCSBuw$!se$b;a_Ko zK?QT@FfTK_e}W)jd68{N#~H|)Po2^0JGPs48g^&2)--9qLCa$A#~jtcgIV+}y}RI^ zYaHeqs1;ADInw>dGMzqmc4pPX>99?8Hj@*EyE2v7kzH9bc7i>N^v8Pt>52i$IcLxfWNq%=!IW_n%@q4^5HD`(CVL(_n!nz9-2HcBjopM|9U*8^6Lw9fY`G7Vh6rH34kLs)lzg*l0ptt4L?n|x@Yx9-6|V8LxxLj%#tUcrmaz+pqdrhgfUg5lcT>}1Qoj8nazqkF7$E5W^Z5>w06@zo?Z#ygr zI8r!sT9=*i8WYTyepQS_j!Z>SPt9qwL3$fv9@dThdSdYF;|Wj!s{&&|+kGOi7p#@$h!aYg@q5zQ0i!Iw z@XEJ-$6|y6!TO-^aQOZml_D z&_SZwzJ30wA10r|&%cLW&iyUt_dUUmeLnR4r&C7=CwTt1*#s3Wf z87|<{Ig75cg%sNxj45gcx0E-qT3B? ztQLZUs@@66lH2$zJfeA=iHvrG&YRwX8U0&r`l8bk7jIt*L!WoH#epfM92oD5|TS4QdRKC51ou@uyXIaatbYVaEZvbGd&Z|de=rGr#Yofp@CP)2YP{fmk7J-6^@(9b&_v9J_TM^;{k1@5gn!4{x`8qr?RZ!Q+6sZPDh&JQytHn;)hh~w z2XV6+xH45f`+{)l{vC`%b9mcbRD1oTe9i>aYV%MV<|uBPH`{yH^bf?~(34eE;%@uf z!1KaAu2Y1AQ`7=WlqWe#-AFzd44vExs3-u`Gt!WK4K{(Z8z-&o*60g)Z3-qyL3gNu zN}INd0Itl6_-4p)#YxyYd4ytbY=+yd0IjKDTr<#J;mM8?rjP7iyTI3Zp1#no?8M4n z4QjJBhLv_SQbBu5)?WRJmQ;rngo*Uk7+H~ED@U&-YipN-ws|d|WqP~;@t?3cm(%%9 zk8&c>)4Tfmw#JS4X{~9wKIENQ!OoXBDm2~RTK+K!Q1)SXQ)wm^gfGls01%&6?ve{a(M|!xd~bu|AVa zSv(y!Bf#mgwaV+0RTM94Lzw+^a92Hgz)zrzN3%~&&2`^y4P+{-Rezu@i|qHgZJq!l zHudvDYr6j?+zZbf978!9zV%nKJ+=Q$g#+9%H>AMei?iNNJK98axU-`;?)e5z)|e+n zVCMK^1AB#ORUbU>Q_YXYC%)D!nmxFexyb9h1L)8F07Df2euG21va23S*z-G1Td6 zt7)#~cCRm^-=*$@Lk_RUTqMt}^PBYXdmmB)zj!uHYFSSz1bkLN*!=ytUHBG6Ez(z$ z8wz9o^X3Z2-aN$KR(~5_73XN_;_hB!27N&T%AMQj;-UDjgaVryO$PMKV_?lILApyI zt;ge%HcmxyI`_7B(VplyomP64Jt(F~k;;=mANVf}bo zqQBRV*8rhuhDQyo)w}GAc`(tRJ5~6jNkF^K7^Ook_I6cJ3Tz#E} zSA%A5cMJhq(l)VJ} zKT~FDDA{?&8*)s;Em^E#IB|Lqp=Vj0?957pwx4>aSj<1D-cq{fe4NWQzev=!=2ZhP zL=1hi?7kS`JTR-vrWHCkY-oIs^#VR#3(eeNUPfmu;p*m|0^t#>l%IG$EhU&Ew&?_G5vhXjtHsc zwAW?xor7TPwnKiurZ|vlOieJ+S-u!8SFl)t3R8+Y}(j$j=nQwLtnVjf4B_j zZM`JYi?&`h^vB!rr7l}{k5r~e!yR99LHUXvJ`L#j3p7{NCt8f1BRpV3b~%E7|#U+G%1Rd`nK8NW8?kw=21b2@*yd7EEKNRdbS%5FG-OjpN8{xQ>8-}n`dv^qrDvBPs z+%El-n^G(4J4f%clxiw9#2t4%PbbPNCu@pr!Sx$6tr)K@>pM$DN$T>sPXD)@_QcMj8YA@kt>og14kQqBV~5`@u#QHux*O$J-51^pu{sz z!<nQihQD`n>U?Ukvl$h=m6Pe%1Btz| z4DU#neCl0O~GpM~@kq!d=a%#Q|-m$Vriu`N)-}He| zpm1a1N!VYjO{LedT@{he7kumcP`<8km)6vd4CARke%6=#7-Bk~Hc?EwCf%u4(f&#O zW7MCH{f`^!>g;-#HtPSu#NQzowt|FgXA?($<=l-rF(p2 z0|{bV(M=+0#lz`Ul5+s8V!NmcxEacZkq2GeBJEc5mBHB-+f_U-$AQ~q_N?`PN|-mn zweNQ}Khg}M=a>AailVS2{|sd#SKc0i>@vDF_jz5xIW}n9Ig+#&=@wHXg#41aGrH&D zcN=jGGY>&8s`p4}Mb};M3(jGRRj`NP`-lf@5Ok6EF2KTC;ub-TgEkVrj(|(#))jxQ z*~Oburxu}d!p)gh4xRLq4veOy3Io4 zdpfr@JN7p9G!%Qz6bl{X`3=#%RlX01bxy?^I(-#i>FP^>s=i@?)WcKFK(<#ZH^xXG zr9*6jz{qgZm+7rF8MQ@hW1sWSZ}3$&Tj?uZ*?8Z0IT{$ zvSs4AyzuecZPxV+!&0QAVO)@+<&s?1#_) z27j3kAfv~(@gi!~mVFEkEfV(Frfz5+U&)JStkIo*=ztG zByF-e$(7j_O~n`e8ktb*?3?6?69-Z|eQi{4LE?j&otB2s;ZLDarxgp*MdLHc@GBoYRl<*(T`X>r^urtFbCW$_hcKi}v zW#Y)%QQ;)5siE-)*0P=6@AR`B;&;Z7H4>xZY4JTK@jcjvS~rJXKRE+CxK!@1sAQL2 zYEJ#4Nt$Aj;9%bmVvKH+@_)7#m~NZ5h73B((`EXV=^RIDe5A?XgRu zOnpdgu*iHVDp{iIZtyLs{xEsOf#D>YcU$$3dH_^zIf9b9lh67Eg)+N{b%j7zJ7Q#>ek zk?ngwi?&c`IM>6H3L0zLZSih=fn__Y0P&UsDo)95(m==H=0(oQqu@zg+0(c9>ATeC z{)_!k*^UmpiOzh)T|E&nazP<44gmb1&k~nVz3XfRV)a4y+aCYp43N4ciGJ@EkA^)E zV86KFtnC+5H!6D(aO? z3S#lF?=_*Nvi>oKJ9nJ4@UD~j$oQbw@R@;UhU$(qs%mIg>8`1CdamXUw84%rl;h2q zT1{q*rOB^SK7@k$m-V_YPy;p$_4Wkd92rptV)Gvz7JHF<(14N7ZcL^Gq6Y*%nh0cF z%&L*f@n)YJvK+jtEJ1i@CQ5~)ZJvMcPq+ncpmv4 zlzh8n`_yyz{5UIkYySKeTV3~AUY3%5AA`~N|e?-P_>@{#m^sXon-lXQ%Zo z@-I=fdPWG`(Kz^MSl&z3oi&d~eWNx`OY9u&K94pd;F$D~N+KCs#V1#{fU%97@%r{> zJs0d@-CL%I`;(RH%#5x5v2fEYu6NOA%{Fyn@%&Zm5TMQlLm%zWQBL!LWb7hyGZ-5N zyFVHgBT^4cvfxZ2qZpg3DdvBOvBD)dwU|}?js`7gwGY?qDZ4NQ znLFOHvA7@!J>=(n)JD?rpRjMDvhs{Yf%D;sVL&dST3OVLYQE6V>E$6~bXo8T2&Lv# zpc}Celg3P!GV87(c38cX?jjvBc8A?(`u5j0-q)Shnz~ZGbXG`TkPR&Ks#@=DQw_tnvNj3t=f^a9EV0_$)Gs|+lz5-zGGCocHJ0X2afcG4n3bT-h;_1%^N5P-vRT!EV8=;y-m??bQ-nx2B5jxF5;Ra!%c&9L5aCqmHI<*jI_3;QMbL z5p-)x?g?)2cK*O2%v70n)vo)k0y-ZwrL)^u9rSyi395C>mi~73c;)ajYhh>*C#|_bhvwz~b8?_8QPmfG4 znw`k*=0E8KOq%JhG%%!|79TYso|{nmtcx-L@Lcbau7gFpL5pa$!(=g+CMFMH(UT!G zA5aVbkR7&)Xx!wuj`ET}D@d&NSKBVw<)30>-`&=4Yv2&g#a7w`z;#5w50>6L4PpM^ z{}{7pO^zfveS|J$Q>6zh8}z+ncP6Q}*dc$St!{7G*8KKvJa50yIOYf+EN9w^2 zJJGdTO~oYHow7=%+E3RAR!@|gJ2M_5?R^!f-tlu$`Xe!LL*M@6fxg`;@ppn=i10g;R99MQIa z@Cw+mxLPAxa65f+9m^^N>8fkB82b7a{h_&uGdz-~ zzHf_R@ok;nn~e)uZnbUNr6x2p50!2^q}<-WvaQ;=H1v8Wv8U1%I<*&cMDeGh)n?pM zMzw$g{K1pEVs^=OZk zHCD?y7pWr%0UrCr77{LE?JGrD2q|*#;>S|VE_y#MYvNC{nTND7bDWI%0iPIrCChgH z43JDk6JVnmSx>E#^``nb!Y%B2epgTq7Yi}du78`7{7~r#1SL+0&qd~I^F(P4t}}aN z_rX$5M~iq>br+%!>i)V7OX>~FkzH}E(G`u}AjZjC6>w}?{k2x_@gps!-s{gdwfhkv zIIYiF;JP}QI4ShxQL+s^wf)=?XH2tVOz*&x8+y%gKU<(_dy(6Ry^+)#!$Gd9k z?0Exe%$wosD!+_;&>x6eLcB|tl9LbyZXxd(F0n%>0fZa_%ps=HvUS0+1w>!?7wxtw zm3}G-jrP|sM)h{=_V;u9L~{!oNb{&r7R#Io^}ULxBjdmo6RUfH&!WX3W8ut2Z%>w! zyWXCnbY}OnJ)4O^X^D@xtw5*fn=)uy`0{cu8{KZ+J;`S9bC>UntGVdGK(CoOgj~kA zkV=s2h!@{ZwdD_X_aRg28+wTgqA#K>>i3UxBJCt=raeQydgT|8#DUPI>2Kxh#)!6% zFDncJIh#*!H*Fau%HVpNxoSs;=)S}z(%4%XGw%*NJFGU?x9KtM2B4MPow^xqVFj!C zxYW9fR_#9dlI&{ZIO~!USZZT)^q11s&~sZ^$HAg~f*>xXt8Vaw?BAr9sMFvV%|>Y) z;`pky$?I7U8WPzP$m0SqcNXXCVQ^JgnV$U%5MVhoF1Ch&2AfN0NYww@qv;Fndntd~ zvc}G8_Ktzw+Cg0W1oxrH8|Q-Y1YYTN5=rGTB}5ZnOE*3y|CBQ)E`h((mWTWVjhZ8L zFr4dXOY&SFHEx5hwV}mq^}BbZI8NvAt%z6)hU|3oO@yCykVgwkHU} zgvi!VIxW+rC7%DBNIyxQj1TPQi1719jBjAIxhuV&&GCEcL#8D0ff2l-BB8*Q9p%X#{GjP>+4iND>ph?uG2941bs=okr#oCTTXfxx z06G8Bj^}QbT$}-zL>-E6oK(;HFs+Sr;PXjbi@h~^i{Q?gu!7fn(Hq%S{eC*g z!6twZXD?aVVPRYvvnkTYDIaMH3qW=AUQ>sxW=k#on!OV(JfumcpFrDtQRa^3 z-0B$PROJ4=jqKH8Ca0%VabS@DSaqEaZQo6NL?hUM8e*V+sw2Py?Gu$j zT?Y!oBKAO6>mpwF0Lh%yC>m@MmM*dWx-rhD4&ix&aev|l*nZ^nth)>V_6cZ_*^PxH zJP7rG9uLc7Sc}_yGDGwGGP~Uqf?aC!k%~3q8oLjzt{vwC?7gG+3uSlZ2;6mj6`XB2 zq1(_EX|@9w>$rGy8(}v7UvBO&uZ+_FpQ51FGU9VbZtpLvvYQNn~|+eo`d`S>sLWU{`yE!ENgf%UDW8?x_>Xc=%{mCe+6hV6a) zPfJJk8{K)gN5n%z=)O|F#6TfN$9a^z&0p43ZrJSUG9-{?glOcKi!h0EZFgCEQIQGt z_|z{l2j<{!!~z9IE2|&2--55kR0Jucdk1|dpOVXK(|M?dW1eXSislf$z47N4M2Y0k~LF6*=XqPnsu;g>(dBSJ?0SIwE8AGV9y!}x>-bRtCT-g(e{dc=xgpsSoq4O8v5Gc@m% zTVcHn5JiS@7!|lXkB~XzkG1)S_FLlI@3NRMr|Z1cSj|3u4RNI^ZPvGTQO`PiPgXh9z})<)HYwv%lwHv}E8Tjp>QX7TN2{;k4{ zhL<6o2&E*-tfaAna)9#H+s1WBzBl+Nx`$wZ{UKq5l%{)(5I$19e6pgYLh_gxFqCQ? z3SH3~G-F{VPAhdsvBmbkSEk54+Kzwypb4J1NPCmHUW6voy|^yt=?Vb2nAl4B7AmfE#PBD^Oj4?;IVQJggoz zX_c!ZKp>)^GqAirlw1wEGnl2{fm#H0$xfdLGFNrZ*78VWN=V+yk*2_a?4}o~RwQgh zm_{?dQi1705fy;W^)cV(tW$hLxr(2`d>Ge@Q}pn<;r4f39p4L-JHaF4Oybb)%`H$k zG_t_!JXEc{@0db#BQg{>5AdQmBLW>r6Y5$qWbW{yyY}(&s8FF#JY<(XP!s&3%6iXn`OZw)bui_n>aA-;aVK${~5kpAnxk&IaRhN+|kPd3%9a%#!& zH+PF}pw&8Ij0TE0<#8hUiwSS&f8hq=S)G6|Jx7>m>&)h|p!*|zH6SLjTq)S=`vS5< zg%SC;N}vJA6ESm&!z(>}x1a>(F$)y73GF#1HF$$>7`kB`G>YrnH?Hvd7QPPyi5hWv z;sWvC+*RbwL?0kPi8MkLaL#zR-J;IRz$4RxJsTU+=hW&**g>;7yo=UCdxh0R&k@F4 zZh|4Z^aJ=iDn>LYKhd5RxzfqqZngH3+mP+nALp4^dEVfZZ&;0+=l>S#C;P#NY2Oxk zt-*Hu<}B+`4v`VJ72U2-Gcn9KxCxetx1KuPzNb2*BERDJKxxsR<`iTLHimU_JlbSG z1z>DmeF5q>Fl30sJjZM-r&6MEIngys9@PuFbW>CE&(3EYB3o|-E}*?oJH~A;o|K=6 zi7oH2a*4kHo+$YWI)r@&{|_q+`L?KrwjEi4pDYNx4;&nW&daBEEv*I*eDDF z0@5G|D2joKh2347(}i>8>RZ=ccX!;yU3Yi54&7#VcOfbY3RoZw(w{%$yze>BlL20Q zB|gcnp_B(Aiw4;E&1PS}MV?^p)iI{`>#H-_6j#dRq_WrCapO+8jw$XANJ8?(#4vb5*EiaiBit%zZc2J#KC@tv* z{DahP4tRju?{w7{Wg*~>v5A^X-{y2TayKn|3rTK+peio4O!>m*8L^6EqvggCD|nd1 zr2||>Ii?AdgGoDLFRA7SEQ4uTmd~F)K*Ar(=nTCkr0{ zNl8y8i;R!KJC+1lcaOYqeWelxdE>+ zzh*211Alhkw%No12~^=aXU1amO^U{PSm@yN#p|Z;`mqHTPQ`xh6^;V;@1(TZ zt}CCSH;L}whQ)Ivj(gF4(MN~HY?{5Xf1^7{b6>yZg{mzvG`Kt>xZ!)H=ynOx!Wr ze)eq4Pq3H9(XBXgHaZlWV0Yp7C#Q>xrfiN&&LwP$X;=_Snm4&WsuP#%3`X9tT7_t9 z^8mVld;UBGUPkO{U$Njv_>1v#+xNT9a6aUTkFQshly!C2yg*^mXN0@ zQd!v(hav;0-SK11fo9FA#JJLM1i8BjIz-HQ`kZyL6$FYWJQ5s=A5D5D5EyS@iusqo zY*yfgtrKCtH^x>&ws4Oi6`pO=4e@%LcB_|}Ye#U-sRf#CxO#1_4rQ5}K#m5W0uDzruaAY!_ur`KSP%rMs7RH+U6` z(_=SNfzIT;T%Lpdttm%Cdqb_hVm=Ud$Pr{uzw={o;$5PHGc@G_lC({2BCRy(yDDQ&I29%?B-Q#kb*l3d&8$XiPK zqNFs2A2m&oVtJC{+fo92JzW((&*K1E#N~WD!D6s-Q^D!7>1E_`a~P>S7{D&=nThF; zaVhoCHtb*7a4(JYtdpd>?B-Ik!B}Y+3CIS|(RnbW`S)!joaq3yeU{TRhr<$%eXh|} z{I%c&PXz4+013l%#^yrd>X3VebKX~tEy@@#VqkTQy6~)Ig1gr)x1TIZ{x++731^Sv zb_b4TDGq4;LG!ru?!yH{`#eAA#S1SRc5wZE6q5?ol#zy?L$K zU8W9L2;C_Zkv>sQEdNb3)c05ak9@d4o*y5Gn!5n+%U7Yw6hBbb;}7g&@S70>URN3X znYX*R6Bm_VQs#JzCt`zVsXFUOuk6JurzpW`R-qafx&ZVs08&( z#?DUfXE_}o2fqY)(%f~27yQvCQMapKj?IV+n!2aBr{UMsw7Mf6%eT6X?#&t3YtKg_ zc%_DL@~hz%0TpGK+Aq8+3>^4eN+EJ|i!ssG_Xa+imd0i#QTT5D_;$YSbG4h?gaTok z9jXUvQT;COCn}goFHhbvM@tdSH)d=#c7ZGdrk*t#c%J^SE!xKg*qo^1FBog;JID=; zd932~6fi)Zb@jKh3&Q%4ggVZXh-x6iu+naM$lZCT2-#gbr;vo|A^Ox_Z%=)O$2`vf zB9d@WTJTY4LrhxIbVp)cGBMFQ*ynl!vQ0XIdz^Z8A4c4g*6O)crFw5=z_S`09fZIx zd@50WnPjlq5OFNg(UA%KJN`5XIXZ=Iamg}0F|h^4z;kd1S{&MC>>gmClhK?!Zmvh_lpR`@1^_9XmQ`KUddlyWvp~tVeo4mEw4$+%C6L7E$pj z|5VIPKyXGglkIS^=Z5{yt~MSO2_C)Udd*TLfS0C%gyQ z(8lJ1ugPD-){cFHrGw`59{)??{$K`hk2Og=ZjQEF#g2Y8980|4E$D+`OR*t~LqRIt ztJUIGB5jWJS^LS@BIFs;#-CfU2CI1`J5+vlkqlsmT>#7X$8rNd0*N{&Z-OY}yw%$Ii+WX4vL@Q3|Kz$1y z#o{pRqHp)^5d$S8|2b29mm8^D>dxDA;}eN^+6&gx*dN+ivHij9n{9PNa0Cm z9JUTsznDB=lY$act{Pry_5&W7QR$!a!x<9a|9qB&Q(FQmj*YF0zL{v~^{LB7b@`%v z^Gv;xkNwL%I@+4Doq%2mxbR zsSOaF0}eGB#&kY1@pGuZ{*OafGqa)Qa~}Q+;$9Vr**Ugb3~N|}T!mdp2W;-Y3&jaQ@HXa2a=bC#Wi zL#!QZ>lt1P;b^Eaz@As{&5kEkO9epCo1q#}&%E~5q4xRUsIL_NW9Cw)C~SklPnMVz zUzyIiNr)c(y=>?K7!%~RJ5X-vL_FC{B%j7IY;6NxgaWX3N;=Zrr>%G+qzKA^MGE-bb=C z)og-N=kY+J1L?Exuj5|&{qFM?r=7Ol1Uln;h;80O#mYr~{8^1T@jH`{@xPp&Nw$~A zwY`p;9LAR~qqZ{H60wX4NkHm|2j8~Br}&HOx1{}n-^ZUoN+?_PC$Sg#YSSU|Dojwo zW@>{Yh=0FlJE&;F&6*Q)x$~`rI~;?);b@r^qaXkKs@kRVw0vkx5iXQ>YacE>mVQ z4^#Q7psGk2$FWJxHR6y*_07H8*xy1MN@zX&doG0ihz=PYPxkp}>!W!aM+vzb zT&Hsxep7H^0s(h(ES~W2iSkcYa`?-L+xf=kBRDNW6trvNd(e8oo$$>5X{YlD48WT? zn4h=Uo?9?mZe{J~l%Vq=YC)Q&1{gg#ce0vpvG_lC-)H_j42;!%?<;iXU{oPeYLRTJ9IlI06b^q61zK6EI&xn6aZ55Yj$}uZj{!GHSU+QzlUekGA zFGi|FN1yU+A46m8R#9JZ>hxFoOjxWL&UO=dI_?~WlA>3B0rQMT#&~N24=f3wedIh-a4H!y&|87gmrv>whDQ>pW-gZoJ3*Bfr&(^Gk;3nZEn-@kRD5*B4JyB%NQC+HjxkswDXZRf88IEAt6sxhvnf5|2F`|nCt&y%n3-c1ul@5&Wcdy zhZ}riX$21RitFNZ7A~A0AvGWx2Skc*u558U)DRPl^VNvS< zspV|oA<_E!ye=6_C0@wE_?(sN0{Mph)*;N-0Xv-uZl0j-8l7>vhcxn7d(;qP+%<5r z$JSgM0V0Zqj{)mlm)fbvooYUjfbN+lm%td$N9-H90^i!@e5TrkC0OgmoP#G_w0Rl% zu;@Mp&6|UEq_5<=nlGJkaXy5`$K5W)SxaZn`Z`2BhxZ(l%#9%3m|g4k@b;DJt6EP7 zL>Z^LzU6j;w=#HiYCM~8fY?5`$uXQ;;PL^N1bwB9$JX}VVvgC?_9JbfVM^e&=1q*z zk)+K^^*K>p=X`{Md<>4rI`;gZQDqIsOFi!JS|JYPDarB^MJt#{8b7hIv-P$&CqG-!C^e@G54b@c*CI1Moqc!L#?KCgcz_PK%<>%otf{&=x*q>ddEG{)%xeFi z<4L=HmOYmLBKu9{BM#r!Frq?&Tuz1-b1y3H4ml!xMQMV6fIn#Yn3F%5y^ZKb^)xA3 zy)fz&dSk~7W+&K=@a3InH?Eaty%0Z2+iu0XcwPN2Zz;Km&0mbyq*?)#tV4dq)&u?}@&4)n~=bMQYTt9*a zg8NHZ^}rCs%|HWj59Bv+dGK^xO=Gcd=>PR?tpN!8)cdFT>zVqQRv$SGV_6@6oJF!J z$=tS1@}*`ft;!)NR6MyBZfIEJYE~BtSs?ELU6)*gVkuz}-Id8y!=~>g-ZdR(QQfTx zkWC2x?zHc3?8RzCsovX&*%;B0tlZ)_k2AVOD5+- zFWLH_Upu|VrwWFbl_z0H3j=ly8i#EK4|2{7cUhh%-Ljiif;5N>*? zJE*r_Kg@pzjt|r_<^^(GS|+Oe1MEN}+llIzgD%#L0pc*{AQQbuY#aZzN>f z`2w>0GeC>pTqeK<H@d3k0_Vbkmt2=m;rVtbi#hCeKr`t$7)D;EnLBl! zobB?_E{Iz$t{|@G9U$GF_L3%uLMvxaIY@bs^jm(;R}pZ5v)vbDc2&vWNm(RpxncU6 z(w{;Xp!f_#P-bjpbx2gbwAA+=&zA)Rl*(NH`P}|4GEpzFeMx%;;1@-9o~L z+H&Uv_Xum?LSR1tY;~>YybXJ7E8E`qGSy80HF}V=DQCJFJ!xUR;*LaWzDo4l*5WP= zm^pF)qv?Bq@b=2ht?HC?GQkiu27Ni?yL*m>t+CPuKf2MF|@VBI|1vw(Hdv*c0QL8YYoi%p)59J|V!EXy;O zxzCr|ece9i=yY#%5#tj17)GuC2Ao4W=KEjU%-9*>oZu(`dg6BdE&R9sw*wj8QOYfF zoK35Ae87~vXe4F)9pPd}1z=a)LfZ_ zlb1^#*hf^^&#TlU^4(aEF3hw18~UXOsCPGSYsel6MPG1sWArnQS$8uDh%LNuHfCye zO1fEu{ExAj8Q!$XYn{LKBT#n)`>7jm2wrxz2hKScyJ&{H+qf}9af$u|*(PQN-Es)j z3WS?N?$2?ugm7Ne^|5fY6!8{#oc;sXh1XKWRuy7gFj-S4Tt4{t+GuCdfWH9X@>nvJ z7LpesuVv3_d2SAI#MgluA1~ktUIRBo{#0O7Lk1oW2Wt}gwki&do;JRrg#cVgA=Wk% z`$zX^YG|j{S*8}6TvByIuYZ61nQgx)m+Ejrp2g7&N5#%hzY8pl|5yFQ0Ld+xcUNAk zt9F^*;4zfkTOO9>S7TQ-6oKyOqDgGKPg8E%aN;V$1b>Kl4RQ`>FTcld@z^INib8(z z%4NfA{up&vWbxoC)&0GZGy)?^uH4ym=ZG{A7Qno0DCi_Qfz< zx}mR;`KZUO+&=L_#odV|{fK5El}x_`duf%3{xxp#*M)9W?vTpS*QopNw}{&a?BVUs zo8nzD&Wc&`mCh^F+nQ^m*1cNZP;3AAVLhTGyrq*>Z-%t6vOego*niz5Bm;hvPxvQR}e^iGA1$64b;kn37l-WKoQ zi1m%XoW5ED5-va;mR{7y6IvkKAO};l`l!hhc(vn^a(O4GeNj#g{_Rdx zdw5OSRF>;)cRxUl8`$x7z)Qx6_6R$o{Fg~V0az6%{BXNSF2J(IttKZKbv-n zw`j9`Sv{xfzJu)?<`S3X2_Z^=`E9m1kv2k ziSuM#utLOk^RD3nQ=amo>vgX#x?q15KVZBf!BD)?*Xf>?CJ zVa_i%a%XSxJ*=Te3Oa@>_+ubWFV)b04EM zsdoX8jmB=lz0J_b_!==L`I^Rnr3z?9FAlnKDc|YNsL9}GLn9t1JXG)e@;&_*6*n~z zbXWL{mM@nj&W(6(${G4y(kZXjJpIk9JZin9l}CRuIjOMcDP-P>D+w=V;*d1(&8`AR zZ_5=Qr}+5E6QM6BE+fx_HzUqtIUz1G>RWeCG<q~u%Smq5k-*zUYe`jTmu_&2 z9C}Z;4>*u!blBT8+u{>J4LxTp5IB!-96N|wCq7kHu3rKsxX|!T^@|h*;uHSO7_YiV zJrSZ1yH8R(dY;PU$FSe4F7o*dnVWEO&T7URCs)B)V1{UC`KBJy-#wz6T^N_?4rq8D z;E*K~&qr@{@TtP3HW~+_cc{;rH)-}wq^wSxI59CWV+T31;|KW-brDQsfc!A)&o2zT)=XK!JjxX|$)y|EM+F1L0 zNt(Rni=_^SFSz47lMAs@UNh{R zCQamDwZ!svFY$KBV41gjdBr)g6Y)r2jPe%p_xvm5HQDn<@VOz9M-~5t0KnPuwh%~5 zr(;d>j*>;Rbkcu}cToE`7mewnWs%QZb`E_7to{D9V0p)@n2Q3jF^C{g|3Q%BcK?HM zz95YHwaN|2rC80KKWM-zTW39@F^y}Pjf1%(#{OTg2cwLppoT!4x`M-uD*Q1G=t*^g z0uk7p*nC9`Lpa%=!=Bg;PqrJ8jTD@6@)HY2=H`wd{&P?M5sJ=?4@kz9Ev-C`w6eZ9 zIaDM0e9at0E+ypyNA)mb29S$5L3~blt-aapz=%bep1SnUf*k32Q06oUX!?K%GC2m7 z^z#d5*WSi*u{ZP5y_afFI0pAhajTjH!Ou`#IB85yNSxv59YMP~Ql&?$$Mqk&e^j`QT!Y59i^cJ;mQwe^85n#9 zg=cS#VdfZ)L)C5zX%J40HY*XGi4mZZhS)P>Ab|-XM;iffe!n< zO>64k;OQEvVk-xM4UxW|{Qp|WV@%x^=d@;_6iX{koix90{vY1}Yr^Yr!J=*7BWy1_ z)O^mbw)aTWi6$*Vuez6J+vM4xQRN&E6;K)XQDR+ z5toqf^wp0YQ~IN(9+bXRZ>4^p+QG6h*FqMpddJz}^3_{ltto4Pbuq(&qKCeSbj~3%bAkq%v z+|rKAGsmlc%PS}OrfXgYD__n+2_BQIw1W)|1W+h~JxBHj#jco@oDrDTR+S>PaBFt3 z#5S2o4!FVb=OkT#5o{@F);pHI>f^eVDxTAm$H&zjV3#4KJgjOd*P;7P*9{R<4r=^hc%L__YwQN9o@7 zT^3`DS&)nQM;iZ2Ikv+0v5jOP7Z2SQ4QOsGvHvK44g`50`qfNZXW8QZ37J=5v8oz% zt&Rb`m0l_`uE69;z~?gZBxCSYMr3cb)DC?BQGz-u`Q|wb&7JK^-HE34PWA*+H_TZQ zP9v>@B&!5H&n34#HaZR0hJ%j5w$dNq^dFy$dHpX;{K#YP-1=f zZVK!P;4h<$P|@T%U{$_$vkU`6t~_l;;&1UhPA+g2shmy~oe&(T zd&vKT``ERDaG5zAq30qM$Aas=?aXp?DKN!N-#0%1S40#nP(+`NohLheu-#FQr`YMgV0GAkJK<_)SH0-1zJnSL%6c}!9FKFh`N46Rva>s+9V`7JHq(z7 z-celo)_)gpB-`D>9 zmGyQ4(Cw7thErkRZRgT>y}$a~(dTkDd8drD41X|p_Fd(@P;YUq<str#Lri)z&R(#MQ{220}vr6@(cQM<=(O}mW&o{(B4;W8?6D6Bf&bWWAd}Ce* zlv@91DR6pSYv7eiBQ1WxNB*8yg3RA_l->GtkI=* z1Z+InvRr&3Zg94k}h0Yhj{EDmUR^>B#ga2#JJE&0_Q;^ot(e>J` zVdm{3yRqTBR_TIc-vMf*VegpdHwD2*Q3}PefRS>#;#cCfyUNp zugA7u8<4wzb)`&fMR%bP8KC!;(2NjK@%;uFeRAkQ^nbx+zs@19*l_Xgsk!$0=Z=S66fMlGnDeu<%NE{eGhLw#E`w&+1)@j8{;Fm09En>-~)u=9R9}!iAO?RH@&p?lQj4J)NhxzFy?-pymGS<{5m>&T-ag zFTUb2Y5}`W@WcGA>of*~F8Q{|G+bUt+2oaK(UG$#T>7q}S(IVDwNdehVT6)>6u@Ch~vHiwdqHToRyO&I2(Z^4&D z%z*@$cmZwm_XhR58C#!>?M?qH@9CTr0o%8>Jq6r0=WzZuh4k$UX90hdB&pcO|F}yn zf7*^X3@o27WVFmKJXCxHlZp>hohX$G_JO)v=sgD2FA)oO+iMQNGg;U*my(oox}_R? zb^QLE?O@)}C1;~5u6uG_Pxpxqj{@)3AHutKY2ay07O)661-_1(v_V%epA;0{-$hoj0eVkU zc0w!KQsHp=6Mt4g;(`&AadyBW`VbD-cNRHNY7(&J4NYuRaYUQswKUT1i-7EtjkU%; zqpu^^ec}csGY4!4qJh>dy%p`JVHKMeom;s*j+Po5v1?{AgBs%RI^n;2XuE(xdh9dT z?({@^MPrUze>N#T{7y%17tCkbhzq*1z@o!hoozJne>e_(**S5w1GA9 z5U8*RM;~VQdfWGh^fcQ3o?Hz5*c_%~I=9bgPJsAnFrRXfjMMasx+d0(!N|t{k#N3h z_@$&~C#=KS%!9l5Srul@@!nd2&8v*1rf`c>t-vY2nr{b z$6Ru$6R|53y{`!s!X4$mGaBJmEq^1ks>gd@MD_T8?S5};G_TR8DgsOThK?!BQv_Ih z*Io!h*N8q7rCwNJz+&PV13j)yoRrHG*?D9$HjHO6@AI^pd`g#1T9%NwQ~0Yhe@^;puS3fj-`sR3=2+>G=f|GAE(_u+ z=jXnN>x`J+dEeF0-spN#S@(PBE{VXZrYmDYdKJs`2=AZKZ-&o#UT;U#R!#jEQfdVS z@6>0T$fN|PNIIzJ%ZNJ#VviUNL=_EtJXNOEn$C5OPZ-({W0g{a!s zb#Z2l)f+>=OTnlGx};&F^BOl0H%6X0Yg1w%v`&5)`?kwJG8P`+Ow+q+?`Y?=!%Anj zv5=8fXBEoT(N4VpWRYWoip)N&lcWS?Jgqf8@i)*$(Dn}QbF8m+oV$?l-9{B;} zCDNDl5`Opl`aVF@f1sCy9vLf?Pc9TJdwZx=szh4F!#J}GB^AY<-9=-w2hjG1gJ#JO zrT?)Vi>{69Y&((CI_BPaVdg{LhOuwlKk(zCd$hWH6Oo9x(C9{sax1YL@rHQYxU z>cA9{+v|Iu4(5$+(RQQ$!j%9$^4biE-I2jJ?D(IVvY@G@t?ZC-Ko)U#YgX;?KAADB zi~m;#wyNo8a<#^&>ts0cl}5(FFkx+chceLm#0&PCw?)GRqa`if~eac`E5pY>NX`i?F{JPF_47&x(8 ze|cVr<2r0GVCGa}e4F)kx8_0d>CigMSR+amp>fJ3(=*Wa*%)FCTTd-Twr$<4Vq%WmEtlP-G@RpjE z^!GNHmQzU&qJ6xQMpVQuw;o&2ui}Q|-Z%5;ZT|$jq05cC(R=Ne!bg<#S^cu3%AVj# z@?(8m{laNWaxrF&^VZ;2OK9SNd`4ufBdFoK6QJ!7_o{lWazTkJ#7SpGDe>p_P&qpR z_|R#BnA5A+5k3L`ekxEnN9-&Np2I8Kicq*_wEPDi>y3x{)*lyT>00W;9p8DqalKXY zLbFVeQMON+{H{*cS!K|5c^+*4T6V7eN%Kj?mC$>bQQL*szK|J|^}%l3eXmY+uTjkE zvNx5@JH(7j6k$^lJ?OSj_HETq59?*Z6ch=@_NQzAQ7#*O=vWnFBMb)iIbeq-z>A|h zppCG31RUxZcdD&`G|Hv+o_U}ZFp|uHh zrp^P_x2K(g=Arp%Bf9pGLJ#ZW|NgR6D8VrjuzI0qY?qPHJp*g$1DrzZyyAy?VA|q4 zqd$Ecd>c7>c2C##vQAVh`r6O~(iUx_cwV?{ICUap&NendJjFU>v}qm1aCFBS9tFT^ zx;qh`ixl}JIcB2jqg5PIpMp>)0vA%BLSD(c#rm-Yh5yXY9=xn?RN^`l>Fy10S}FO5 zZFX~sKa9A!ec`aLK;cNXabqCdasu2Ai5pqbo&B_!W*ycvXF=m$*$^hIR5RlU*Cjc} zGmN&z=1k?a1z$KP<9tyEnv)ExV-|;&cKKzUj>96g-3=6W3RQA8zQZ|5? zJL8>hr1Phzuj0(t|9mcy%=R6ctUs?*p}o$1Vk)=!w778Umm`r@sHw8U!+!JzA>D%i z>AS82OtMY7C^yT+02gyFlMjSFe7%%fT+4$Ma2HbeC6kH-{^Quv7u`ZGL5;i-_oon4$rT~X?VkV7Z_~66x zekw>3S*K-dzG$|2r37aRKDSiSuP0W5eQ(Z*`a0RrB{JX@n;0hn&A=;yal?4gXmwO@ z3$g+8usxv=qd2W|5iE2`VU?N*108k8efhq({jk~|fA*v{_qU~)UqJa`LAlMCNgWs% zvz!>CJ^#5vpn|934yih!-lu z{Kz&#>gn;a>3$M>u#zqx+U&Ln^BqH^lxzH~|57+2)<{5etaYQ5Z{9BpE+~lZqhWjA zK+LbGR@@Pbu`sE>B)I;oVG^Fsd@?`74qTU`TbQ=7`k){iZ=iJz{-(4Dk5!l3I*+!& z8*AWFU)shDUG|EQ%+Vi_`xu48Kae%`Yb&kcbER7cw~i<&yVkFutimmJJ4sj*n@k@2 zc}jb-JACK@=maO#SO&@?M$UW$ER;ps%qpIt%bofeJ>RvXc9Ojq^hLTvyqK`c!}7iZG$8gVg5!3{>- zp&lE~b2~`8FjUdx7IWW+2q}$?SL}tYmfxr1wF}3d&KZ;*K%Bx}cc+7%_M|cl+^5Pv z1y{^A+?hjplGDSwpaW1FIIDCOiYdV;xMO+oOB~M{qs?ArdA`h>@eq4QW!EO>b)14u z5iuwtr5&P~MEmJFtA8~&!}4E+^19jwzyTCsn>+VMzX!8nq|nvM-CVt;$|_keE*!3Q9xl5+ak|;S+1;G?`C_|g zkAL_+?we7_!~H%_vA6rv!~&}x)DsU4tEu)lZpJTxz7l_5vusLC;$tMS_hVyP-;lmc zEb!^VHkE(Jc`Ky?2gElj7@j^MfQ&$F0)xi6-E)@My2_b%eckOeS8#=v{Noj*iVc>vr#$$0>Su^d2+kR(}jdQFh$JY715y_}9Qh`!> z$@sj4p`iGT)5RY>p8>Mw`?KSF{Wl6qU3wwZlo>tb=Kye6dwG+tM3)KwNM5Z;3@~*T zshOXPL1urCD^lp-cbcKvjlz8U_s@>EzN%o-&VauT<@kwBF^`})h%k#pr zR<9ora%P33`3;DrUrzqYTLE2!x9iDcSUJhTErvIFgJX-rUO_hsQ4TM73&wEVGgW)I z;Sp^83Cy~T@zKxT-Kfj5qAn3o5=HXpM8yX_caBeJ>-eEv=M!r~j{JA1N%25ijXq)v zOSoKh7v|sdSs{x~7@Fr0)p}pzD2`}HH~*40KsPll&TXLXm%q|1XUFM|U~9)tx~wZq z8#;>b@=9=Dt&4}{80P^A&{H6yVXafQ?=t%}%nbv({9$wN&MrU z-f#!WAKw?rX|NV>XS{!Tq1B(-?jipq3yg}hSB30tbX(ltEI>|I*LU} zZw5brz7S5#)x*~XHqo28_C5pxy^%(G*+PI9fh+j`;;!@oQg58F+W-tvBA{(9@%&N{%#uprG&T)Kyc;;0f%x?wpaTWMJbcqW@@vgxR(l6r}2Va z|CMhUeIIg0)Tp=^#iPDfv=c7TOxkxPKaoEbGO^9`D~LN&FL|<`Ac3X=vLvZFA>0cv+O`s3Vt1IueQju9aO8Oo+(+Br!>tOJIcj~&l0*w_7tB9ddb4jQWNYb*q8B7V5@PCbP2$A&5F15V@_Ij# zX$|HaKQ5%LA$CljFgkcn_#pyd<6?b0V#60d9rh24rzy7{-mTU)A8$OZx#2fk5tig% zwODdj>>2Y>)F|s4c-BMW{8FzGIrRiY<@7*l^bfBANp_{md0(dq?kF_J-<&3AyWWXE z=;<&-SrG=ZH`=zpgl#o5+x3G^MOCto&}+d*KwBksb=J;}dXoK7mXmBo%|7&fO|J7E zWq8LCckjO&l9miUWd_f(jdLl+{a&vBWDGH`v|7F957*igVw72KSUz@MfGooOhy028 z8}rfu=(>O$EnErE4Z!ERm~FA=N23+D><7w(3j&Y|-#+LOz(vPLL{~q1r)5iin%tkS zruDb_lM{SEwIRGa7%k#DPA?-5-&f!xn82hAH0Ho$~o>YEqx~ zUy1k!T#J6>x&?1z3fq00yz9%sL|dy%y-QgPG8GapKR58zcD_o^A5()vb7$49S``TkPznb5kWOY-~6huRl*m%MTk zK4xw!PzJOhzL$|=XDm6rVg%t142k!#--1{Y{z#Uj!;_9n?J5egIQK=NIkm`Y1T#R0xByu%N0 zdX;`w!{i*BtAP8CD-s`qZ-w|6y#+$ar5Iw=G4zgHlBQTzEBIkJP?o&m-@E~v_$yX=(W2i!TNLbHrr0q&w-8jmzF2rUF#;2ep;c2 zLrIri?Nm(_^FJ3c9E3|LLyPB&u%v>TZ99^Jy0$MU`f? z-%vk^qGk(%-#Dsd-t!Bp!R!3yXZt}n?ws1W>3j*EoeSS$*<~uWb{{Sk)~KIBJF7*l zE^Fhp_5;`JzK8E2U+r9Kaxow~#fN^_{9DypaAUZRcad~XkF~6s=Ye+hWSP4mPeEP6 ziv3?;54V0ZoE+(qe)aeTNi|FaE=OuCV;Te_-M;(Gj^xddFL@}Xmu<*3w=|Tf77As~ zc`Oa-&Ic>6&FVFII$Z(W#vd?8!0*kXnsR(rCu@D@b!)Cyo9JCZNzd82_Rpw1fBm6y zgPri7Z|lmoHcSGR2H z6pePP=^#<#1-hnKM&o-s=73&C-{}-L-Q3BW_h{ z-~7j*082A9-h|dM*%)|fL*o(FwEf!(Ceu~t@ z@xVwCuE^+lXe*j6Ju|Ru>J1fAwREplCJrCg!Hk=q(!6Z`aq`fur6iLi(EJzJXf>e z!En*USHtxkS&E(FHe1djU%} z?n`s44IIZ$_~yrkmrhVl%urji=xxjXqs?^YbD?bWZCD70wZ-TM^E~sS&E-i5G!Px)65a~^Jj*}SZFzIJHfY7Z}F3WG)XEDBybKB6#yrbqStCDf9eDcu|eNA@> z=ZGLwlM9HV6hJSU@j-2X>sBZGg_Y1~O-;i{k-dk<;pJO3ij|AA?pVq|UtN85u6o1x z&m~X~lR^k=AsbITV{pKU9L+QA?LUL}v$5`Y2`Va$v1pwrBtKUkQw((ME&G7ARP!8@ z<~(3gQ@^OI$TUCc$RW*luNQOYhyIe|UG!$n?T&H_)Oqy*;uQr7?L(L$@}QejUX!E= z+62yNIsxCWAVSidR{hKCdqxY;yN_Y&H85?bqd*7S>wy98VWsc({Py>-4sXmxpD?ZZ z)w`Sp`vZR8FDAdt{$js^{7G}xdW$B-anS^JUwSoS7^Uw%jT3#V%PhWK=Bt8fuRGpw z$Ye$}12yk0Ozf@K$_&z5j*0fo8acNB(#$(NCPP88g+^8SW#k#kWxzW0L-o^Tgk-*BaW?Q3ud<%3KZk@&8e7h9T_(wX@W2ZG_KG*lOS(AzNydivD{73)4~GNOJPNbI6`&)P`F0eQ z=$a7CPF=9;EgPpf8|J!G^-YOT1+RA) zXD-+Hwl!dp|7hU#eiv}WAG*&C_2soy4xMLYIEwq4C@^?T#V20DRTmE$5AL1x)sx~@w zR=Tf}`t%kRC!G;`%(IZYmpt$8BvUKzb5m7IqNnp{dSf`Ro_b(dhpqn0Mh>%7^n&`m z)wcWEmZ2cOK=3*__LB7m@Cn0cRRg;Nat5V8Xf+qPb1#Msgn1?_&oZdSiOmkvyT~}$ zjaqSm@v4n52jN~rH=l#uX^^yaF);tA6tg&+P)J`ZQBp|@m#i7)Qs4MlVpam9`)-Y80;k8g(+c<#%W!A}a4jNzX1#Y3&vqUAg4UJoEPh z<{bjX&sQE`W9fys?U)zoSGk|v7>-1hn{ z^KVnzB-HZk-?Zh=}J`JVhHioKTEGnitW?b7yke4R#qr(XqH{7h1A+2-9$c z5T!N+^^<8L<@AbiQs)z8n#p3bb!A8uMNbvC!G%tJtGY60<6``zg9->y&WtQ@at{iGfZ)q-CEO!yX6R2Wf>5f&h9 zJuQ(=>{~Qiqt{eHwujX^gYRScnKhWj4(CkV98CM9rklz~S;?w3-sIIL(uGp2m4{X|+Y8BVe5xYBcbb{?mN<|3{^zTw*Bi)Ete8^wl(g3vbD zf}S;;;>q!Mzk#_P&io?j4*OX+wKJ)u4(jE*x|xcoABp*QCGj}VU?j^Bpk387{5J|U z^>0|X0DN*dS$_EEi+^S9`GU|E5^#F(oOu>L1Hw%C2~9CSKbFfrRC-$grIgPl&bczG z!T%OKS8Ood=DFEAH%bO6wsLh|$j>($Htrb;!7oQfVg5RwFi0=IYU?F$`s|I^E5AX{ zqIGqe)Sr-!Gb~VKGSP8qVY(tCX&D1C_h-h0zeICNOXaVXwkTV3<))J$m)>5>^PG5* zk%_k&+_Lx1tZqgUF}B}>Q_IoZMUPBoj6?WO>ZK#5%RV^nMLuxQ=tqs7@Ek!d?Yb-i zvDn5Nn0IOz-VV0f$sqcdktBs{mmThweLB7z=Q-6M*(s?|}%_<@MKgLSSoVnEjJysFqwH=p+Me=3H)y&7# z=C-x4z(`Vm8#0q&R)H8c`uMAe+K=W5C%(EmzXwlsZHmAiu7&55m+%6x1Y2NCKF1)g+Y77-+o+fUi+1gzRd$0Qg9`f!7 z%LSiT9s;LfRF)p}qmsML>Al8AFJ`rJXX5>YuS?Ba2+Xf-g-V3OD|w%-AHenF)X!$s zaVM)VC&c;@Iqa$E{iT(7D^xh+Z2YzbYjo@CERZKo z5~vSn(6+`ZG0fF;-JnzXFXAJUEw=d9b;2;Wxz@zF6+2W=d*RP&E_-G6JrOf>aA>(; z%Yd_i9g*u$DVLD#ChF$Krj~ZWRcC&DM~eBynyZ#=h-@=AWbu^C>s9}rIUeMn(%VLH zuXgX6ngmW%k=-l^xI+#P;2YF}=s55V^K;t`$`x}lj@KFMyKLFv#$r)9;Ery;`ZVa$ z5;x~~!Ly-f-AVmNT@4IGx*M@VR;>5#!dv`X-Hps;pqIaIjh`C+j)V=K=WNg`5Nxh5 z1*TGNOPku(O{2Bx%poes+Xmn)mZ}c1zKow9dc|^=9f9>(d~bMw-fGBqk$4U3*TWB+ zt{DvS+kwf#~fTm)1tz2g!H?h=iTyc@kndSqPWj1SA2O15)BX7Gf-z)ZSf zL9>-xiu*Q>J-9S4M8xf9S%~c3065;~sLSQ{CWl}T;AuL8N%yhq?Xz~rR0z<882!A1 z&d)r)KMAkr^!KZ6=iFo;I93tf_)yUb`6Zmt@D#UKQ%-6RHp1K4ZqTlDauFULhog9y zSV&y%WHTBpo`6dl@XNF-bu^Q`rVZtz`Bq;K@M9yM+CH}Nqy#r5I9()Ow_k5uTN2~9 znIEq4TrC&<%dE7`Wv}_%Cf#8?$2wieG@SKC_lkxB7&XXUe3#xB0blGM;Mx|1qHrP= zr>K31I5cuj@mwFb=K&&$?#r-@790_EWvRf?JVi{$ZH$8`bEC0 z)sp7(kY0l$BU)?B6sEHs@2q6Towv4zwVJ$;qD(80%p8#$ZPDn8B_7)Yz@oxB7*+NWgQJdj0Mg8oZjAKI8$iGbvxo(Pk+vCF%!FXikRT9<=+J_+2i*X0kt6G z(n}^!2ev5h)%-?91YEkc2D8bM-gHD$(DI?afjHS|6!8AehOsWowY<_&V_-@$g`@T?6+D_<-wHn^yLV zna$I!%>#I6r<&laj+-`n&hl?r|a>o-6WXNr1J4fo|AVcHe@3I)Kh%P909gL$d zR#bC$(r_*}4abGMloaKHuF*BQHWw{>b!IZ1>UBr+I`XWiczwbQ{E~k6Tr1kG=ceNR z@VHPjuXeB;k?E-AZZFKuMe1P+1q4X-zY|VPPc)a+b1vNk!@a^MsmM92SQA$-;La8QuFNN5b%Q`g%0ov ze-}4py{eFtX5Po|^8t{{%epZx(<{Y_=^gzU1IKyGwq&}mvlC;|kx7XYk5+=-I(oWK zVv=aBMwi+vrpFSWV^7qdZVjJ6PyMHz#4W1*UFnDZiu&9A!q%R05dWD|x!c119mKo$ ztmGWS2m#)tZzk~N;nhy5=GNrpt<+FA7I=QGU$Lib_ZsUNq6V~9&3yntc#5w%D*-wjlGbZ%zHBWTbuG- zIDP4xggFjVF}dWM-4+v}oLb{COf}$0(0819;g+$_@?C~MKkBY zBrxtq=}YZb%w29oOC2+%qACf7Yp>;yPvX~k-vStb=DY{|#yr!2N)}@9b9YAT(h_cE z3)TgYO8#S-VwPTi6?D^B^B3RyT{=NGcyEPxXyOu0lla)JZ=PaD+0|gV}ZCNx=!5&l!$l956xNkQ2*u)t_DHO zrf30*wIlD4Pm1xZZi^!KN!AwifT7-OT*bR_5_%cKbY$H1A-KQN%CT;qZFo4xB#7Kn z98%!4Yw!oyrQO;YH}Ct(a#~?_+hE*0!mH@m36D;?k-XSxE!y7yz;Ja}{|IF^-&W}m zz}_|`=+5}PbZFV{r^GG9p{|(TKXo5X4wwa(M3bDUTQsfMRq{Uq}{4T6MQ)X+`8DB0==Ir=B!G~2UM?qobWwN#lVuCH z4bpZeJQ_g!djp(YRS41584wP|Jnnj8?`7lpjql=W|Hom}%5Y30omj5#La_bd@ypS= zEDAN4k~PPaX2BQe-(&HH$FzLH@vsNJ+n99hsPN4otnUH%B!X0PoB68Ib#%MS1)VfP zL-_EoD0&x$-1{cnFYdc~7Iy-4*Ogye(X_zi>7Qe9-`#eyQsAc3ujf*!OjkzY54(DH z`)afWwIUap>-G${Vp>|VX5@KmbB}{ba+$Ncr?z1DD(~KFV5<#RCn5epO9n&P4%O)2 z{Xgd^&Pyg2TIR?scqE1klU=Kf*%8mcr{#tiY@joI zlS)W-nW05o)g&%3|J5^Zp{;ef552|vKvQ?0^!nbFjz^fK3W7cYfWd{6zp`o0{0X=C zLTI0F2aD?`71Y;EcMm`7a1-wg$HLD{iUyWqF2R*}DBrtPg5v$#_v-riZb$;C;ME5i z#V<>7le&<;d&@K3E&O`G-igACyK(MV;?IsJ`u!#$w_(AQFI= z5g!7&g3~Ab{_fMOT9p=Kv`x>3tXR?J-9mT$?D&}=)Av^3adUK2IT7(G`jhfM)=6golG40&G~j+<>;@*mzhY4r%uoP%t$2ozb%vG~z#K<<{Y0bHgAMw%s`W*K)}l zI)JisVy($msJ+00_MNZc(dOQsWDK8;0z-_MoTL=ytnud2b;=9eZz8PgAz;+-CoSp4L?5T?$Pg^DVFTrdc6JKbbyeBr z7B47Iymk1pYILz(>d;B^3E|;z=<<$S^bH#?!h!&L~-WhjQ#kr4)Uu5!N{Ch57!N=WyE& z(|Lhf1^X@dIjZ05GZ?#Ys9*ZiR;rUeH`Qynuv^c{t%suxXVrzRk>tT||L&i(q0E)& zaP>Bd70LJs&Uo-2gBC#`YmL}WMHAe`7tcy3u0ULEwJoQ7GN&ENM7?O{DZL!~ckUG8 zw3A!rqIhRa4dH7j85bJpICyMrzIP3n&M<#b>u!yG!u_b(gNnkBIwczzV*kc~?6XzJ zr<#P@8Mmx*1!w1{lM~u=JScZ3^H8ziTGTYtB|hCiRkUO4kt<&#f=?Ha7)* z`Qyci((bnePB!WN*305u(rli{9bV4>P~S^11LogPv0RN)O8tj+m@e(<1IxxDhW9S3 zg3lQ|lQp}a0+*_nm@bku;hd(nJzXTcPP+guq9r=jsz<96Sxc?12edMiK{D{3#%x+! z7rOMXM~&P_^{&!r_>mCidpzJh^rsJf@ZR_i!D+on>o5Zg#(S8g{fOqLV~P!G4RjP; z>PrVs(q(wBH03H{q&ci+S`_vJNPJJI(V948(5>OeA&LPpWm5|UmFj|OKR&&>xGSJ0 zxTZneca~ekmQS%}&c}*1H=%ci!oP+4HK^^`yOEQ<&~6W1Y2H`BZ#n6eZCgdk6%%Aw z59*r;Wxa}h7>3sxoi1z9=)NuY7MFOwAFt?hdb^Kp8nk9+TfbaBN^~(q&s@3N)Y`0f zuelU?IIk^GFm{r224S!h~IV_Wk zfJ>AW`dfe+_#)HiK!Pg$r{CzT9!$7ajh2$S%*M5%MpwT6`RM_tMv<%HO?SN}P`3SF z@wk(NoEx&`?3|g%H1w2(HcNvCq9(gsTRv0ejP;EZ+6Ugeocv z$1YGrJGY{x?;-|RB9FQLkk&n%> z^Wy9- zB>k6>=?JKMsFEj9>HLQDKByUkD@Fc^@pCInxAk3``DP9f^`YL%g0q#d7ISzE5a5L` z(J$5Pu=!6ZR%P1mjII0#6y4X_Pv1g9h7R{c<({1%a-^U@BXbY7wo(75d=1lgYH81D z;8gJGFi0q)HR!nqlI@CE(2W*y;wX3j9^@HXVunsK>1d)~1kXHRt30b=DfN>AE3wlf z5>xH2SutN{s!zC3M|;6P$&03*E}tJPdPM@%qpe@7^gM&ytVsa}ii2uq1b?xU5HR@YH7$UfUa@y9+^s-wOp`7W%b z<%+sm2o)#J8i6AjtHQzX4rQF)=^muu2`szay0@b(5dLSVS+;OX`pBQrFRU+qp4Lmk ziY!bTL6Iw&5BU1ppLu&gPbPMwHrtz4E5}#r{g&u+<#=Lv7kqg)&uG1XURfNSH<+P{ zjMzo;9{_NJ^|u+Xa=o3CB@$_ikmYUX1m$XKwxbib?CakI-KK^%!y*5XWQ^HA=pMVo zF79v==Ah%4E`yfX|LsRGIj|YkJ7(zZ#jNPXZZs~{u8dH6Ph-jIXs-)1M@-*numwZ? z@HtPXIbuiEytd*yQ9liSZOW_9LvqyW%v_)M1^F%Sqo_wqU*|MSqpi=d?~!W$-Pb3< zr;)cpZx8QcMoPMI<%$epBhlumt;ZC{pLWJL1>~!|D2p>Av3&_8W$DPf%oDkk`ZC;@ z{y60nh;k3se&XV(~_VFD`~TOgN|=O3SDT5U5e2SccbspBE)2_yTZS@n2kw(D#(- zUc+3X^E*sMh02JazrenrC*IsGE>HZh`n0ZtaShW(c-px_`&&Y(jospN&2GA+Xgo;Amye7^ z!c8RpouOVw4bz!n>PYuhXf|-Oamy5V280e2x=f$q7Zu<*e_Y4fnvoFWhvK{Ne)Q9k zYE|F{wq~_bEz5*mr{E`iF#GMt15YUzOu!s_W5zA^s52|M)X(nAS^v#msac^>l{?vm z(qaLx1GtQ4?mBCd>1q~l5}1Dp_?!iqxI>Bbcb*Tz5DD16wTN^lV5HG-b2k#ez*$6tYGViJ zcTHanuWM;WtT#OX*wge=z?$#-YFZMC*IBKFNnrql?a&I~2jOP|BpO1y6G|N)?;JuU zX){UM3L`X&zG1f2_$T#F-;(JVGcF#r`jbZ{M3F#rs*(z5Py6dhgf3hUK@~NO$Oi?8 zhvO{VH%!gy*%!1@OWUb;7h#I8c+X{joeW#DUv~+zV89#F<1+;`=m)EoYU4(ON7~b( z``~ki?VsKht+lOkG&y9qvO%S6!7cVK@L*FQQ=`(92wTU0k+VWr#B3`&Bg)rjcV9zp z5?ZjYh?WGXL=+7u@bAa`4yhy^^r0u?x5@NHV zVz=mkv0~E5Aq6+@kp^sX4+x@F-5Jix!H!8RdD?#D0IN%-b1!X1$cH3lylc`-pj@$@ z@_Bn%b!hf8YwVb&e>=_4=(oXPMqkM7IAy$LC{p$e&Ox_KUNU|*v!Rf&(Nu2LyEyqY z4^6y~=fhvHc$cST&zB!39iruTx<7PWbI620BXt(+WFA%`1yfy^j~_+Vd!K{0oOwc}>ZzgiX6o8VRgg{0OvdugZfQ%w8F6RWRdM_-uZ zk2w%yHc{&t4eaK^WxTI6ySa=-rtkpCL00FW2Tfvhre~@CWP4 z2-z_FbTZ3&em&P<-gP3Oi57|aVp?JU72v|}QsFnBZzBby&7No6z<%m{?eV_Dh?C;T z5fDFJN6$?OoPQuUVFG#aM&E!ySfm+>65?yX(pmh1oX2e!{#WLsUys$yY>PJ)9UhG| zBN&=;S}Py)fm~tJTjf-fE&6f9scE&R6{K4_e`Y%k#Xa)6*+`J_w|cWTW66{Vuzinf z>7S;@DZTCYIOHOI*=HF@_Fno{Uc!xKy>xU!_9xwx+#Lv1H;tDos+e2Yr@BANwxbNp z>aEu{l#jRzZ$WA}O;ea!HxLMN_x_(Cj9qU3!9d@AMomv64R9?abpTuE;=!(HRW8G} znT_W^)cu;?*xT!sjU8zGmXjFduLr{ST>s{8)P8fHAFmva-$cbK*PY?{OShn7J1HDwGpm#CTbf!+GT znj*Wm=7xoRN#mn?`)-h|P4xot9jkO;h)dlU18zc7bM?P?Y@h4zHYol!x!7SeOoU8D z$Mdcx9`)2`?$g@%Mx)n`h)O#g_tILsoh>!KG=7fhcgiRV*kbsV@1AQYHBwt%o_gO? zwad-eTLo9M`Ui}RXVyEsM24~tl{ILLNjm@$GE)B+^kjHksXDydXf0-!Z@nms@Vvuk zT@I?reZDq<7Mbl^dC49lw?pCZos=76FN@SnBE_dO$eM-O4Zo_|8`jkAJ`hdV+rMEo3 zZWbHci zU_iASzA0d_>bHQIStBvg>Q4vA%_}&IAshHTT1-K(K8*TU99JE zmw3_jiN>N}ap$4l8jM2K-;ii=xEvulMbUV8j+>Lsk_vyf+lD%`=dKrw7Szw|__fyR zpU#yFMewr$f!~Zq)I&fjzhb5LWQXLoDw2q`=_YyLX`~5Iht!sGZR8yn#p!Cl zCEl2&soksnt@&bU#n>h|$s3sLa=V1eq4q0BO%^U|QiM4}lHWQ!3tW>NZ}{8fliZW2 z(l;-N>@mp+4SmzNyUPE22JF(D1!t2vWAMG|PlrByJC6zT>$qi67k-74g~tIu45q8w zOa}swaNMBpw^$${)||19`Z9RlSUc269b>aedYlDSUlcqY4;VmsT`WwSC^F6i`pd~G zu_(1`!Gct~*8B%;f*@OMKy!rM@$$cXsl>dK4L__PTZT+6gAN3DsV{Ng^&Zmy5KRSf*H)oiN@SGDD5}Ew(%h*b#7OWIpFILHF&*UD7>DX~wx*hnBHC3N&P0(n5bd8Di`+ zSo1DGujWI?RZyg$(RsSZGRH(hbgBVfbfPpL>1}jtA3V9RK)qjDD^7A4b1me5>$jAf z&A89ijr4I9+PM~vE=1d?IXwnPJZ<=(gUsKHXBxE{i->7%Zc~eaU)RiTtm#l`wK3zdsN+iw;;!u@4dlo2-=D@!mp>y93?I z$BI!bxiL`rHoALRbZt#dk#D6S=*WzPVclP{?7qe_uoHb9eigHy3((dVU0XEj|Ivdp zWtNmBJjgS%>T*G_fpB=q`Ks5L^{E^#fQ=wUva#D7f-k*Je zJLcupw_%QkRJxXRqtsYC*MJ)a77pvoj+u7Z-29fNPyjdIOCG*re8?ak_hzy-d_Ncu zE>vchN)z^Vn~&{{Th*Lp5YZG)JSg7y!w|5T=PumtK)3eFHPLwy=#c~z_1sG3k=WQ4-m-kip;1m##@dTr#T@wG+UZ9^O)YO z)+Q7MeVh)MO4qs6kBp6vFPXUwT076UrHIkSrMa z3+7AAH8h)E=lQ^$%PW|i6X0ocCib=WQG4{(RT)PRRN+WJ+3waP-u~VVZXP4MEN-Z! z>@_Tn|2f}t%J&QBA1}p9__%H-bpmRG@}L4fy1vtrm@{cfO|}*ywpw&Xzcr{X{VcDW z=QP=}e)9Yv#m3QKaMyF9hx>7Z=-~%uaLsdVo69N0HkVTyb`ow2k2wBEJ}r`r>9jtW zOvmimM_5uw#ek^P0U7JuJ4n!21^SBl9o-h#2mzsn;MVh$W2T89oxv}VrYYPF_TpD- z)-(k{y@?M?b>FS+g{D4_2P1BEI;bEiS-|t{9c7xx<)f(j8WWc>_ULwLl4CDqx8!Nq zS@Ey9`^aX=9_skl3Vr=WA<(04+x-z^dwAD)@9Wk>k4D{{a|M+CEgHq!TpKxP{KI~W~>Dc6{SoK3{EO1r*PTP;vNa|m`yvYre%-*u`Z^MzQ*!6Jx z7yKj?iN9w0t&vy%7I4I?N4+`LW9%PF4u>r}tUur6D1o6NJpm@WEb2dPQly%*wJVex z$*-mgs}AUW3Z(bN0QnZF?ycYvQ9z1{V8`{Ti`zU$DVj9WmGO%BB= zF}n7&X2stxqGQe#dM=K4Oof&kqR6(n!G3yE?%yR(pH@8USpen|0gN z>9&}SK^_4X&s{UIv0WaXt-0rzK@IkO-;NQ)p2AMRTF)RAI zy4YxTXoFMpPy(PMvc^0p{7NgH=LCqY#vvntwx|YE@YHI<7?iV=Hr8IJ8@Wl@2kmP( ztP>MY7>60AuTNy-z?B_?BRx2BDM6pghfa26_qqYnpIN+@-xd1W{MWhG>KfT(S7@HU z4{hFn{Mz*+;BX(AbHWbsY^27Cy;kp+)11vLw}lCYwHnPypOESV-_V4qBdW!2J(K$> z&L;ceh9h3CcP+WHcS(HHtB=Ja_h-^=^E~*2ha#2yY4WypUEXPWke&m7&f+`}YX^=2 z0+3nwTn}HzWj(^A0v1D7=_+GH&Fl?aYy~YvYN$Q~n%!8cm7qI#DsaGrS0UfQIXZNr z3CHRljc}Rput7v|(dM7+xx=nb@O~}Ob7=|jBR6`&1zdn?B?km)0fn8Pq|a&x@tOFD*4%KHT>EN77=-2f~6m6l=t9l*>)2o`D~-+hmO-9D0HMo@ zJ4iiJAQ@Lv9yvVK%@919^A-$cU+dgIR}sV_LytfEiSB`S>@_L)uG)<{ICW;$DZJA) zdHfD@w{io9rc3$xr9auGxiiwxz-zDIdjPZkoOFZxbWbXaJF|eyutuQ|&;InV9RF3J zl8$%B4)vPv!eU@@mugWs{76NB$M&V~jIUhTTJz0QlM5k-9v( z6+H{yIJcU3!7c^2BFtgDNiqp2oZ#q*T+`cjSDTrC!F>XFtPYdh;qEu}2R~>V>KO%= ztDM2RG&96CeRwU*&&>50>k%QE)!gb=*41~yVVh4@#E2`=8ZR0WTVV%iYumNTZ9l)z zc5xjQfr-(b0NCb{(*S#5T4I&JwRYi#Sk}&_f4&LaY-2Lijrx~Tr!9^6jh|>g)Fy++ zHLjWQ^x$E!sMCv%aNWk?WZle_nEPP`lplk`6edp8o@N{uuB;gU^=OjP$gX%0GG+#A zgpAqOR@puj7aMtzPsp;y3p!5|PpL`p%znUUL!sUb9V^?MY3>H|b%W3!IfF-bR}YFF z!&5yny7j{6e{?6y^0Eg-tOtxB`_@5s#A)#tb1!o|XFu9;xM(yq(57B8_Es+(B_WrC zs>qf(Pnzkn1c_*xBF-3j3j6hYmrSf|?z`j4eC;l3>AoQ@pT31y!IRBw3Ii8r_g%Lh za{p!OuCn2i+>dHc6?;6eirdmEUFUFR+(fi; z*r#=R$!$zDfY=c0@CH~Y8`eRQ!7dHfe@6vXCl;{XyJ@WdV69}K)gO_cp_K!djXAQNz=i#X^j3Op4RizLwYZu0KuPuC$`b#B z+NG#HCdGpm!g=CYZ@1b^(?MK`y@zEZf#{8)Bhy`e=R*E-HJTxFk|ugZU#Rb>MggVR z4*d@EO7z&^Y}`)F@?MFuidv=iqaR{tk1?^8>}7Jh%JV=C_^)9m{RE;iQPkw*`;qY4 zYB4`*e0FCbJf>=~(}jSy{Xplvq4;r&8j|9vCPRe|-zdIBIl`DTI%Kn_nmU$gP$%tS zPr4Ui*>35t;ySMyTmVIxy^Ql?u3#S#oXxLyIcc?WVWWPHJUq_8oZH`Qd8=WO|Dfo(X+IOeY|~Yjrzido}C9_|Y(f4`s76|52%Cr`NjY_rVEW zA*O%THLhDp9bnjEC~H;yuhD|8)9-dC8C7zHigm(S8YY?e#+)?t^J_Qra3kC(=uZcM zJJGL|C??AtjGLPBq3_!mcHgWfhO+Y1uAk)xi-R~6@U=h_>>9fU#xZl$`j&7!v$|bwyFxCl)0xWMa`XmG1?M+3!!3(K{09KIRMZ6;Qilw z!uWr(j#&r5YRkV)e>-b=6$TDNLVhH{V`^u15p0e4V~^CZ)IU5*4>ZYo?C9p;DLW0$ zQ&(feQw!!f*;m@${`-^=sqfo&b4?kXN>8(%G|(vs-TNpx9#uBsaz zpA*;Tw#2rJ#b^ZS&$f21AI9;w#*~elXplcXb1woS1Tqy7(5sK3T$3E`**ifUKFqb2 zAWS@TVce;RJmxK-9lU{GNaM-5wo{ciSUxxp@4>L=^oqtQ2)uyv9E&G6%rVe}b@7 zcZjrBUm>op9+3bq=+X%HL9sQ(llXHcv-Y9MS>IE0dwK;{*H^CuY_h3#w?m&ZVukKp z00gqeT771}JGSYJ%*%I77V~Ly@k1$yn!Ls3mFTW_n5G6+74w_lt(t}(`xC|>+lQWp z-ix5}u5eBg4=~?=AE%zv?)6Eak@_FF=p17W9|4T(4`j8A;>|PAIm*w2?8zYVPNX+< zV5Fz7U%fo%Mt8m|)-5L?ef&b`TcSh9AA6}@9=bq_4@bD%uPfBZtoDd~oQ5O;(vH$E zc)Ho!+(~z{zL)e2`#H=3iCIFq#W@^Db6xjUesrv^t99gk=wC`Q{0?p;+$?i9LP#?e ze2?qm3Y((Go&;9%zTuav6=S~s#SM4+mJ>39Y%6~ns&vzqNCF`J0HKaf5pK2hnHnl1 z!x-4a&gCV35HnrA@}qKQj80keKSO8z*Mu5I@pZ6f2^+D|-Q6fD2!h?+?X|n_wL7su z1%nWj5|Hlh7%&EG)HW7ugVpsvcz=1`&+~lFIp4#61@$LwrtUIx40Rm3#=mOd-03;l zOTRU>NzHeI_MTl+Y5;jHDFV$+ta!^th}jvBO47_J`xR3i~yZ!y@U2P zy;S_Pv6VhT%CbF06@efwO^H{Lky<@=rofVJ>Hw*@H57vOGcpNyNW|jK{@&yN*KVdx zG-I=IdAG3D_4lSNDHocEHXlk&349$e?s>E?`h4fV1?L@4bhCzz_*|nmo8`IuB5WcG zML$pq&f41jfF-(4{0WtpUb3>n+to80W68=Hu?_@MF3Ab5)}+N#8L+RuVft%K(T4He zp~86eI+NR~LSnnoWd6CaY{L!a=^Ptlm|S1}hQP5|2mhzvetuA~+iwf{z0XEGy5XPc z0eh=!F;y8jTV-~z@)Jst)Q(NL(cJ3$in~Ku2#izVLmxGB3<*=`!HZ^}v1|+-1B4tR zW;g7gzQ_LAB+~9vML{&4N4G>Z3wIcB-K&xzKTqqrA9S=%Gfmz)Hy>R;vKA5VVVGm% z_;dEK=^UkOoZRofwF>TH@8xCQ{*(2*A8PW`zNPbtEWppx+QyJa!_KrRHN$asjXuui}w{n##pFdZk43l2vt9yv^sbIV*Gd%v&TW*sQcz@j2o z^nRy^xteLG{`pCmAv5h#>!$Qu_(Q^vTu7ZiNwIh~+RQvPpbn!c`g;RpO@k>BCPRtf zwF`&RodIdw?|yk9_dB-aiyR-KLN&kXSk9dD@rj+HNug1JQ^2{vV#&JhJ6IFvwf1J} z3#28YZKn1S(0+3V`l$7yua2y)sp%*&mV3@_2Q96jSt(-o)P>`|h+BsL%N@x-1IcOl zE&$Bk)a%b4S4|75rg5}-l3+YTR6nGW-VAHu{=;~|Icc**ap|0r{?l}fxm$QgXN$jg@jr&i?XLoqtO$Yjv;-*6Zti`WePJP=EW#ds2rJMTue3XZ^<%xk*C)GhYhATL;q;0Al0 z%&!|=fvh18Gc4DFzsY~Ti8U7y6K3f`F2Tg<$aE~|P&*!GIG>KVBFT_yW( z<*|t4Z&>PmRMuH2AAZqIn!@UG_%cN%%eofZU<_m9zVyTg+zfNJ_^8#0(1HFLA=Zcp zEx>=}YV|y*4&CCZ=Q0X-tUE?ouL^J&7Wg&aN!-T$N1D~Jfbs~qtvx`-BwU5X0{k$C zp-|E?S&CmF?v&e$SqpTB?Jh=guW!>iBzj?&ncV0O?+NC;Rp696@-oR!M4~+p@t@yC zdeZZ~`j=qm%t~EbZqY9@*$)$aC3lWzKOrlNrCXz;586d~{_Ddj7a9In5rZ`GH}S}E zyE%WVWDst=AjStx(M4TGeCwTRdf^u5nwHz*Pd@(z6oq(0cha2}8`Zrb-$9dSW0xv~ zzm?Y~DePkLupSrw5)9+p6-g}e1@!4ZV`o$CBuEwhKOq%^1u;f$?~Adf^Xk?y`?Y4uE;e?$Tb62Bz z5J!Qh5zkqv>}*c1;lAP9rK?n5q_$o>6{fg<`90>U2p3UZi(5y0VU)S8J{r55Sg42t zi%?A~Jm9b9M};npLj4%Uy2bHgZ?E#_AY#C#y2e3{*^A2K($h z(`X4%6J=$#W}W(8He10Pf88_l>-uf6cT-O*$~bxWU;M_!*X_gM4?1e}A*f98F&w`v zX=J+#TNR@4t?pT0Y14x=^gGpZ6kRiyE6HMAX^rJ{F=73cybq@5nn^W5>f)|8s5dmI zEndemd5T~8L8^H-02J1cpEj5}el!b@zm0Q1u3hv-Wzl}uPSJQBzE64?2{A|gSUVN@ z?Sk;0=Hl+-2B^sw2K%zbO4AWH;2yv7j(3*FX&1vP@UhM>Oy8!i?mVG+?v5>Z;`*p- zD+Y{zKCaZe1)ah^5RaPiXy>3o)uusvMvG8QgGo(;)NHx`nAAXTDa_Uv7XI<4lrmIq zmpIW%QQ%Tv1``k4!^TSu{GAZ&c>YR4W57dnPS;hXz0uGQpnIn(b7W)3f-Kk`gsng- z^TzcT+hqat1V~HqAMHS)`NIWY&D2kgnHHQtmvHIfJRnDDB z2hr$E#^AU`8u^51qk9RGFFDX04YFm~VBI0N&Ds26zJZ;_L=(R1K~d?RJPF2hiwc z+R^g8D)piX1U<|h)aE7O+12cF(reyrT*Z2YT;L7$yGdiXRStQ72`?!AJ!pkk#23;! z_1;3O(+|(}%PYv*xwRk#va{zybLTvpge`xdfFtPMBFpWZFg(|<_s2h3mGY^MjWMUe zPJ9!>8=kY_3EY6~-i9=M$&Mkl6i`*8-%)On+OfFn&9cw%VfMwT786CpW9ED34ujV+ zBWRKWjI|J)7`SD=;Ia=6%Yo_Aq=ley@aM54^$yZvWBb`{^ZQ`$e1AIgj5ZQcsK%LR ztUl9nKLqi2%cMCzd`3rC%Ni1rVl>BHsJ}*x874P{s$j9#%nlE1GWn7?kVfvM8bJT9u}{=L%Trfn_5QbjQ zH*pV$g>Xlw(24kObe=`ykEPfBo^?0qzAuDoB28Zc-bm=!Hb#xGS3eCnBU`0sIgut_ zrmszVhjUj5GDd?RbTet3s8YR`MbQN3jx9rnh~6ASnuazc^y^H~t9G~oYC=wsye5~$ z#y9!P*N(r}pgt*pk7Jr0 zuh^^>M$aR<$hQ>9z1wB~P0^+u<_-XV0eNb@@l0vx>QAJ4n6D)hd^g-&H3ynf9clUq zPXO2SIuRg%h8o>Z7rcY&DBz`ON%Beq)6TIm8SB053wo>K_FzkRjxkQ}qFXWPDc~Z{ zeRoLA*wCeKZ|Y1&4Uk_K6moC&iu*Is285w7I!=qEUg zm-#ZUHv4qAsN|{)wfk%?c&FW6c^J*EXs~TPf7wjpn%#a4v6Ut-yv`a+q@7p!+WTW+ za**`nq@S^)VuL1My&YEB_y%t_@oGwky~~`mBrXGxVo3Q$gpO;*p@;;)fX3e$5qJhM z+;SyXpd1ke7(@aD^Bk7E{$+WX1E?4wi=haWk9kR-y()hT$3QwBgf=yLP_pxLYhR&I zAy`}NK7Yy}x4}AM5&aR49tUjRIX@??;6jf_5T6x*CD5W`HmVrDlAkMdfyK|E_1YwD;3@#n#4Hp)@|E}2Bg zRbMu56@ZhHY+AEXx7-Q)!M9{FI_a#B({1(x1W2ydw^v(3U$VTP~p5094Yyx{W zB-h{FiZv6|ztU^vrX0Js?j&LvyxqH5`B&~}e=-;eGn`s(;jEB=E}^Q_Ba_!>7K9J+ z7APaaDJIxSC1C^PK==BJu0#jU_Q+X4m+?zu>|Ep{BM-5-q0{x5GakgW*t85fPVaUA zQ%w%zQZb8aw6oVKyxAU-S23^a1P6rKHF%;GH`>Q~Mc5^|>^PdANG79hb1Ow9(wA

z(&Bw@yz`*)_*aPrm{JW4RrSFug$#CFL-GrmEhxamPb`;kPSpEIG4;8t6 z**_9=Njb!qwZgpl^ZL1QP55|^#ZidQ^zGqq9mSd@=#hC_#xG9*-ZMHIxYWjyQ`G07 z^O|Ow_swrG_{ngtjMMz+@|%rvZ|+>vmeo9<7p-ambx0Z)7+n^|NOWL)h5bR-Cx%yr zdp!q`W3KJpFQ%yQ6X35I`>X-JbJXib=J=|F-?+_nUN*zXX6H4?LGyd?bYU3F=cfiz zUGEA|wTNSO;329ggi=LR-Ro$w&X{gipX!Z-M>QJhA64&YE_J-DNGIl)5il`{NBt^8 z)Dd^G5qhVw!P520*V7oka~uY2Ye&UEyxC!NZ0J|V@*zV?k>P{%Mci%e1C^`fo)mI} zjbe#$Z^&K6*&me9E@j8uhTbRIq9z{5d)YC5u>LW7o=K!UGuq0&$0=+6jp6CBu7RyV zvt=2bxhROf_ps^A-Z2yAZ`>jQtrz}_qZ>EAgfy*i5UH1$h- zsKJA}Z?ol=Msw|hZ(^@1!d*I?r>yo&6=ajEg?}2o;`I_NS#doOJ^X4#tRWjENSXv>I= zW2)^V!7Hhm@onAta(PUIY-rfP_`t}sxnHy52^9OKkqb@|l4DoHC_PcY)AMNHO%Y?iuIROzYry-(0Snhhaf1RkO-3nr2lm@{vY zo(1cL@E&PKBi^TTF*gTNDx}Gf&gY-p`DLq`*7uqG>gCSm>%d)ZR1V$skp3~#RfKY< z5;Ij2b%+4Hy2&qju6-RW4A*L*@H#l#G_sC#{heB2R1YGq!k(=O?vqNOCesK@8sJ;Naa`+_ftbQ;e#s#A5DYk4#7kJcv^f51xLz!VP;0NK3-sJ`i>+8~5AFX05f#=rMxJz3B0(Rx`My(n~ z?_oK>L4LMmSqowT$lDwq(D_>sU3*RbG{hmjl11;nL-OgJfYuw4zz~eg~MiAywNdR4}#l3k*38y z6S>duC-kKInfWxpqQNzV=SgR^2bGNrKKv#_d2nr-B~n|-WMmkf{IlHXzviD!H#!=u zlE&U=)wsH&zm9aHcN8B&?!#w3du{azX_02YU)O0w9CF=4zbblX_#Wh5H)KkpR#mZNmns3^*p69pw5JRE+?WYkHDy{4tA-h=RK6)h9Z3R#ocdv)7{RE8e0voBW|}iD_(GFxuqc z$~fwA5}LyW7!AgfI1Uc`DU6}Zh`jd8*(QBR`wiIF3GmQRuB+WU=;P2-Ye83oo@o)d zqH0NqeJV<6-(q&J6;sK9<(O;daE&hJD;*hP4@8n*JkB@D$s$KsD)gYL7|HPP5Z@p& z)qadbjb6y?@dxh*?7@s;7~p>dokd&eS-f$*H>!hdfLRT9Fzy_X{3DeFVgwf&^rzuu z216#3n2JPSbHCo$woa-D8wbPTa^C~JGB@h-r<#?IE2wH0C$H!}EcXfN1M^B(2M zFL7NuxU2KGc*p2o&f|`z1&tQ;9oSwnZ8rQKr{QA6-@BJO#xtKS)cPu|J*$+)NYp^~@jW=9C}OdoWEldM(_|b=FVO|5g+VBuv?0 z9xuH4unyKe;O_~(i{@?)Y zUFTIjSMl+()%+Kd#-RjV^g;x2+{}{$wrMqvfydDh=?+Ci%R$Uz=`C3{89o0%S<#_D|5e10Y&Y0^U;T^Mm8EcR4^5fy z`e3t?$*UD-x%-=68}sB}b2%}fr1?v3@n8gce_n4~t;wIp$wxSro|LrvFHg3zSBP3P z94TF{S1D-<>+gxsTQemvaI@E>|E4iWjhz^o9xD3#teP^vt~8Bop)c?)RIObVtQc%e z*`Pl-1jabeKWL7m?htiI!Ud2FK}g6}QFa zxbH0ky|Ij^(js1C=T2%wNp66bs3yy3W*&c}ls^HmjA?iZmx#AbY+**M;i@iooSBdc z!z6puNxb$E;SXusp)TXmr~OmiL&F~R8M+!^O3+02*-<^BTd0reVyO_ZY0Q_o->#Mw zXf;QPmcO(9<+Dc6K4B`^tY2i@487=cmab7Wz8kS9v2A}OSWt+scPF^sZ#LIod2FzO z+;wfHq2G^v&#@f*rTe7n24>y#G9{!xqMTtB&0S@;Ystd+9sp9(GiOAY*&-tfu3*tX(|GlP4wHq1 z{gKp(0t4`T_ zOpZD~?ARcvH*0BgojA(rEt*mts=pVbXZ{Y;4*QPYY4IdA6DG-AVri-Ix5*H+eXuh< zGy(5EPdy@dmbo9b0rSx~*El@b@gvK$(RNLpCv%4CE_sw0F##eC*%e24!w(il(Zmzw zqq)T!#0~o%5!8tPSk)mN?1SYEj17WhFuL>GFg&okZUmNJYdTvE*~OTeQ6dB z^?UbZJ~p#+6pSBM1omKy4oIle0f-GwuZ%CUXx2xlHo_5_BiQ5DL-aOCOzrJxgQ*YW zhDI{@N%OrzM|LErd&YXGn))4K1b*uJsACg4g&OoimR+eTW%}{+j7GfFh#AmwCnfOT zHbH&~vXHjcy|L?j$|G))&|Y?WfEqc`9ou`c`z~;CQCV?O{&R(uo}90c;W^XG&Fj=| z2jmH01W7?clMmvas0h!yh%~jT0q~ zFHp=Du7drQuAp-QzlEQ+haf$g0DPTyoN;95pt;bcG>9ab*>sA#-1T zLaZ=fZJUPeIMyauV373Gcokq@-f_xw50fIsM@=03@wL(#iC|lf)TDnz`utrs*A#e` zyq~zz^>yJlCD_9=-ptc%@F(##FoJ)|B*5rrTUmv^uuPUXp2v8E`h;G##?2)TPN>zN zaF#!)eOw$nw@v;pL2vY5MGbhnV)M$=Q%TO&hLzH@Q;(F#G{bPmhE@xf^nJwRI9-#U}%9?)Q ze`u0m!}NXw8^PEBf11~tz?*bN*J-~+5oR&dFBRoXxOeHP=J!s@xKUel?{{#vLH0O@bd{@XGm#yRwWypv^!ckfQrN1oINnG1@oX-RV$vqI=IXI z9(lJ;TT`xlJFS^K4Ii0s3<_GYw?ia1B$_&q5bqsi_K$HVT-Ngk8!{-#@jkPu=6KzN zJacS@vOEw@hu{;Nt;*!|6V|Ql|2izXev#ro>vTOKd3GO-$7iK2JBO3)wY86pcoA;I zy{J$d-D!;3Q9(r(8QSO*Yiu%+GHqTKTJVW_Y(?MavUTk5#C$ zG2YDM9=LbBKzkc@Ri;^cIq)Mi0XO5_rEZjOZa7ZpLOhtVm2QOJ$?Md;2L?jM&F{-_ zrr*Xky3EW*d4Hb&T)&x1>@HG*;KnXJ0m1bverMPDpx%xpy@ISX9h!0ux7-!Wlt~k;#vrNX-xMcLC=v;lgaJwU3>jU*ehK#M6QHkZ_9N<_lC~zhEE!l3=Ri+hvcp0@AFekpZ3s6 zvLQs>ziQ*8M1Dh`t>#GQGuUp;Q~G)dud!pa(9q-v&ls#_VSRwWq1|p~lyBOFfTGR} zS)VLqjD@Q%dE44JwDEhe)^|e>d=dF&=W9DH@!ymI6kht!@n^Nye5`$LnGE^f`#$Ty zwAI*a#tGA>^JZ=v7!}U;mR<_Go<(Sl^|F4U{X5(_{QUH?o`6s5Ivs5<11qN#nV!xc zEcQ~`^+}xrq~^ILxh?&bO;5QG$|B(~O2x}6Lqodz%U#Xz$adL5Ex&ABZR_tmAMXts z17D&~9$xQ^`a$#-C2TWszf=5u;r$y(9-cn~?8*p92LOQ%%Yn^$dQq z5(~mj`etJh2Gr2L#WpSjccC|hfxWl1spWO)nCf-&cfNbX*COX{enzIi$0p9`w&?{} zSxmWPTANpE6L}#Jp%qIn5fvu8*?ygkgU11ihtkQ{1?lWVdMJH!R*WLG7b8sS5Al0L zw(nDMN>Ck!*a5b8wjG4?7Im?G95_NeHxSpht^XP%(#WOPbKwR?QV@p0cG)XKm5PIT$=d!MN-9mPI_g`I>2Yn!rbhm_O z_NFr$(UYDVh4(@db;%RfjSua$JioDJ5vx>I*psHNh)y40y;S49@gvG^Lp8fb_6x90 z_nvriq;YUAs}K4Mf@m1U5TH+0T!n{eM)dHuYq}*Pu(CJC_9o)lebNUdRsOfEhrQI3 zA(S_k>9DA#>EBDK#}+ODwrbz<4aUEN=b6kNGa4cSCO_}ogS=~{6y_n12)(Dj4ZdqJ z#JbR%>>jc^9Sj;eq$|}MCQtUaBg5E>GTHzeT5q@;kFyjjcp$4%OKrD9~A zrBOpmWvc`4=UH<~*LKcY!J3gQJbd!c`Y}#qZlgSQ{4LBz7h^>(yfN-Nd|!uxmR5HK zgpOWjg7v2WTI}5dkg4y=vyCQm9PU=5Fhb2W`|93uEY%-p3^_h9hhn=f)h{!==yPEH zMNd_$v~W42*N(Fywezp+iG2KP>--*B%wX=wQ}e-@&zzaoi$j-pxEt2kYMP=DfUCU6%nXW>Wlr`~B{fq_?{D{M>jg!M+^rj`|2_F%FJ z%4$!~7ae))d8VL*(c%~QpZvz>PFi^89>Ebe8|o#;e-<_HpG+mIpS}Li{j-n z4|hMScXqwuwe}NhOwx)Mi}$SF%li*{Notbn%ej(nYuPegGMH+37qo;nEAquU+ca6Y zVr>CnBEP5E8lf2{84z6|$mk1yI_JjZ+orvP&b9t!*p>(0g(g{l+por2&f5?mS{K*t0R06q zxQl>~<%xd(O}dc#7v5Stv;^euLrY{OlldkoL&42sJ+B2Vnm_9E?e5C0Je#>$E$)t9bMrB7a=`(@1U@?D@H;yfRCPFItAVvNn~};kAC)+sW`sju5MD>W zM@1H23@)8=7aDN?IN7jFiLd7Y_$Y_r;CD;1dwe{9=PeoVmnGL3Dkqva;Fg4cQ450^ z%=>0+F^Aplu#0S%V6N{jvLL7$=OI0Xh)ZKs9RrI!YV0|__lR4@X(PA+ZT)W<5)xbY0 zT#gwxh~5MrGM#(3(rD!c%E}8n4eMX4$8B27*9ip zfenKWIES!(g+6n~i}l#DIRTd&jBhu@+*8#dy(l&4W<5>MJNz%p%WxWhXV>-2HYFKW z(EGv8m_Cc`7AIxy)R($l>knW21EGd>)`9+6qjRHsZgIG*8X;7rBQx zqWeODj^l#L%Zd7BG8N3TdTmk>0m4#as(w-@M1y5Vp-|mhLrsZlc5g zWCI!zCR?*mtNZE7=e(*p6{(dMDozAF@W%BDls#G%pIz25d&M9UTR&S3cmt3XwJiwX zCROhW|B=l&2lbC3{L~HQ!jO2;e$>ccoX_)eQDTMV6!00!d8xfvw1%!nYUXS(~Y>dLxZMMq=V>lVKC(0eeZq^e5 zP~S(`3-#J?r|C;E>1Jn8c{TPS*@}ZrwW_#oJjNU?ib}D_rFY2ouy!l@C!wNN)mbHz z;VN>+q=NVpXHoek6@ZUmLz&OQwngQw{5nl{sV1b4nADiCkpIru!?}5j#Bo$qZsq&OyGX6m}Y=0EsjM|^ag}`#oMh8 z#CQ%8dL2TNw$2??XX;bcP2M?7eWzyd4Nlz5-?ua$Z0phjda6TzN@&4%9>^l8p@w{iX$^JL5!!@B{8yXFP!ZDKhv?+^OVT`uW2)LH?XjmK!OOl+G@ zw3cu=vQ;kO^SAkyz69ByyzCKzrf>CA$vg`<@wjyq^q=kVFqU{|m;3x0+69-Z#g&~` zbVcSS$wDZ*p4{;wDja*sFLJux=pO!?{6w6B{`Svw$r!&U<5ID|_J}46{xG23k~)&K zas_2O;3M+=%w9MrINxnGm!!S-o9tk(Z$9)J`bxA)FG=A)d9=^1@b1JWHKN%cyOEV= z`tOF{2t~KBj;{zomofMZoAQ28vvz0qb;TJzn^&IrYyMuiW2o^2!}HF3!@zU5hl}0S zFR1zayR~7%pJunXcm{kLh$S}TJh#6wel&O9ahm}~kI8kcUa32la3&k+wY~g$=iC5HjZ=RDr{Kdn?wVfkdST|<@=+V&5+WFu<-)`Z)sStju_bu9J+fvn z!s{3PZ(h$^DL*hG)g|dm&4X-|jv?yX(|6E`t`@j0(K8PE{zJyK?;oIl%3iw3$xm8( zC1_GiM4r0Na$o(u;pg7x0YB)DNDX1V)k(-jh?cT@`awvpmF?n{+w%L^l&!!emcfmO zriu*ltw%9$T{nh2H36bO{aDF&tzZhD3jsQScP}T(dJ$u(2<&W)VnVGMB;=~vDE^jc zPtq&DF2W;)1NM-xcxbovmXRgWV0>ZUvZ7t&wJc^{o~MB*iNI05(UFyFYum z(_tT)uB+wHC6~wsGhu*59R{iUxOc#(;lZi^)LP^xdcEJg@7Byu z?GLk$jElqjWmDg1ZW9_A<+|oy_Lo(4dX8`_gHK{W--4h_^K#-pk4(6T7oBjY>au+& z{~u|&@e&o8Iyc%d?7LfJi3bRs^Kj3YLY zRkjgYBCa0eTXq#|Gpt%=?l9FQt*gr~P$esR{pe8#f!j>m(0joQ{+hNYfL&GB9b^A$ z=Z~zM6o*D5L`TTTs-!P_#-Bn1OXDU9nk*_C6~Q@(cKh$Ml@T#Ya%Z&nPZP{$x+mCF zba`wg-gz`Q2x;@E*atq(~IY zDt;5Xr+x?fGFOdoE8nbmqUSW7*~^`5AXBgs;AHudw27k2rvK93^DfBW z&T2&K5r;vSAu7m6<3>U~Xop#}=N6hp=^5B|b4Tz9_=k>5!;Y9XZbvNFWTE~A3ARF_$?v|++o_yI4;Sc_|E9- zY_vb-cr!z!4|Y(%ozBZYe0lHGu}t%xHKOY{&?w1V*w?FGDXOli?^te!us&@{uDRcl zI+0qVa-|OS5sZIL8key?w>_iWFf7}=TUtc~wx6dgp=vaftHj8~E-7%o@+Y+;*k`L3 zSzvgPTpz{o;&j7u8z+gXfa|(W%Tn!w&bxO2cR$`30n?;x&L+-g-p}!1X>e?v_23+Sx&Tod};tZIrpS%NwK_28dY%wIy&Bfqve+grn5R*4V z`3zs)xI*?9ukjutx-)GAITFF^(gJt3n=9=n7XXruq$DB)H+CK zlcKvY__Y6kWeAtTyGs0`x+l?^A##8NUa+-dGY31Q67bOMzIlA)&ZSY}d`kw}L*EOv ze|C?ZN`0W^SKWr8uYRv=3~T?9T5#X0OFY%M=R>Qg`jAgu?}7E1V}n)jgUA}bzTsxG z{@!MIC&W2Au%l020{nn#OGuJ2V8ujFf_J~u_%u7TwBNAVFwmQ6cu)8nU!naTa7}!{ z1BJ|Ko2$JeO*TJ2e5x+IYb>DW-Pz)#r7Eef+y#->+2goDxYsVAt$FI8*VEK_KTT~H ze6QsVqEyei7Oq*+rJik3MUpO1e*zYbHHz)5Dg)ajT&O<&UHJ{wH~w?b%|*#f-E1u>`IkA#VZ}jRmX&m0mvn=lU`cm@5 zq@qnV{q1G5gzx-yc$pi|6&c!VRf4I-tOlN>85yM--+;a{jPbRGlC5Vr-ma5otNQPl zY4s=O5A;2=V{@T4!^73)_v}{=J0oMO?BlF|+8HdP-Jbs9>XdQJK4OWF%e~M*{958e ztcS5+X1~WLW!=?chXaE<>h!q~^)O+wk63(Ad2^`x_KZ*1S4K+*P?!%Mw?(+w`UW0icCy6u93jan6;RZC zqDjTtn$N%>p~z_}x&AL(_Gwk4^_!t2a=tRpF&v3Ceon)8z9#O6G$?iwZ7n;591HXh zz9x@hKnZWXs(jHM-V_KiUidHcm;Mo}JJnSL8z~*#sK31-Xw;J~K|fIrEE&^2lRA}7 zwhP3U1EyWK`3y~GbRPYcJSZpc=j4GBz@DjQbd02HvtD4c?7r z*eup2be?1FsShJKH6nZOS}y#`=XGPP17VdZMqm0)%V(=hs}4D*YZ{UJ6pq3qDcC9c zck`?PL~VT*ju^pz9wS+g{+RBJSTSr>I@^%xv8?}|1H31vR%t6h8RlTjk1yWOJ=s?h z@B`k}QXRD4b5GpiQMJq0ykB0kwp!g6vytZea+Qcp} z#fL?`a$QbO3^dXd{W&si7tEP`JJAfwXX;ZO#kPhsqPD?-fZD_tzA%k^aqyR)d z=4&H;CM#-(&}#~WwDrSV?;fy0Euj=Fu*mMqca@8YMq^)8V`}9X6i@ zU>QvM%CZ~}JKKOmC~b`{iSvsuK$j5UBH~C_S||BB?;Ci_#!KVvA5(+};m$fd(jDtI z4D9OaO!D45>VX6wdjV7g)HX_;3N}~g)-fZ@EPdDUvYg5=4-_Y7u9WBnv!C4UtDQ)K zh7hiRKLB~ytt2fCZu6&gE4Bi*C5-84HnpFgBp|VxWi=hI(9JX5+HaWR$+(Ym3=q{y z-)EeQIqrX@I~gA)+%<7Yk68G5=4{y83Xaip%q}G}FjWON+!GZd{iMfr`X&3w;DkfK`8aB8w{>|n-R_F2`c|2%PuS)7#wl%E6a@nM^~Ne6-#5 zkKVF^(cKP!u$65W45-qR-M96~)APeXf$hTZB3e(1`iw;g>4cLBt043n_z=EecHNU+ zY*5rQm&E=*Sng6YVi@&}ehMRACDk(_e>^AxAcgk`&bP{|764ASQ=CEelSQ=3^xD@ZH=^0$% zrZxWFGP-{e-l^t-<^ItNgTbC;ry|QcgtywDDi%qHop8U6 zt@INE_7*~I<+e!_c}=HskS&DnE{yoVAjAbTNY*HWdOmd~H3B~`Y%r5iqOBmd$ zeebo@z;2o~xViQUJFqi`)s8#WS~5`a{wH{N1;QHV3;!!1d(g%KLSzrWnNN0nDf4xKrS0 z9j3HLy?gl3ls|4=L$}R6rkPhK=9~+SvjM4PX&hM~NB&99@qv|QZ6Z9k81k!Z!(co1 zao#e_+HnK&9OI&Wy3c!VH`Rvq$Y$7fW29E0A!~e}j($WeHP=$NU=b~+MlPrencG8c zN3YE;BLyiPp+d9M-NSPeT$Y2q>`5+-@u?D1-#BD2NuyzncI))xPEJ-#Vuq!$#?IJJjwGq@iWJAJjd5Ndh3gDV<%erPSuGi)X&QJF6H~U&+Id2C6 z<9ra3BiLlh9?PHFYwYi{Sh`SX;5oLakS;6^maYnHE~pgAJ^A*_8GjX|XG3^lDgEy9J$apry=@nH4>D?=kBh^P8S~YqrCZ;4O-Wfxy2hW^b*5&4;w+ zo`Wt*+7Fnb-Cwa{e#n{moFqNdg`SoRu${i#!OCxPYn{WI33Vt#UrK(wdk#)l$S#5g z=Up7nW3zSVhe(K`_FKiPP1k(dn=matHuEXsFu*&c6%MW}PLE?8Llw=wGBZ@{(feqw z2eq29H(Kd*TP2=Aa;`MYTio^x$#~Zh!6K*~VY)uC`y|yob0vd6PNUmO_PM%RT+M13 z9b#0FSe@Pq(zJ)};0y_}k$666tJgm;0HFf|lN{2I5*r#$ZEfxQOgUmZKWQw8X4B_= zDFE)JiN||?G*&Yd=JMh~s%`pd*UOVHCEJkGIu89`?H7M&?MKU_x}<4m5?o)Qd_SJv zf8gDAo8JnU-nD*i>lyue52oWq+XI-}wM4mr`eM)q$sIS5LN$X4`36AoZ@?h4M<#~r zRkf5&4Vm!^X{(qrU4k*7&xULntywJIG%ED219i|m3g#pn`F~AuGiM7hdT$#w9J(qF zT&`r4_*W-u(R0()YpKf{w+|Eqz49)>R}>G6YjcmO_0X5eeHt$?C;4ISeG= z9orPPyXCz7h@f709KP2)XjpovU@bP|yY*i?M6(<2}-USo6_zwjJMoro-9rCh7y`r&cOl?ZkGPQKh+v=)9V3%_5g@*W{Ti z1m0M_-ql&lVJ}tw@O`%TumvenuQThRO`^A`xM6!rb( z%<8Q-+ZSM>jiXg%nVCoZ?RsymaGYfMW*P=K<&T;!T9Tl6mJ7oZ-vd4Qv!mC-TkW$^ z{G^bfWsULS#Y5x@prLf=vI>;n(Q2Gn6>3-$?ei2hWOx(?hkVyfq`olyJ>@c-F8=E> z1DrzgU3~`a@Gkm7KHa@OVTC-eD z4`>6v*YO$6_jtMGP7gtGC2<7P1bq{CVHVWcg*swWUCeS=3tTeJb+0r{Hi+CAiIjBK zQ{5Cd)VaJ_b=2sN$)yPJuj)zRh(U+%Tteef;{vTY(*g<(NZjBvem$pxSmw=0i?ey6 zt{_46x3~XX*sD5id3W~e*dc&k==7-V5A=`2%xbwmwje0t8^Goxz89Ewo64#l_X92trAYa`fO6vH|}TeCdok;4;SvdT=Wq=fMBVWw7Y% z$ArerVUz{Z-uS&{>MZa`2^{EtyW*OH#6tnS7KbWH^ym1nX&;eyd0K}kL*r5%HZ+2V zM@A#OQYH$7ecF3n`v%n_B<6*^kYZ(O$#ymf87q|c^WR}>bj`*62G2`Xgo)8TO*Ocs zT5m*pt7aAsaG~CTZ~eqFi62X^qmDvg4S%elo{k_ zQy6-}Ne&sJR1nwLL$^dl@0WC@nm-F+pqlkI44y6T?aLn;kT+4TD;wb79r`*p!hSVy zYU?T{CeC?8wH??xX6#ktFTIPp#-TPtts+?86}@tQ-lD>%UJj%Q%Wdxdw3&&C7ma-v za6kJm_dNFss|(<|LZazjqUWR3Q5+x|f3o~te`a%Xojsu%f~mU753}oL{SaW|%zM*- zp#$5DPS`!@s3exa9s&TD?l|E_L79pE|NV6!huYtt+0hc~Ly`hUzxI{78q}Sv%9(*; zTRYr)90HcHGb@DL35`uo5XnNJMD<3!#Q)}u%4F!Bq(BFd>_l-kAwM*xebLG?=80T$ z{NtgspZ6BsQ;6l1-#+t4a*}iGw5ZYE&8O^h2dKN7W)G=@R{oqfVce=~gFQee$=nIs zJMGK>;%7CFjdv*hYiC6NH}&07X>3vV^dd!2K(Sy2vG;Cbi!r8XVq#41<)!DnnDWxQ z=B4*$dXJi_CNa_28+Po7A}S~#3IZZ+e&pqQzwaB?%$>FG-e;dXf6Q8}HTRtSID{|_ zx{5YtI2Zb0^qSRtDbQ1A_=ENg;@>QVN#ybg0rWXbNyQ2r`UmzxOe<~6EOimjh&pvQ zZ7uPG@6n;GY){=2$n*Rr0TX#j!b!E0J4rwc$&dUn*Q+ z^BV+WAJzN%+Ss$Uxsef;ZPeQ?vr7E~y869MuT$xmENyvU zo!q(4D}+R^M22!T%*-MZ@l5z;APmCOAM8U?-bbGKaSAo3M-*+1<T zTsbl`Te$@%7PZgpW9$0F9mks`gWJ98trx!Jdfn3I+mcP5c`t(vl=|v!lID2ZchpF; zMYVji!s50Vv0?VqJEG}Ih;JA#BpJ5H`vDgXUx^qR-XL2K*$JOS?1k>_{o#FQQS5!W z@S=GpE2JyJ#1K~yb4a;Pdbk1MxRvny-3Gi4F=*k#>ax~3T@#j-LNyc=4mZCKRVPrP zn%^lCOA`;#9Np0xS*vy7)3D?jOwx!YjvmV|(9Yybt(y3sv+=cO`OU0>DHB3ekOJ$P`|OZq2aW% zjDm(XGr0MlsDs!R@fW<`xD&$`Uq;`mt_WSl{$SWjW|GgMO1Vb}t2y4Fa?H(E-|<}K z_M6`(!Xr;(*b^-5c993}y7Lro4JET%#Pnl6>*FB`*@GS9jSq`qA`8#)fYhq5xER|= zhKXbPB-0;W4Vyvt&^C*mw})p-W4+9zTRKdl7W6Yz^Qo&QKbb#G8gY=+9cwRAJuY3~ zwTIti=cT;W_kosQ!n0uxa7V@*9+(TNizF*W?;__wPL!qVvbsOn)f2XJ?hml$-EE=i zBlUll+!LIiIN7n@d&qJ;+toeDuF~atX{dhT!1{@5uEl2|sNO@OXf2Tl(lFO7SB|8T ziF`rWI3DvIsO=hrkVY7~;3k`mG$(AeY&(Z0Zg;j3*ee%W4upn)s8ch5k7GTO%k3+I zms0&bQ@l1Si5=^m&sq5N@*3h6!~uw++lZGMHW{QXr+sSwIJT@h&9O~Vce@zE!`)zZ z)Qs}3O}avQM8Q7u12VcYc~=H^p;p8ERH}}{ZBPpb4Zz8xmsMo22AuD32fIwj(>zcj#rsBglpXHjs|I+ zbLX+}NYIaGl=WpqMR{<%aZk-V;W6?B9bA-N_sls&K1V1Tg#9#+C{x@nocVUC_L3=c z?8o?1;;9}@tU^}k^JR=#e|`Gy=RvV9Q-`Ln&U-LEz|0uQ0Kc!;6=36 zziD~5#ARfB^b)dhNRWC?CNBQu4Eo@Jzhsib_<&5~j?AweyQ<#6ZLx3y-N-@WHZM5k z{Rm+nk{o-fC!`hJ+GWQjU}_7Dy{N}s=0Or#zBcWq7b#j$HMWQ*1YP5Tws;)XflX!a zE9Wg%gXM#jQh#ZhD;0T?sbh&^Lcwdyk>kkGKdFOO^-y)*0nJJ-h|niI>OHA8Rh)Iy z8U(_~sqQ(>Hs>XCeWl3zcjATgW?u1Q-G2KFlOrS-IssbK-BpUBjqqk#MnHhZbq*x$ z;i;s1#h_wYCc<4T>&g%A?n%%tByZ+x`CRDn=5X`C5p!4pjf&c2vu|>h-A4^c5CnZz zncDg^VVBQWz66)y5Z3W>c#-C6?IGF6z{;4iP7jtD{YJM(BNg>bwFHur5aiA+G)1fKdrs0FIbCZ#E2V{=}^tw)Dnio|5+2jVSp7Yq8Iu_3OtM91uX6J7o z+~J>`7@XLa2x|ZRdre_0=X<9R?(u_FSXnjb{Op&)M(hfo6+BJ9x|$2AVqYJqW=B#w zoJD=ruDy^Sj$(?yrM_m1yXhc*NTkK|r4jtE>XxKEFay#o>i*ceod zt?bJ)^nMR6_EvCqBTDs^ewc=zY^S_&I{@1SDRB6M;%YzND^6U1J_t(?bkn!=B+3QY z1=(*z^2eB*ON2krl(>CCjDYGfSN?7#2;%cCqn%Sqk%V|0s+s|{&2HC)1STT(VtSpn z*-T;=>!Ioo;L{%4XQ0JHDOV_-*^yHZ+r9WDTG`-%!6^2_kV{iXp1F9Xht2skR%}A~ zdy49Xfi$D*=xD$pMLGJR({r?ibFN*|(Q4Vu+er^r95R)dS)1Zq_C0xGRS@;s4g-RB z9`-GB+uIN($oH-!Cc}@IZ1Y)Vy5S*yqQ+EUp;yWj0(fRQvNfH2Nte;%(-*Euq1@CDgXV*Rb8^j#?(B;JLw~#nVBez zg^-2W3ztN^(8mqo{KD|Fu>pA(Lhd=+2;C_~0WLYQlWVaajd@&_G-@i@LKV>1g~zVw zHIX>Oo}x|}dky|&x!vi8YHaZRB%+^PXVrFw$E*9yyxsWBd!>^n;-6MG(W_W;{g%nQ zuVp54Eg1biXh-Er$`AN(&?6RDaKUqklGrw_n{SEJ9+4hJ9PLDQaGl|tLHrk7i7K9L zKVt4yC`eiWC^pJIB*P-kk&}k^dR`{Ymme77L`9lcIn0M0@_&JM;k~fsRxbwUwhQD5 zV2lgj0!QX_&G~w0(X61?UCEyM$#?Pxi26+PJkD`0d%^w0M z`MwK34Bt>S2|q(#KS6a(vzyaT8%k0?z(dr>gxt#a!)Y!{ZBn}qV67bIR7>1IZzewVJyva0TPYnYovb}cq1EZk`4Zavw! z+H#XWJ5r*^^-nYpce$wJRqU|YRACwLM-fSV5Wy-i&%096A=B_xO(C2@=R>t;x`X0< z4C|-PlV6UX=|1L}(}rni59`O`;7kFQY9nzj^OQF@Z<$_WvjnIaDRI|@Bo1eVMPYkm z_|em`Z}lylhS8%HE(lcr6_xz6Il+FcsrBlVnc}O>J)m5nG!)n#vk9EhKtHj#5Gk^7 z^hk7d=-JE{vnG#b5`cz3!lp%&Lra(Jkd;VMFC`jG-0 z1Ioxd3x_HCy=I&9Vdq^3N?wh-V7?BNo2|1vQcA3>pFGg54Y)MTEJw{ej>sh$KM`%+ zkBC9;E~rE73u7VapdMbBaE$ZzBaBvt-tzhzXelD8t+G>H_gCeUUU6-h=nxDo$a5fQ zpKzM24Hi@6Cke44--=S3%O9wDP|to!)mRaIcjJ1yJfW_r5j{suU0p*@rG$S!EIN{k zk_&1`^QjDi7L?jEr*tHHbZyV>FPYg6lW0!pr`4{G4FwT7cqg$d|UMWOSnPnF0(U^yeXfkWzo!ZbA2!;R+>OkpIF|L9xEr z<2OFSC48vs()W}MS#atF*Uk2GExVnpm;XkXUg6Prb>!%Diw>0 zoeQ0AMLVX5V(jiO=YgcBN?s=+22ZlF1$@Il(QN^hquE{gmMK;a;R^@&qfc52s5vuI z?VwmD-LC~wxy+Qo;}4!DE_SpD9EIwKeUoP|Jg2)+!EN>FJ1)9|{*fvk8R$5GUBvOB zQLW3^JIJajFY#8pf6(W3HDXgxI%cD;yHgJygxs)rC9RS~njLXnuzU&_%i{@-zoB3P zVx}X{t1|IF@CPslqC12%{d>-F)zbF03WGI#eDOVA@gpY>yB*_Jo%KJZ!|9mWgJp-YpQ?#T*$oPd1e>bfP}ln5@AXQY1<_+lCPd9RDbF3x3eb_hkeYDso9>P}y6Tlx zkw^PNfLVxoB4%A(Kh0R%YXOAZ+xt1iVeRZqjFpg+D~Xdq!stPTVEgz*jSK&8$<2=N zGP7PR_i{`N+9Be!fr)u+mm~SZ;*rzA<*H%^EyI$|bJpJ=YTG9hl zXYl)KVv{WbBwgnd1O4V@I=N%S%0tE31HD`eM$UjMdrWOu=8;lr+r_at-~I##xn+>P zAvP&(TeXvT55nB!*pnTR$`cl=F$3ivq$FyH;pbCt~b`Rf5%+Z&9c6J&ghPx(K285$@vL7*RgF-5syTxaxR6 zpPjl+y15^lRW#rm^>8Ytf2Zfx6hq)99z@;Q{t zND_SJTiM@I6^q`hm&$VO7jREvzb-#TyMdo)7Jw@CRali_NW}fr*)dCFEUNX=viMqI zPOVq3-{dw{354std@urMDz&}OcBL@Wfntgioa7(}P3JlQ>K;pZb`i7!w$0;buxT3!gARvquQ8paOX8kDC?Eb$c#b{@py0`q7>&WpD* z>oULh2A%0z*Q{1~_a>Y56cn%&V6WH%b6atebgpLU9!CUqEFFx|p?5BnfJka@~s>!NJ8h$*2$=`gQQ zG|@cuG}@nf!z{M^VO3hU`!-zIbD+5#QPbsht8A;r`rSJDm8|xF8ACnD5H{?MOf$WB za3s65&{4$O#H@y!W40p8^{a%30|dS(jZ$qTAPLUgHZr=un#8kYj13-7G90;>ss8E*}85B3T=^P5P!_L z(fZHWDCD*Na51P4?uEWS6BE?)W`gItp>@CA>j{bZw8n0jY5l_CQ4jL;@Dw}z5k_$5 zA@_}h7~7p%e%*JJ8+RUfX5a#TgXz`jf3q&sovm748wdW2=-T*rJUcf^|30XX&Z5q% zeeubXa)HBj8z(Z>PfDqhsW*@D`VP}AIxeKeAOS2AHzuQNwTQ=CTwU&#+2InS(|H;D)o;#llN@b+#$KExDiPFipxGM0#Y;ceOmlA; z*~W7bZ7Y=2J^|(he^Wd$C=u@A9XL45E0>P5}>t=i7 z9?5(Lc2G|TRf6~R=@<#1EnRyNS6j)siIUffPrcWIxwwmMAlw>Fud~u zHL(5bqDoq{eJGorLd#Xhb}nl61jPPd#r{r(MElX1(TP}3>t|y>nX^b>bNs?{4oea< zT_1DN9%qgFzy3ljt8S+@sMAJOl8&J7O`imx zY{&XZlQ|u+Zgj{uvGuklZ?X=epBOv?9S$tX@3c(!s376sGrnzu-QeVOM0swOsn93g zzCz`eClN37xA-q~KWH~QE-;sP&P80yTA|t%h^}8mj}_K=3}`O4_QbCf?bVip(^`Y1 z`5;`M9HqgMeq_L}VI2}qhviC^S+ZOD;chm$v$T^0m0?Dr-3n%XoyGiBZj6tA)%20iB;*GoO8uCfJk?-(ld;qJ zdzc%UR9@l$khaIo;c#U&iiCz<`Aot?dVyu)EGMVEV}oY0=I6!=psVt~F_*uBRHpZ5 zkTKKq*AEct?%fLUlpQRLtZtMORXc&p(QOvi7BoTzW3*fz3j zfl2?7SLR2QF{4AxcKl&gR^b`ZCthfGGB6iNSaQYAxIbKcTiWAs*8zq)-E>-wjCt)_ z-_0E{b8K>*;q@H+vTzQ1!1TP$+bE zk030ktrlc?Is#dJ>h0^A8r9Mr*HZ~JIiP26!Niot;CkWg~(4Wl{vZJ zRNxj5d-l-On=XvYQO1@wGU07RigZrHL2-gdrR`zbA@o~JokwKwarY+b4a~CPolC(# z369RDlBUEmEXl^HttyR6ly0F<@AnQ^GqMpf`^UM4<#mT|R(5ZGe`bi)zC|_OFezzF zd@8h8x`y2yKW2Ax(RZG(7CQXhbGrGlRxjyo+Dyuxp}^28+-(HLJ)FLsf%9Fo=x@Xx zLA@QS@-izL5bHB$ASYZrTHUQ&I9^?CyUl=Ln#mJQ#PG@nB-Y1P+DEFKs&dNN~7Hop_Y1-e*P)b zp(R3C>3gf&KE#gbx#Vy8{X4T97n`};)-?9Gb&eX;|14VAV*xQ6Pb;{ne93eDXdb(S zcEu_?YKy9?_iTjE`xE5Lv8~TSCTX&z-*hXb{R!(Xj3UFj1af8DTU8|L z%SfRmUbl~#r~J4$i#XuNl_Cd|#X47sVfOI6;JfaDp@aRo1)-J)yew2M#yFOho!uaAa%pLYHe^3VG29xBroS>Wto^+Rbp-v$cFQ-jh=9>qaneMWMX@JQCu$lHh zBijXsT+$umEbPWtS!t#_2ZcF|Yxn1{xdQzpI@NZ{%;M50=N$kw_; z=js}vr}Qm`yU-rPpTJXyl_3|{1!U^oVPV?u(9ODIuuGcT@GL{7mIXOyNP>zDS3!?J z_WD-vJV0wmfg~6PARhV?5Q^>~xErF>mVrwR-k>IM3h0|57AOP$0l?sH@JoXUzytXL zDWGYPwYtOLlYko-1Y!e6LDvkc!D|dhK-r)%z}SliI11DP>4x>t0{u2nJV*rSfkQwB zxJ};&`U1QL-3FNfXF&tNe&9XmBR~Z4fp8E2JOYwI1Hu}JfEC4VVM-2e~ch0y7BW3_VMklQi*BkGCVZTv`k^M{YFYrGXgVFOh`iu7~ zmd=QPjmlqczvKP#gc^}w%wMwKF@E_#{{N}}SNWd?^l!}nvG{lR#fBPV!;ItaZ2mVQ z-e43FNa@#zd64%`oA;(<^0?E7wrT_o{ literal 0 HcmV?d00001 diff --git a/test/assets/kaldi_test_fbank_args.json b/test/assets/kaldi_test_fbank_args.json new file mode 100644 index 0000000000..91d1b57f71 --- /dev/null +++ b/test/assets/kaldi_test_fbank_args.json @@ -0,0 +1,88 @@ +{"blackman_coeff": 0.0939, "energy_floor": 4.5062, "frame_length": 1.0625, "frame_shift": 0.6875, "high_freq": 1841, "htk_compat": true, "low_freq": 479, "num_mel_bins": 5, "preemphasis_coefficient": 0.84, "raw_energy": true, "remove_dc_offset": true, "round_to_power_of_two": true, "snip_edges": true, "subtract_mean": true, "use_energy": true, "use_log_fbank": true, "use_power": false, "vtln_high": 1832, "vtln_low": 1824, "vtln_warp": 1.0, "window_type": "hanning", "dither": 0.0} +{"blackman_coeff": 0.166, "energy_floor": 1.7875, "frame_length": 1.125, "frame_shift": 0.5, "high_freq": 4999, "htk_compat": true, "low_freq": 1740, "num_mel_bins": 6, "preemphasis_coefficient": 0.29, "raw_energy": true, "remove_dc_offset": false, "round_to_power_of_two": true, "snip_edges": false, "subtract_mean": false, "use_energy": true, "use_log_fbank": false, "use_power": true, "vtln_high": 4587, "vtln_low": 2289, "vtln_warp": 1.0, "window_type": "povey", "dither": 0.0} +{"blackman_coeff": 0.2215, "energy_floor": 1.3444, "frame_length": 1.125, "frame_shift": 0.75, "high_freq": 7468, "htk_compat": true, "low_freq": 87, "num_mel_bins": 5, "preemphasis_coefficient": 0.17, "raw_energy": true, "remove_dc_offset": true, "round_to_power_of_two": false, "snip_edges": true, "subtract_mean": false, "use_energy": true, "use_log_fbank": false, "use_power": false, "vtln_high": 1700, "vtln_low": 870, "vtln_warp": 0.3104, "window_type": "rectangular", "dither": 0.0} +{"blackman_coeff": 0.2512, "energy_floor": 0.2607, "frame_length": 0.875, "frame_shift": 0.875, "high_freq": 7380, "htk_compat": true, "low_freq": 4471, "num_mel_bins": 5, "preemphasis_coefficient": 0.76, "raw_energy": true, "remove_dc_offset": true, "round_to_power_of_two": true, "snip_edges": true, "subtract_mean": true, "use_energy": true, "use_log_fbank": false, "use_power": true, "vtln_high": 7138, "vtln_low": 5172, "vtln_warp": 1.0, "window_type": "hamming", "dither": 0.0} +{"blackman_coeff": 0.2834, "energy_floor": 1.7885, "frame_length": 1.1875, "frame_shift": 0.9375, "high_freq": 5385, "htk_compat": false, "low_freq": 2579, "num_mel_bins": 6, "preemphasis_coefficient": 0.82, "raw_energy": false, "remove_dc_offset": false, "round_to_power_of_two": true, "snip_edges": false, "subtract_mean": true, "use_energy": false, "use_log_fbank": true, "use_power": true, "vtln_high": 4782, "vtln_low": 4492, "vtln_warp": 1.0, "window_type": "povey", "dither": 0.0} +{"blackman_coeff": 0.3188, "energy_floor": 1.6288, "frame_length": 1.0, "frame_shift": 0.5, "high_freq": 6258, "htk_compat": true, "low_freq": 2043, "num_mel_bins": 4, "preemphasis_coefficient": 0.57, "raw_energy": true, "remove_dc_offset": false, "round_to_power_of_two": false, "snip_edges": false, "subtract_mean": false, "use_energy": false, "use_log_fbank": true, "use_power": true, "vtln_high": 5274, "vtln_low": 3268, "vtln_warp": 1.0, "window_type": "hamming", "dither": 0.0} +{"blackman_coeff": 0.3637, "energy_floor": 4.7928, "frame_length": 1.0, "frame_shift": 0.5625, "high_freq": 7671, "htk_compat": false, "low_freq": 2385, "num_mel_bins": 5, "preemphasis_coefficient": 0.81, "raw_energy": true, "remove_dc_offset": false, "round_to_power_of_two": true, "snip_edges": true, "subtract_mean": false, "use_energy": true, "use_log_fbank": false, "use_power": true, "vtln_high": 6881, "vtln_low": 4659, "vtln_warp": 1.0, "window_type": "rectangular", "dither": 0.0} +{"blackman_coeff": 0.4702, "energy_floor": 2.668, "frame_length": 1.0, "frame_shift": 1.0, "high_freq": 7231, "htk_compat": true, "low_freq": 1515, "num_mel_bins": 4, "preemphasis_coefficient": 0.92, "raw_energy": true, "remove_dc_offset": false, "round_to_power_of_two": false, "snip_edges": false, "subtract_mean": true, "use_energy": false, "use_log_fbank": false, "use_power": true, "vtln_high": 6506, "vtln_low": 2549, "vtln_warp": 1.0, "window_type": "hamming", "dither": 0.0} +{"blackman_coeff": 0.5988, "energy_floor": 0.8014, "frame_length": 1.125, "frame_shift": 0.875, "high_freq": 3663, "htk_compat": true, "low_freq": 1941, "num_mel_bins": 6, "preemphasis_coefficient": 0.59, "raw_energy": false, "remove_dc_offset": false, "round_to_power_of_two": true, "snip_edges": false, "subtract_mean": true, "use_energy": false, "use_log_fbank": false, "use_power": false, "vtln_high": 3373, "vtln_low": 3354, "vtln_warp": 1.0, "window_type": "blackman", "dither": 0.0} +{"blackman_coeff": 0.6421, "energy_floor": 2.1404, "frame_length": 0.75, "frame_shift": 1.0625, "high_freq": 6031, "htk_compat": false, "low_freq": 57, "num_mel_bins": 4, "preemphasis_coefficient": 0.03, "raw_energy": true, "remove_dc_offset": true, "round_to_power_of_two": true, "snip_edges": false, "subtract_mean": false, "use_energy": true, "use_log_fbank": false, "use_power": true, "vtln_high": 5417, "vtln_low": 1170, "vtln_warp": 1.0, "window_type": "povey", "dither": 0.0} +{"blackman_coeff": 0.674, "energy_floor": 1.3778, "frame_length": 1.0, "frame_shift": 0.875, "high_freq": 6623, "htk_compat": true, "low_freq": 2402, "num_mel_bins": 7, "preemphasis_coefficient": 0.5, "raw_energy": true, "remove_dc_offset": false, "round_to_power_of_two": true, "snip_edges": false, "subtract_mean": true, "use_energy": false, "use_log_fbank": false, "use_power": true, "vtln_high": 6491, "vtln_low": 6262, "vtln_warp": 1.0, "window_type": "hamming", "dither": 0.0} +{"blackman_coeff": 0.7979, "energy_floor": 1.4223, "frame_length": 1.125, "frame_shift": 0.3125, "high_freq": 2534, "htk_compat": false, "low_freq": 810, "num_mel_bins": 4, "preemphasis_coefficient": 0.77, "raw_energy": true, "remove_dc_offset": true, "round_to_power_of_two": true, "snip_edges": true, "subtract_mean": true, "use_energy": true, "use_log_fbank": false, "use_power": true, "vtln_high": 2494, "vtln_low": 2015, "vtln_warp": 1.0, "window_type": "hamming", "dither": 0.0} +{"blackman_coeff": 0.8161, "energy_floor": 1.2937, "frame_length": 0.9375, "frame_shift": 0.125, "high_freq": 5030, "htk_compat": false, "low_freq": 966, "num_mel_bins": 6, "preemphasis_coefficient": 0.03, "raw_energy": false, "remove_dc_offset": false, "round_to_power_of_two": true, "snip_edges": false, "subtract_mean": false, "use_energy": true, "use_log_fbank": true, "use_power": true, "vtln_high": 4652, "vtln_low": 2559, "vtln_warp": 1.0, "window_type": "hanning", "dither": 0.0} +{"blackman_coeff": 0.8873, "energy_floor": 1.2866, "frame_length": 1.125, "frame_shift": 0.4375, "high_freq": 5558, "htk_compat": true, "low_freq": 1464, "num_mel_bins": 8, "preemphasis_coefficient": 0.77, "raw_energy": true, "remove_dc_offset": true, "round_to_power_of_two": true, "snip_edges": false, "subtract_mean": true, "use_energy": false, "use_log_fbank": false, "use_power": false, "vtln_high": 4613, "vtln_low": 4001, "vtln_warp": 1.4073, "window_type": "blackman", "dither": 0.0} +{"blackman_coeff": 0.8997, "energy_floor": 2.8795, "frame_length": 0.875, "frame_shift": 0.5, "high_freq": 3383, "htk_compat": false, "low_freq": 259, "num_mel_bins": 4, "preemphasis_coefficient": 0.08, "raw_energy": true, "remove_dc_offset": true, "round_to_power_of_two": true, "snip_edges": true, "subtract_mean": false, "use_energy": true, "use_log_fbank": true, "use_power": false, "vtln_high": 1175, "vtln_low": 1038, "vtln_warp": 1.0, "window_type": "povey", "dither": 0.0} +{"blackman_coeff": 0.9113, "energy_floor": 0.9909, "frame_length": 0.6875, "frame_shift": 0.375, "high_freq": 7562, "htk_compat": true, "low_freq": 3978, "num_mel_bins": 4, "preemphasis_coefficient": 0.03, "raw_energy": false, "remove_dc_offset": true, "round_to_power_of_two": true, "snip_edges": false, "subtract_mean": false, "use_energy": false, "use_log_fbank": true, "use_power": true, "vtln_high": 6483, "vtln_low": 5671, "vtln_warp": 1.0, "window_type": "hamming", "dither": 0.0} +{"blackman_coeff": 0.9312, "energy_floor": 3.3768, "frame_length": 0.8125, "frame_shift": 1.125, "high_freq": 5824, "htk_compat": false, "low_freq": 1366, "num_mel_bins": 6, "preemphasis_coefficient": 0.28, "raw_energy": true, "remove_dc_offset": true, "round_to_power_of_two": true, "snip_edges": false, "subtract_mean": false, "use_energy": false, "use_log_fbank": true, "use_power": true, "vtln_high": 3917, "vtln_low": 1620, "vtln_warp": 1.0, "window_type": "hanning", "dither": 0.0} +{"blackman_coeff": 0.9472, "energy_floor": 2.4134, "frame_length": 0.75, "frame_shift": 1.0, "high_freq": 7959, "htk_compat": false, "low_freq": 1770, "num_mel_bins": 6, "preemphasis_coefficient": 0.12, "raw_energy": true, "remove_dc_offset": true, "round_to_power_of_two": true, "snip_edges": true, "subtract_mean": true, "use_energy": false, "use_log_fbank": false, "use_power": true, "vtln_high": 6874, "vtln_low": 5861, "vtln_warp": 1.1718, "window_type": "rectangular", "dither": 0.0} +{"blackman_coeff": 0.9483, "energy_floor": 4.0177, "frame_length": 1.125, "frame_shift": 1.125, "high_freq": 7854, "htk_compat": false, "low_freq": 4793, "num_mel_bins": 5, "preemphasis_coefficient": 0.47, "raw_energy": true, "remove_dc_offset": true, "round_to_power_of_two": false, "snip_edges": false, "subtract_mean": false, "use_energy": true, "use_log_fbank": false, "use_power": false, "vtln_high": 5868, "vtln_low": 5848, "vtln_warp": 1.0, "window_type": "hamming", "dither": 0.0} +{"blackman_coeff": 0.9631, "energy_floor": 3.3222, "frame_length": 1.0, "frame_shift": 0.5, "high_freq": 7662, "htk_compat": true, "low_freq": 1833, "num_mel_bins": 6, "preemphasis_coefficient": 0.71, "raw_energy": false, "remove_dc_offset": true, "round_to_power_of_two": false, "snip_edges": true, "subtract_mean": true, "use_energy": false, "use_log_fbank": true, "use_power": true, "vtln_high": 6204, "vtln_low": 5887, "vtln_warp": 1.0, "window_type": "rectangular", "dither": 0.0} +{"blackman_coeff": 0.982, "energy_floor": 1.668, "frame_length": 0.75, "frame_shift": 0.1875, "high_freq": 6788, "htk_compat": false, "low_freq": 1968, "num_mel_bins": 4, "preemphasis_coefficient": 0.14, "raw_energy": false, "remove_dc_offset": true, "round_to_power_of_two": true, "snip_edges": false, "subtract_mean": false, "use_energy": true, "use_log_fbank": true, "use_power": false, "vtln_high": 2114, "vtln_low": 2024, "vtln_warp": 1.0, "window_type": "blackman", "dither": 0.0} +{"blackman_coeff": 1.0183, "energy_floor": 2.1572, "frame_length": 1.0625, "frame_shift": 0.375, "high_freq": 2018, "htk_compat": true, "low_freq": 317, "num_mel_bins": 6, "preemphasis_coefficient": 0.14, "raw_energy": false, "remove_dc_offset": false, "round_to_power_of_two": true, "snip_edges": false, "subtract_mean": true, "use_energy": false, "use_log_fbank": false, "use_power": false, "vtln_high": 1118, "vtln_low": 947, "vtln_warp": 1.0, "window_type": "blackman", "dither": 0.0} +{"blackman_coeff": 1.0269, "energy_floor": 0.3681, "frame_length": 1.125, "frame_shift": 0.5625, "high_freq": 4897, "htk_compat": true, "low_freq": 543, "num_mel_bins": 4, "preemphasis_coefficient": 0.57, "raw_energy": false, "remove_dc_offset": true, "round_to_power_of_two": true, "snip_edges": true, "subtract_mean": true, "use_energy": false, "use_log_fbank": false, "use_power": false, "vtln_high": 1226, "vtln_low": 960, "vtln_warp": 1.0, "window_type": "blackman", "dither": 0.0} +{"blackman_coeff": 1.0298, "energy_floor": 2.249, "frame_length": 1.125, "frame_shift": 0.25, "high_freq": 2031, "htk_compat": true, "low_freq": 257, "num_mel_bins": 5, "preemphasis_coefficient": 0.65, "raw_energy": false, "remove_dc_offset": true, "round_to_power_of_two": true, "snip_edges": false, "subtract_mean": true, "use_energy": false, "use_log_fbank": false, "use_power": true, "vtln_high": 1731, "vtln_low": 1582, "vtln_warp": 1.0, "window_type": "blackman", "dither": 0.0} +{"blackman_coeff": 1.2222, "energy_floor": 0.0582, "frame_length": 1.1875, "frame_shift": 0.8125, "high_freq": 6633, "htk_compat": false, "low_freq": 1117, "num_mel_bins": 8, "preemphasis_coefficient": 0.96, "raw_energy": false, "remove_dc_offset": true, "round_to_power_of_two": true, "snip_edges": true, "subtract_mean": false, "use_energy": false, "use_log_fbank": true, "use_power": false, "vtln_high": 4191, "vtln_low": 3264, "vtln_warp": 1.0, "window_type": "blackman", "dither": 0.0} +{"blackman_coeff": 1.2251, "energy_floor": 0.4403, "frame_length": 0.5625, "frame_shift": 0.6875, "high_freq": 3192, "htk_compat": false, "low_freq": 599, "num_mel_bins": 4, "preemphasis_coefficient": 0.75, "raw_energy": true, "remove_dc_offset": false, "round_to_power_of_two": true, "snip_edges": false, "subtract_mean": false, "use_energy": false, "use_log_fbank": false, "use_power": true, "vtln_high": 3183, "vtln_low": 2975, "vtln_warp": 1.0, "window_type": "povey", "dither": 0.0} +{"blackman_coeff": 1.2278, "energy_floor": 1.4848, "frame_length": 0.6875, "frame_shift": 0.625, "high_freq": 5785, "htk_compat": true, "low_freq": 289, "num_mel_bins": 4, "preemphasis_coefficient": 0.58, "raw_energy": true, "remove_dc_offset": true, "round_to_power_of_two": true, "snip_edges": false, "subtract_mean": true, "use_energy": false, "use_log_fbank": false, "use_power": true, "vtln_high": 4062, "vtln_low": 3715, "vtln_warp": 1.0, "window_type": "hanning", "dither": 0.0} +{"blackman_coeff": 1.3199, "energy_floor": 1.1137, "frame_length": 1.125, "frame_shift": 0.6875, "high_freq": 6702, "htk_compat": true, "low_freq": 390, "num_mel_bins": 6, "preemphasis_coefficient": 0.54, "raw_energy": true, "remove_dc_offset": false, "round_to_power_of_two": false, "snip_edges": true, "subtract_mean": true, "use_energy": false, "use_log_fbank": true, "use_power": false, "vtln_high": 4426, "vtln_low": 2811, "vtln_warp": 1.0, "window_type": "povey", "dither": 0.0} +{"blackman_coeff": 1.3325, "energy_floor": 2.6552, "frame_length": 1.0, "frame_shift": 1.0625, "high_freq": 6444, "htk_compat": true, "low_freq": 759, "num_mel_bins": 4, "preemphasis_coefficient": 0.67, "raw_energy": false, "remove_dc_offset": true, "round_to_power_of_two": true, "snip_edges": false, "subtract_mean": true, "use_energy": false, "use_log_fbank": false, "use_power": false, "vtln_high": 6065, "vtln_low": 4599, "vtln_warp": 1.0, "window_type": "hamming", "dither": 0.0} +{"blackman_coeff": 1.3426, "energy_floor": 1.5712, "frame_length": 1.1875, "frame_shift": 1.0, "high_freq": 7444, "htk_compat": false, "low_freq": 1986, "num_mel_bins": 6, "preemphasis_coefficient": 0.46, "raw_energy": true, "remove_dc_offset": false, "round_to_power_of_two": true, "snip_edges": true, "subtract_mean": true, "use_energy": false, "use_log_fbank": true, "use_power": true, "vtln_high": 4787, "vtln_low": 3163, "vtln_warp": 1.0, "window_type": "hanning", "dither": 0.0} +{"blackman_coeff": 1.4359, "energy_floor": 1.2709, "frame_length": 1.0, "frame_shift": 0.5625, "high_freq": 7657, "htk_compat": true, "low_freq": 1017, "num_mel_bins": 5, "preemphasis_coefficient": 0.93, "raw_energy": true, "remove_dc_offset": false, "round_to_power_of_two": true, "snip_edges": true, "subtract_mean": false, "use_energy": false, "use_log_fbank": false, "use_power": true, "vtln_high": 4228, "vtln_low": 2903, "vtln_warp": 1.0, "window_type": "hanning", "dither": 0.0} +{"blackman_coeff": 1.4621, "energy_floor": 1.2891, "frame_length": 0.875, "frame_shift": 1.0625, "high_freq": 6324, "htk_compat": true, "low_freq": 408, "num_mel_bins": 7, "preemphasis_coefficient": 0.09, "raw_energy": false, "remove_dc_offset": true, "round_to_power_of_two": true, "snip_edges": true, "subtract_mean": false, "use_energy": false, "use_log_fbank": false, "use_power": false, "vtln_high": 6163, "vtln_low": 5973, "vtln_warp": 1.0, "window_type": "povey", "dither": 0.0} +{"blackman_coeff": 1.4751, "energy_floor": 2.3567, "frame_length": 1.1875, "frame_shift": 1.0, "high_freq": 7115, "htk_compat": false, "low_freq": 4236, "num_mel_bins": 5, "preemphasis_coefficient": 0.65, "raw_energy": true, "remove_dc_offset": false, "round_to_power_of_two": true, "snip_edges": true, "subtract_mean": true, "use_energy": true, "use_log_fbank": true, "use_power": false, "vtln_high": 6523, "vtln_low": 5708, "vtln_warp": 1.0, "window_type": "rectangular", "dither": 0.0} +{"blackman_coeff": 1.4883, "energy_floor": 4.1237, "frame_length": 0.75, "frame_shift": 0.25, "high_freq": 5670, "htk_compat": true, "low_freq": 766, "num_mel_bins": 6, "preemphasis_coefficient": 0.29, "raw_energy": true, "remove_dc_offset": true, "round_to_power_of_two": true, "snip_edges": false, "subtract_mean": true, "use_energy": false, "use_log_fbank": false, "use_power": false, "vtln_high": 5479, "vtln_low": 4173, "vtln_warp": 1.0, "window_type": "povey", "dither": 0.0} +{"blackman_coeff": 1.493, "energy_floor": 1.4719, "frame_length": 1.125, "frame_shift": 0.25, "high_freq": 7805, "htk_compat": true, "low_freq": 5052, "num_mel_bins": 4, "preemphasis_coefficient": 0.9, "raw_energy": true, "remove_dc_offset": true, "round_to_power_of_two": false, "snip_edges": true, "subtract_mean": false, "use_energy": true, "use_log_fbank": false, "use_power": false, "vtln_high": 7300, "vtln_low": 5299, "vtln_warp": 1.0, "window_type": "blackman", "dither": 0.0} +{"blackman_coeff": 1.5718, "energy_floor": 3.5447, "frame_length": 0.625, "frame_shift": 0.1875, "high_freq": 6777, "htk_compat": true, "low_freq": 938, "num_mel_bins": 4, "preemphasis_coefficient": 0.69, "raw_energy": true, "remove_dc_offset": false, "round_to_power_of_two": false, "snip_edges": false, "subtract_mean": false, "use_energy": true, "use_log_fbank": true, "use_power": false, "vtln_high": 4540, "vtln_low": 3168, "vtln_warp": 1.0, "window_type": "blackman", "dither": 0.0} +{"blackman_coeff": 1.5786, "energy_floor": 1.9016, "frame_length": 1.1875, "frame_shift": 0.75, "high_freq": 5812, "htk_compat": true, "low_freq": 3000, "num_mel_bins": 4, "preemphasis_coefficient": 0.14, "raw_energy": false, "remove_dc_offset": false, "round_to_power_of_two": true, "snip_edges": false, "subtract_mean": false, "use_energy": true, "use_log_fbank": true, "use_power": false, "vtln_high": 4930, "vtln_low": 4316, "vtln_warp": 1.0, "window_type": "rectangular", "dither": 0.0} +{"blackman_coeff": 1.6134, "energy_floor": 0.6389, "frame_length": 1.0625, "frame_shift": 0.8125, "high_freq": 7384, "htk_compat": false, "low_freq": 184, "num_mel_bins": 7, "preemphasis_coefficient": 0.08, "raw_energy": true, "remove_dc_offset": false, "round_to_power_of_two": true, "snip_edges": true, "subtract_mean": false, "use_energy": false, "use_log_fbank": false, "use_power": true, "vtln_high": 2759, "vtln_low": 306, "vtln_warp": 1.0, "window_type": "rectangular", "dither": 0.0} +{"blackman_coeff": 1.6312, "energy_floor": 2.6556, "frame_length": 0.625, "frame_shift": 0.4375, "high_freq": 5589, "htk_compat": false, "low_freq": 1049, "num_mel_bins": 5, "preemphasis_coefficient": 0.8, "raw_energy": false, "remove_dc_offset": false, "round_to_power_of_two": false, "snip_edges": true, "subtract_mean": false, "use_energy": false, "use_log_fbank": false, "use_power": false, "vtln_high": 3816, "vtln_low": 1550, "vtln_warp": 1.0, "window_type": "rectangular", "dither": 0.0} +{"blackman_coeff": 1.7515, "energy_floor": 0.5964, "frame_length": 1.0625, "frame_shift": 1.0, "high_freq": 4349, "htk_compat": true, "low_freq": 702, "num_mel_bins": 5, "preemphasis_coefficient": 0.36, "raw_energy": true, "remove_dc_offset": false, "round_to_power_of_two": true, "snip_edges": false, "subtract_mean": true, "use_energy": true, "use_log_fbank": false, "use_power": false, "vtln_high": 4168, "vtln_low": 1531, "vtln_warp": 1.0, "window_type": "povey", "dither": 0.0} +{"blackman_coeff": 1.8179, "energy_floor": 1.3295, "frame_length": 0.5625, "frame_shift": 0.6875, "high_freq": 4510, "htk_compat": false, "low_freq": 122, "num_mel_bins": 4, "preemphasis_coefficient": 0.56, "raw_energy": false, "remove_dc_offset": false, "round_to_power_of_two": true, "snip_edges": true, "subtract_mean": true, "use_energy": true, "use_log_fbank": false, "use_power": false, "vtln_high": 4365, "vtln_low": 3721, "vtln_warp": 1.0, "window_type": "hanning", "dither": 0.0} +{"blackman_coeff": 1.9387, "energy_floor": 4.7991, "frame_length": 1.0, "frame_shift": 0.375, "high_freq": 6123, "htk_compat": true, "low_freq": 740, "num_mel_bins": 6, "preemphasis_coefficient": 0.21, "raw_energy": true, "remove_dc_offset": false, "round_to_power_of_two": false, "snip_edges": true, "subtract_mean": false, "use_energy": true, "use_log_fbank": true, "use_power": true, "vtln_high": 3970, "vtln_low": 3355, "vtln_warp": 1.0, "window_type": "hamming", "dither": 0.0} +{"blackman_coeff": 2.0479, "energy_floor": 1.4296, "frame_length": 1.0625, "frame_shift": 0.6875, "high_freq": 7818, "htk_compat": true, "low_freq": 1628, "num_mel_bins": 8, "preemphasis_coefficient": 0.27, "raw_energy": true, "remove_dc_offset": true, "round_to_power_of_two": true, "snip_edges": true, "subtract_mean": false, "use_energy": true, "use_log_fbank": false, "use_power": true, "vtln_high": 7749, "vtln_low": 7478, "vtln_warp": 1.0, "window_type": "blackman", "dither": 0.0} +{"blackman_coeff": 2.0809, "energy_floor": 1.9752, "frame_length": 0.75, "frame_shift": 1.1875, "high_freq": 5933, "htk_compat": false, "low_freq": 666, "num_mel_bins": 5, "preemphasis_coefficient": 0.72, "raw_energy": false, "remove_dc_offset": true, "round_to_power_of_two": false, "snip_edges": false, "subtract_mean": true, "use_energy": true, "use_log_fbank": true, "use_power": true, "vtln_high": 5348, "vtln_low": 4645, "vtln_warp": 1.0, "window_type": "povey", "dither": 0.0} +{"blackman_coeff": 2.1098, "energy_floor": 2.1356, "frame_length": 1.0625, "frame_shift": 0.9375, "high_freq": 7825, "htk_compat": true, "low_freq": 408, "num_mel_bins": 4, "preemphasis_coefficient": 0.37, "raw_energy": true, "remove_dc_offset": true, "round_to_power_of_two": true, "snip_edges": true, "subtract_mean": true, "use_energy": true, "use_log_fbank": false, "use_power": false, "vtln_high": 5297, "vtln_low": 2747, "vtln_warp": 1.0, "window_type": "hamming", "dither": 0.0} +{"blackman_coeff": 2.1463, "energy_floor": 0.3422, "frame_length": 0.8125, "frame_shift": 0.5, "high_freq": 6892, "htk_compat": true, "low_freq": 65, "num_mel_bins": 4, "preemphasis_coefficient": 0.47, "raw_energy": false, "remove_dc_offset": false, "round_to_power_of_two": true, "snip_edges": true, "subtract_mean": true, "use_energy": true, "use_log_fbank": false, "use_power": true, "vtln_high": 4178, "vtln_low": 2891, "vtln_warp": 1.0, "window_type": "rectangular", "dither": 0.0} +{"blackman_coeff": 2.1768, "energy_floor": 3.782, "frame_length": 0.75, "frame_shift": 0.8125, "high_freq": 7063, "htk_compat": false, "low_freq": 2703, "num_mel_bins": 4, "preemphasis_coefficient": 0.99, "raw_energy": true, "remove_dc_offset": false, "round_to_power_of_two": false, "snip_edges": false, "subtract_mean": true, "use_energy": false, "use_log_fbank": false, "use_power": true, "vtln_high": 6819, "vtln_low": 3764, "vtln_warp": 1.0, "window_type": "hanning", "dither": 0.0} +{"blackman_coeff": 2.1902, "energy_floor": 4.9973, "frame_length": 1.125, "frame_shift": 0.5, "high_freq": 7066, "htk_compat": false, "low_freq": 1699, "num_mel_bins": 4, "preemphasis_coefficient": 0.95, "raw_energy": true, "remove_dc_offset": false, "round_to_power_of_two": true, "snip_edges": true, "subtract_mean": false, "use_energy": false, "use_log_fbank": false, "use_power": false, "vtln_high": 5452, "vtln_low": 5271, "vtln_warp": 1.0, "window_type": "rectangular", "dither": 0.0} +{"blackman_coeff": 2.239, "energy_floor": 2.9557, "frame_length": 1.0625, "frame_shift": 0.875, "high_freq": 7615, "htk_compat": true, "low_freq": 4707, "num_mel_bins": 7, "preemphasis_coefficient": 1.0, "raw_energy": true, "remove_dc_offset": false, "round_to_power_of_two": true, "snip_edges": true, "subtract_mean": false, "use_energy": true, "use_log_fbank": true, "use_power": true, "vtln_high": 6790, "vtln_low": 6501, "vtln_warp": 1.0, "window_type": "povey", "dither": 0.0} +{"blackman_coeff": 2.3199, "energy_floor": 0.8311, "frame_length": 0.9375, "frame_shift": 0.3125, "high_freq": 6738, "htk_compat": true, "low_freq": 1787, "num_mel_bins": 5, "preemphasis_coefficient": 0.83, "raw_energy": false, "remove_dc_offset": false, "round_to_power_of_two": true, "snip_edges": false, "subtract_mean": false, "use_energy": true, "use_log_fbank": false, "use_power": true, "vtln_high": 6635, "vtln_low": 6360, "vtln_warp": 0.7856, "window_type": "povey", "dither": 0.0} +{"blackman_coeff": 2.4071, "energy_floor": 2.7889, "frame_length": 0.9375, "frame_shift": 0.8125, "high_freq": 6598, "htk_compat": true, "low_freq": 2373, "num_mel_bins": 5, "preemphasis_coefficient": 0.2, "raw_energy": true, "remove_dc_offset": true, "round_to_power_of_two": true, "snip_edges": false, "subtract_mean": false, "use_energy": false, "use_log_fbank": true, "use_power": true, "vtln_high": 4565, "vtln_low": 3464, "vtln_warp": 1.0, "window_type": "hamming", "dither": 0.0} +{"blackman_coeff": 2.4586, "energy_floor": 3.3176, "frame_length": 0.625, "frame_shift": 0.75, "high_freq": 7380, "htk_compat": false, "low_freq": 4248, "num_mel_bins": 4, "preemphasis_coefficient": 0.59, "raw_energy": true, "remove_dc_offset": false, "round_to_power_of_two": true, "snip_edges": false, "subtract_mean": false, "use_energy": false, "use_log_fbank": false, "use_power": true, "vtln_high": 7263, "vtln_low": 6361, "vtln_warp": 1.0, "window_type": "hamming", "dither": 0.0} +{"blackman_coeff": 2.6039, "energy_floor": 1.1619, "frame_length": 0.75, "frame_shift": 0.5625, "high_freq": 6578, "htk_compat": true, "low_freq": 551, "num_mel_bins": 7, "preemphasis_coefficient": 0.16, "raw_energy": false, "remove_dc_offset": true, "round_to_power_of_two": true, "snip_edges": true, "subtract_mean": true, "use_energy": false, "use_log_fbank": true, "use_power": true, "vtln_high": 4974, "vtln_low": 3139, "vtln_warp": 1.0, "window_type": "povey", "dither": 0.0} +{"blackman_coeff": 2.6068, "energy_floor": 3.6411, "frame_length": 1.125, "frame_shift": 1.125, "high_freq": 3078, "htk_compat": false, "low_freq": 1003, "num_mel_bins": 5, "preemphasis_coefficient": 0.12, "raw_energy": true, "remove_dc_offset": true, "round_to_power_of_two": true, "snip_edges": false, "subtract_mean": false, "use_energy": true, "use_log_fbank": true, "use_power": false, "vtln_high": 2920, "vtln_low": 1121, "vtln_warp": 1.0, "window_type": "povey", "dither": 0.0} +{"blackman_coeff": 2.6192, "energy_floor": 1.7209, "frame_length": 1.0625, "frame_shift": 0.625, "high_freq": 2275, "htk_compat": false, "low_freq": 367, "num_mel_bins": 5, "preemphasis_coefficient": 0.27, "raw_energy": false, "remove_dc_offset": true, "round_to_power_of_two": true, "snip_edges": true, "subtract_mean": false, "use_energy": true, "use_log_fbank": false, "use_power": true, "vtln_high": 1293, "vtln_low": 771, "vtln_warp": 1.0, "window_type": "blackman", "dither": 0.0} +{"blackman_coeff": 2.6578, "energy_floor": 0.9137, "frame_length": 1.1875, "frame_shift": 1.0, "high_freq": 4898, "htk_compat": true, "low_freq": 886, "num_mel_bins": 7, "preemphasis_coefficient": 0.57, "raw_energy": true, "remove_dc_offset": false, "round_to_power_of_two": true, "snip_edges": false, "subtract_mean": true, "use_energy": true, "use_log_fbank": false, "use_power": false, "vtln_high": 3704, "vtln_low": 1013, "vtln_warp": 1.0, "window_type": "povey", "dither": 0.0} +{"blackman_coeff": 2.7083, "energy_floor": 2.8806, "frame_length": 0.75, "frame_shift": 0.9375, "high_freq": 6605, "htk_compat": false, "low_freq": 3759, "num_mel_bins": 4, "preemphasis_coefficient": 0.9, "raw_energy": true, "remove_dc_offset": false, "round_to_power_of_two": true, "snip_edges": true, "subtract_mean": false, "use_energy": false, "use_log_fbank": false, "use_power": true, "vtln_high": 6542, "vtln_low": 5821, "vtln_warp": 1.0, "window_type": "rectangular", "dither": 0.0} +{"blackman_coeff": 2.7704, "energy_floor": 4.5251, "frame_length": 1.125, "frame_shift": 0.875, "high_freq": 3819, "htk_compat": true, "low_freq": 787, "num_mel_bins": 5, "preemphasis_coefficient": 0.23, "raw_energy": false, "remove_dc_offset": false, "round_to_power_of_two": true, "snip_edges": true, "subtract_mean": true, "use_energy": true, "use_log_fbank": false, "use_power": false, "vtln_high": 3368, "vtln_low": 3286, "vtln_warp": 1.0, "window_type": "hamming", "dither": 0.0} +{"blackman_coeff": 2.9255, "energy_floor": 3.4363, "frame_length": 1.125, "frame_shift": 1.0, "high_freq": 7660, "htk_compat": false, "low_freq": 5020, "num_mel_bins": 5, "preemphasis_coefficient": 0.09, "raw_energy": true, "remove_dc_offset": false, "round_to_power_of_two": true, "snip_edges": true, "subtract_mean": true, "use_energy": true, "use_log_fbank": false, "use_power": false, "vtln_high": 7470, "vtln_low": 6783, "vtln_warp": 1.0, "window_type": "hamming", "dither": 0.0} +{"blackman_coeff": 3.0009, "energy_floor": 1.845, "frame_length": 1.0625, "frame_shift": 0.75, "high_freq": 5812, "htk_compat": true, "low_freq": 1287, "num_mel_bins": 6, "preemphasis_coefficient": 0.22, "raw_energy": false, "remove_dc_offset": false, "round_to_power_of_two": true, "snip_edges": true, "subtract_mean": true, "use_energy": true, "use_log_fbank": false, "use_power": false, "vtln_high": 5573, "vtln_low": 4642, "vtln_warp": 1.0, "window_type": "hanning", "dither": 0.0} +{"blackman_coeff": 3.2195, "energy_floor": 2.9858, "frame_length": 1.0625, "frame_shift": 0.0625, "high_freq": 6899, "htk_compat": true, "low_freq": 4117, "num_mel_bins": 6, "preemphasis_coefficient": 0.85, "raw_energy": true, "remove_dc_offset": true, "round_to_power_of_two": true, "snip_edges": true, "subtract_mean": false, "use_energy": false, "use_log_fbank": true, "use_power": true, "vtln_high": 5077, "vtln_low": 4977, "vtln_warp": 0.8739, "window_type": "rectangular", "dither": 0.0} +{"blackman_coeff": 3.3208, "energy_floor": 1.5569, "frame_length": 1.0, "frame_shift": 0.3125, "high_freq": 4556, "htk_compat": false, "low_freq": 334, "num_mel_bins": 5, "preemphasis_coefficient": 0.02, "raw_energy": false, "remove_dc_offset": true, "round_to_power_of_two": true, "snip_edges": true, "subtract_mean": true, "use_energy": false, "use_log_fbank": true, "use_power": false, "vtln_high": 2831, "vtln_low": 696, "vtln_warp": 1.0, "window_type": "hanning", "dither": 0.0} +{"blackman_coeff": 3.3976, "energy_floor": 3.9462, "frame_length": 1.1875, "frame_shift": 0.5625, "high_freq": 6513, "htk_compat": false, "low_freq": 3398, "num_mel_bins": 8, "preemphasis_coefficient": 0.38, "raw_energy": true, "remove_dc_offset": true, "round_to_power_of_two": true, "snip_edges": false, "subtract_mean": false, "use_energy": false, "use_log_fbank": true, "use_power": false, "vtln_high": 5827, "vtln_low": 5388, "vtln_warp": 1.0, "window_type": "blackman", "dither": 0.0} +{"blackman_coeff": 3.5842, "energy_floor": 1.2264, "frame_length": 0.9375, "frame_shift": 1.0, "high_freq": 7744, "htk_compat": false, "low_freq": 195, "num_mel_bins": 5, "preemphasis_coefficient": 0.62, "raw_energy": false, "remove_dc_offset": false, "round_to_power_of_two": true, "snip_edges": false, "subtract_mean": false, "use_energy": true, "use_log_fbank": true, "use_power": false, "vtln_high": 7667, "vtln_low": 2993, "vtln_warp": 1.0, "window_type": "hamming", "dither": 0.0} +{"blackman_coeff": 3.5889, "energy_floor": 3.3559, "frame_length": 1.0, "frame_shift": 1.1875, "high_freq": 7354, "htk_compat": true, "low_freq": 997, "num_mel_bins": 5, "preemphasis_coefficient": 0.98, "raw_energy": false, "remove_dc_offset": true, "round_to_power_of_two": true, "snip_edges": true, "subtract_mean": true, "use_energy": false, "use_log_fbank": false, "use_power": false, "vtln_high": 7088, "vtln_low": 6494, "vtln_warp": 1.0, "window_type": "povey", "dither": 0.0} +{"blackman_coeff": 3.5936, "energy_floor": 2.1701, "frame_length": 1.0625, "frame_shift": 1.0625, "high_freq": 7407, "htk_compat": true, "low_freq": 3649, "num_mel_bins": 5, "preemphasis_coefficient": 0.65, "raw_energy": false, "remove_dc_offset": true, "round_to_power_of_two": true, "snip_edges": true, "subtract_mean": false, "use_energy": true, "use_log_fbank": true, "use_power": true, "vtln_high": 6878, "vtln_low": 6036, "vtln_warp": 1.0, "window_type": "povey", "dither": 0.0} +{"blackman_coeff": 3.7002, "energy_floor": 3.567, "frame_length": 1.1875, "frame_shift": 0.625, "high_freq": 4479, "htk_compat": true, "low_freq": 2240, "num_mel_bins": 6, "preemphasis_coefficient": 0.73, "raw_energy": false, "remove_dc_offset": false, "round_to_power_of_two": true, "snip_edges": false, "subtract_mean": false, "use_energy": true, "use_log_fbank": false, "use_power": true, "vtln_high": 4084, "vtln_low": 3955, "vtln_warp": 1.0, "window_type": "hamming", "dither": 0.0} +{"blackman_coeff": 3.7078, "energy_floor": 0.3892, "frame_length": 0.8125, "frame_shift": 0.3125, "high_freq": 7876, "htk_compat": true, "low_freq": 2830, "num_mel_bins": 7, "preemphasis_coefficient": 0.46, "raw_energy": false, "remove_dc_offset": false, "round_to_power_of_two": true, "snip_edges": true, "subtract_mean": true, "use_energy": false, "use_log_fbank": false, "use_power": true, "vtln_high": 4726, "vtln_low": 2918, "vtln_warp": 1.0, "window_type": "rectangular", "dither": 0.0} +{"blackman_coeff": 3.7585, "energy_floor": 2.9425, "frame_length": 1.1875, "frame_shift": 1.0, "high_freq": 3277, "htk_compat": true, "low_freq": 2244, "num_mel_bins": 4, "preemphasis_coefficient": 0.76, "raw_energy": false, "remove_dc_offset": false, "round_to_power_of_two": true, "snip_edges": false, "subtract_mean": true, "use_energy": false, "use_log_fbank": false, "use_power": false, "vtln_high": 3158, "vtln_low": 2865, "vtln_warp": 1.0, "window_type": "rectangular", "dither": 0.0} +{"blackman_coeff": 3.7772, "energy_floor": 2.8211, "frame_length": 1.0, "frame_shift": 0.1875, "high_freq": 3747, "htk_compat": false, "low_freq": 1244, "num_mel_bins": 4, "preemphasis_coefficient": 0.64, "raw_energy": false, "remove_dc_offset": true, "round_to_power_of_two": true, "snip_edges": false, "subtract_mean": true, "use_energy": false, "use_log_fbank": false, "use_power": true, "vtln_high": 3640, "vtln_low": 2770, "vtln_warp": 1.0, "window_type": "hanning", "dither": 0.0} +{"blackman_coeff": 3.8514, "energy_floor": 3.7933, "frame_length": 1.0625, "frame_shift": 0.5, "high_freq": 4136, "htk_compat": true, "low_freq": 1010, "num_mel_bins": 6, "preemphasis_coefficient": 0.12, "raw_energy": false, "remove_dc_offset": false, "round_to_power_of_two": true, "snip_edges": false, "subtract_mean": false, "use_energy": true, "use_log_fbank": true, "use_power": false, "vtln_high": 2408, "vtln_low": 1892, "vtln_warp": 1.0, "window_type": "hanning", "dither": 0.0} +{"blackman_coeff": 3.8677, "energy_floor": 2.5418, "frame_length": 1.0625, "frame_shift": 0.0625, "high_freq": 3496, "htk_compat": true, "low_freq": 309, "num_mel_bins": 4, "preemphasis_coefficient": 0.47, "raw_energy": false, "remove_dc_offset": false, "round_to_power_of_two": true, "snip_edges": false, "subtract_mean": false, "use_energy": false, "use_log_fbank": true, "use_power": false, "vtln_high": 1490, "vtln_low": 645, "vtln_warp": 1.0, "window_type": "rectangular", "dither": 0.0} +{"blackman_coeff": 3.9033, "energy_floor": 2.677, "frame_length": 1.125, "frame_shift": 0.875, "high_freq": 5699, "htk_compat": false, "low_freq": 2960, "num_mel_bins": 7, "preemphasis_coefficient": 0.52, "raw_energy": true, "remove_dc_offset": true, "round_to_power_of_two": true, "snip_edges": true, "subtract_mean": true, "use_energy": true, "use_log_fbank": false, "use_power": false, "vtln_high": 5458, "vtln_low": 5400, "vtln_warp": 1.0, "window_type": "rectangular", "dither": 0.0} +{"blackman_coeff": 4.0371, "energy_floor": 3.7559, "frame_length": 1.0625, "frame_shift": 0.8125, "high_freq": 4280, "htk_compat": false, "low_freq": 1207, "num_mel_bins": 4, "preemphasis_coefficient": 0.12, "raw_energy": true, "remove_dc_offset": false, "round_to_power_of_two": true, "snip_edges": true, "subtract_mean": true, "use_energy": true, "use_log_fbank": false, "use_power": true, "vtln_high": 3686, "vtln_low": 2010, "vtln_warp": 1.0, "window_type": "hamming", "dither": 0.0} +{"blackman_coeff": 4.0757, "energy_floor": 4.7442, "frame_length": 0.875, "frame_shift": 1.125, "high_freq": 6363, "htk_compat": true, "low_freq": 1524, "num_mel_bins": 4, "preemphasis_coefficient": 0.32, "raw_energy": true, "remove_dc_offset": false, "round_to_power_of_two": false, "snip_edges": true, "subtract_mean": false, "use_energy": true, "use_log_fbank": true, "use_power": false, "vtln_high": 5178, "vtln_low": 4628, "vtln_warp": 1.0, "window_type": "blackman", "dither": 0.0} +{"blackman_coeff": 4.1248, "energy_floor": 2.5255, "frame_length": 0.6875, "frame_shift": 0.6875, "high_freq": 3527, "htk_compat": true, "low_freq": 1701, "num_mel_bins": 4, "preemphasis_coefficient": 0.43, "raw_energy": true, "remove_dc_offset": true, "round_to_power_of_two": true, "snip_edges": true, "subtract_mean": true, "use_energy": true, "use_log_fbank": false, "use_power": true, "vtln_high": 2884, "vtln_low": 1773, "vtln_warp": 1.0, "window_type": "blackman", "dither": 0.0} +{"blackman_coeff": 4.18, "energy_floor": 4.6907, "frame_length": 1.1875, "frame_shift": 0.5625, "high_freq": 7316, "htk_compat": true, "low_freq": 3483, "num_mel_bins": 8, "preemphasis_coefficient": 0.61, "raw_energy": false, "remove_dc_offset": true, "round_to_power_of_two": true, "snip_edges": false, "subtract_mean": true, "use_energy": true, "use_log_fbank": true, "use_power": true, "vtln_high": 5820, "vtln_low": 4635, "vtln_warp": 1.0, "window_type": "rectangular", "dither": 0.0} +{"blackman_coeff": 4.2251, "energy_floor": 0.5, "frame_length": 0.875, "frame_shift": 0.625, "high_freq": 7515, "htk_compat": false, "low_freq": 1751, "num_mel_bins": 5, "preemphasis_coefficient": 0.64, "raw_energy": true, "remove_dc_offset": true, "round_to_power_of_two": true, "snip_edges": true, "subtract_mean": false, "use_energy": false, "use_log_fbank": true, "use_power": false, "vtln_high": 7486, "vtln_low": 4238, "vtln_warp": 1.0, "window_type": "hamming", "dither": 0.0} +{"blackman_coeff": 4.3011, "energy_floor": 1.4663, "frame_length": 1.125, "frame_shift": 0.9375, "high_freq": 7804, "htk_compat": false, "low_freq": 1208, "num_mel_bins": 6, "preemphasis_coefficient": 0.18, "raw_energy": false, "remove_dc_offset": false, "round_to_power_of_two": true, "snip_edges": false, "subtract_mean": false, "use_energy": true, "use_log_fbank": true, "use_power": false, "vtln_high": 7421, "vtln_low": 3707, "vtln_warp": 1.0, "window_type": "hanning", "dither": 0.0} +{"blackman_coeff": 4.3252, "energy_floor": 0.7732, "frame_length": 0.625, "frame_shift": 0.6875, "high_freq": 7389, "htk_compat": false, "low_freq": 2071, "num_mel_bins": 4, "preemphasis_coefficient": 0.08, "raw_energy": true, "remove_dc_offset": false, "round_to_power_of_two": true, "snip_edges": false, "subtract_mean": false, "use_energy": true, "use_log_fbank": false, "use_power": false, "vtln_high": 6900, "vtln_low": 2344, "vtln_warp": 1.0, "window_type": "blackman", "dither": 0.0} +{"blackman_coeff": 4.3693, "energy_floor": 3.9073, "frame_length": 0.875, "frame_shift": 0.9375, "high_freq": 6107, "htk_compat": true, "low_freq": 3905, "num_mel_bins": 4, "preemphasis_coefficient": 0.86, "raw_energy": true, "remove_dc_offset": false, "round_to_power_of_two": true, "snip_edges": false, "subtract_mean": true, "use_energy": true, "use_log_fbank": false, "use_power": true, "vtln_high": 5001, "vtln_low": 4046, "vtln_warp": 1.0, "window_type": "rectangular", "dither": 0.0} +{"blackman_coeff": 4.3926, "energy_floor": 2.0617, "frame_length": 0.5625, "frame_shift": 0.0625, "high_freq": 4253, "htk_compat": true, "low_freq": 1367, "num_mel_bins": 5, "preemphasis_coefficient": 0.84, "raw_energy": false, "remove_dc_offset": true, "round_to_power_of_two": true, "snip_edges": true, "subtract_mean": false, "use_energy": true, "use_log_fbank": true, "use_power": false, "vtln_high": 2112, "vtln_low": 1445, "vtln_warp": 1.0, "window_type": "hamming", "dither": 0.0} +{"blackman_coeff": 4.4706, "energy_floor": 1.7516, "frame_length": 1.125, "frame_shift": 1.125, "high_freq": 7645, "htk_compat": false, "low_freq": 225, "num_mel_bins": 6, "preemphasis_coefficient": 0.8, "raw_energy": false, "remove_dc_offset": false, "round_to_power_of_two": false, "snip_edges": true, "subtract_mean": false, "use_energy": false, "use_log_fbank": false, "use_power": false, "vtln_high": 3717, "vtln_low": 304, "vtln_warp": 1.0, "window_type": "blackman", "dither": 0.0} +{"blackman_coeff": 4.5385, "energy_floor": 2.1519, "frame_length": 1.125, "frame_shift": 0.0625, "high_freq": 5610, "htk_compat": false, "low_freq": 1239, "num_mel_bins": 7, "preemphasis_coefficient": 0.87, "raw_energy": false, "remove_dc_offset": true, "round_to_power_of_two": false, "snip_edges": true, "subtract_mean": true, "use_energy": true, "use_log_fbank": true, "use_power": false, "vtln_high": 2231, "vtln_low": 1432, "vtln_warp": 1.0, "window_type": "rectangular", "dither": 0.0} +{"blackman_coeff": 4.6337, "energy_floor": 2.902, "frame_length": 0.875, "frame_shift": 1.125, "high_freq": 5072, "htk_compat": true, "low_freq": 826, "num_mel_bins": 4, "preemphasis_coefficient": 0.37, "raw_energy": true, "remove_dc_offset": true, "round_to_power_of_two": true, "snip_edges": true, "subtract_mean": false, "use_energy": false, "use_log_fbank": false, "use_power": false, "vtln_high": 4253, "vtln_low": 2427, "vtln_warp": 0.7049, "window_type": "povey", "dither": 0.0} +{"blackman_coeff": 4.7468, "energy_floor": 2.1835, "frame_length": 0.6875, "frame_shift": 1.0, "high_freq": 5153, "htk_compat": true, "low_freq": 943, "num_mel_bins": 5, "preemphasis_coefficient": 0.94, "raw_energy": false, "remove_dc_offset": false, "round_to_power_of_two": true, "snip_edges": true, "subtract_mean": true, "use_energy": false, "use_log_fbank": false, "use_power": false, "vtln_high": 3287, "vtln_low": 1478, "vtln_warp": 0.9406, "window_type": "hanning", "dither": 0.0} +{"blackman_coeff": 4.7855, "energy_floor": 2.1377, "frame_length": 0.9375, "frame_shift": 0.8125, "high_freq": 4123, "htk_compat": false, "low_freq": 587, "num_mel_bins": 4, "preemphasis_coefficient": 0.92, "raw_energy": true, "remove_dc_offset": false, "round_to_power_of_two": true, "snip_edges": false, "subtract_mean": true, "use_energy": false, "use_log_fbank": true, "use_power": false, "vtln_high": 2588, "vtln_low": 2346, "vtln_warp": 1.0, "window_type": "rectangular", "dither": 0.0} +{"blackman_coeff": 4.964, "energy_floor": 3.4931, "frame_length": 1.1875, "frame_shift": 1.0, "high_freq": 4235, "htk_compat": true, "low_freq": 1036, "num_mel_bins": 4, "preemphasis_coefficient": 0.43, "raw_energy": false, "remove_dc_offset": true, "round_to_power_of_two": true, "snip_edges": false, "subtract_mean": true, "use_energy": true, "use_log_fbank": false, "use_power": false, "vtln_high": 3706, "vtln_low": 2840, "vtln_warp": 1.0, "window_type": "hamming", "dither": 0.0} diff --git a/test/assets/kaldi_test_mfcc_args.json b/test/assets/kaldi_test_mfcc_args.json new file mode 100644 index 0000000000..7ec5959dc1 --- /dev/null +++ b/test/assets/kaldi_test_mfcc_args.json @@ -0,0 +1,117 @@ +{"blackman_coeff": 0.0063, "energy_floor": 3.0323, "frame_length": 0.625, "frame_shift": 0.0625, "high_freq": 5842, "htk_compat": false, "low_freq": 3240, "num_mel_bins": 4, "preemphasis_coefficient": 0.29, "raw_energy": true, "remove_dc_offset": false, "round_to_power_of_two": true, "snip_edges": true, "subtract_mean": true, "use_energy": true, "num_ceps": 2, "cepstral_lifter": 73.5792, "vtln_high": 5749, "vtln_low": 4449, "vtln_warp": 1.0, "window_type": "blackman", "dither": 0.0} +{"blackman_coeff": 0.013, "energy_floor": 1.8509, "frame_length": 1.1875, "frame_shift": 0.625, "high_freq": 7999, "htk_compat": false, "low_freq": 4330, "num_mel_bins": 5, "preemphasis_coefficient": 0.38, "raw_energy": true, "remove_dc_offset": false, "round_to_power_of_two": true, "snip_edges": false, "subtract_mean": false, "use_energy": true, "num_ceps": 3, "cepstral_lifter": 8.1048, "vtln_high": 7497, "vtln_low": 7397, "vtln_warp": 1.0, "window_type": "blackman", "dither": 0.0} +{"blackman_coeff": 0.0487, "energy_floor": 1.3641, "frame_length": 1.0, "frame_shift": 0.8125, "high_freq": 7892, "htk_compat": true, "low_freq": 1904, "num_mel_bins": 8, "preemphasis_coefficient": 0.26, "raw_energy": true, "remove_dc_offset": true, "round_to_power_of_two": true, "snip_edges": false, "subtract_mean": false, "use_energy": false, "num_ceps": 5, "cepstral_lifter": 34.0918, "vtln_high": 4400, "vtln_low": 2737, "vtln_warp": 1.0, "window_type": "rectangular", "dither": 0.0} +{"blackman_coeff": 0.0577, "energy_floor": 2.4313, "frame_length": 1.0625, "frame_shift": 0.875, "high_freq": 2922, "htk_compat": true, "low_freq": 274, "num_mel_bins": 6, "preemphasis_coefficient": 0.48, "raw_energy": false, "remove_dc_offset": false, "round_to_power_of_two": true, "snip_edges": true, "subtract_mean": false, "use_energy": true, "num_ceps": 5, "cepstral_lifter": 21.3007, "vtln_high": 1352, "vtln_low": 280, "vtln_warp": 1.0, "window_type": "hanning", "dither": 0.0} +{"blackman_coeff": 0.0718, "energy_floor": 1.3071, "frame_length": 1.1875, "frame_shift": 0.5, "high_freq": 3159, "htk_compat": true, "low_freq": 759, "num_mel_bins": 8, "preemphasis_coefficient": 0.04, "raw_energy": false, "remove_dc_offset": true, "round_to_power_of_two": true, "snip_edges": true, "subtract_mean": true, "use_energy": true, "num_ceps": 6, "cepstral_lifter": 2.6493, "vtln_high": 3145, "vtln_low": 3119, "vtln_warp": 1.0, "window_type": "povey", "dither": 0.0} +{"blackman_coeff": 0.083, "energy_floor": 2.1607, "frame_length": 0.75, "frame_shift": 0.75, "high_freq": 5872, "htk_compat": true, "low_freq": 708, "num_mel_bins": 5, "preemphasis_coefficient": 0.95, "raw_energy": false, "remove_dc_offset": false, "round_to_power_of_two": false, "snip_edges": false, "subtract_mean": false, "use_energy": true, "num_ceps": 4, "cepstral_lifter": 24.5097, "vtln_high": 5231, "vtln_low": 3888, "vtln_warp": 1.0, "window_type": "hamming", "dither": 0.0} +{"blackman_coeff": 0.0933, "energy_floor": 1.577, "frame_length": 1.1875, "frame_shift": 1.1875, "high_freq": 7519, "htk_compat": false, "low_freq": 357, "num_mel_bins": 4, "preemphasis_coefficient": 0.5, "raw_energy": false, "remove_dc_offset": false, "round_to_power_of_two": true, "snip_edges": true, "subtract_mean": true, "use_energy": false, "num_ceps": 2, "cepstral_lifter": 88.0941, "vtln_high": 7042, "vtln_low": 5298, "vtln_warp": 1.0, "window_type": "rectangular", "dither": 0.0} +{"blackman_coeff": 0.1048, "energy_floor": 0.5013, "frame_length": 0.75, "frame_shift": 1.0625, "high_freq": 6426, "htk_compat": true, "low_freq": 3613, "num_mel_bins": 5, "preemphasis_coefficient": 0.96, "raw_energy": false, "remove_dc_offset": false, "round_to_power_of_two": true, "snip_edges": true, "subtract_mean": false, "use_energy": true, "num_ceps": 4, "cepstral_lifter": 73.5838, "vtln_high": 5816, "vtln_low": 3997, "vtln_warp": 1.0, "window_type": "povey", "dither": 0.0} +{"blackman_coeff": 0.1447, "energy_floor": 4.7142, "frame_length": 1.0625, "frame_shift": 0.4375, "high_freq": 7629, "htk_compat": true, "low_freq": 3498, "num_mel_bins": 7, "preemphasis_coefficient": 0.39, "raw_energy": true, "remove_dc_offset": true, "round_to_power_of_two": true, "snip_edges": true, "subtract_mean": true, "use_energy": false, "num_ceps": 3, "cepstral_lifter": 19.4145, "vtln_high": 7169, "vtln_low": 6751, "vtln_warp": 1.0, "window_type": "hanning", "dither": 0.0} +{"blackman_coeff": 0.1473, "energy_floor": 4.9154, "frame_length": 1.125, "frame_shift": 0.875, "high_freq": 3631, "htk_compat": false, "low_freq": 1229, "num_mel_bins": 8, "preemphasis_coefficient": 0.04, "raw_energy": true, "remove_dc_offset": true, "round_to_power_of_two": true, "snip_edges": false, "subtract_mean": true, "use_energy": true, "num_ceps": 3, "cepstral_lifter": 34.479, "vtln_high": 3390, "vtln_low": 1536, "vtln_warp": 1.0, "window_type": "blackman", "dither": 0.0} +{"blackman_coeff": 0.1485, "energy_floor": 4.275, "frame_length": 0.6875, "frame_shift": 0.75, "high_freq": 5222, "htk_compat": true, "low_freq": 311, "num_mel_bins": 5, "preemphasis_coefficient": 0.31, "raw_energy": false, "remove_dc_offset": true, "round_to_power_of_two": true, "snip_edges": true, "subtract_mean": true, "use_energy": true, "num_ceps": 3, "cepstral_lifter": 48.7991, "vtln_high": 4833, "vtln_low": 513, "vtln_warp": 1.0, "window_type": "hanning", "dither": 0.0} +{"blackman_coeff": 0.1829, "energy_floor": 4.5358, "frame_length": 0.9375, "frame_shift": 0.9375, "high_freq": 6148, "htk_compat": true, "low_freq": 455, "num_mel_bins": 5, "preemphasis_coefficient": 0.59, "raw_energy": true, "remove_dc_offset": false, "round_to_power_of_two": true, "snip_edges": false, "subtract_mean": false, "use_energy": false, "num_ceps": 3, "cepstral_lifter": 48.6724, "vtln_high": 3138, "vtln_low": 2247, "vtln_warp": 1.0, "window_type": "blackman", "dither": 0.0} +{"blackman_coeff": 0.2002, "energy_floor": 1.4805, "frame_length": 0.9375, "frame_shift": 0.875, "high_freq": 7621, "htk_compat": false, "low_freq": 2232, "num_mel_bins": 5, "preemphasis_coefficient": 0.03, "raw_energy": false, "remove_dc_offset": false, "round_to_power_of_two": true, "snip_edges": true, "subtract_mean": false, "use_energy": true, "num_ceps": 5, "cepstral_lifter": 69.3653, "vtln_high": 7087, "vtln_low": 2800, "vtln_warp": 1.0, "window_type": "blackman", "dither": 0.0} +{"blackman_coeff": 0.2107, "energy_floor": 3.475, "frame_length": 1.125, "frame_shift": 0.8125, "high_freq": 5701, "htk_compat": true, "low_freq": 1629, "num_mel_bins": 4, "preemphasis_coefficient": 0.09, "raw_energy": true, "remove_dc_offset": false, "round_to_power_of_two": true, "snip_edges": false, "subtract_mean": true, "use_energy": true, "num_ceps": 2, "cepstral_lifter": 77.7066, "vtln_high": 5622, "vtln_low": 5544, "vtln_warp": 1.0, "window_type": "blackman", "dither": 0.0} +{"blackman_coeff": 0.2523, "energy_floor": 0.148, "frame_length": 1.0, "frame_shift": 1.125, "high_freq": 5833, "htk_compat": false, "low_freq": 556, "num_mel_bins": 4, "preemphasis_coefficient": 0.66, "raw_energy": true, "remove_dc_offset": true, "round_to_power_of_two": true, "snip_edges": true, "subtract_mean": true, "use_energy": false, "num_ceps": 4, "cepstral_lifter": 57.0398, "vtln_high": 4519, "vtln_low": 3600, "vtln_warp": 1.0, "window_type": "rectangular", "dither": 0.0} +{"blackman_coeff": 0.2959, "energy_floor": 2.3729, "frame_length": 0.625, "frame_shift": 0.5, "high_freq": 6757, "htk_compat": false, "low_freq": 1744, "num_mel_bins": 6, "preemphasis_coefficient": 0.2, "raw_energy": true, "remove_dc_offset": false, "round_to_power_of_two": true, "snip_edges": true, "subtract_mean": true, "use_energy": false, "num_ceps": 2, "cepstral_lifter": 99.871, "vtln_high": 4957, "vtln_low": 3549, "vtln_warp": 1.0, "window_type": "povey", "dither": 0.0} +{"blackman_coeff": 0.3642, "energy_floor": 3.5246, "frame_length": 0.4375, "frame_shift": 0.9375, "high_freq": 7942, "htk_compat": false, "low_freq": 3282, "num_mel_bins": 4, "preemphasis_coefficient": 0.52, "raw_energy": false, "remove_dc_offset": false, "round_to_power_of_two": true, "snip_edges": true, "subtract_mean": false, "use_energy": false, "num_ceps": 3, "cepstral_lifter": 74.4735, "vtln_high": 5601, "vtln_low": 4966, "vtln_warp": 1.0, "window_type": "blackman", "dither": 0.0} +{"blackman_coeff": 0.4891, "energy_floor": 1.989, "frame_length": 1.125, "frame_shift": 0.875, "high_freq": 3219, "htk_compat": true, "low_freq": 973, "num_mel_bins": 5, "preemphasis_coefficient": 0.91, "raw_energy": false, "remove_dc_offset": false, "round_to_power_of_two": true, "snip_edges": true, "subtract_mean": true, "use_energy": true, "num_ceps": 4, "cepstral_lifter": 85.357, "vtln_high": 3181, "vtln_low": 3129, "vtln_warp": 1.0, "window_type": "hamming", "dither": 0.0} +{"blackman_coeff": 0.5428, "energy_floor": 1.2368, "frame_length": 0.5625, "frame_shift": 1.0, "high_freq": 6700, "htk_compat": false, "low_freq": 749, "num_mel_bins": 4, "preemphasis_coefficient": 0.86, "raw_energy": false, "remove_dc_offset": false, "round_to_power_of_two": true, "snip_edges": true, "subtract_mean": true, "use_energy": true, "num_ceps": 2, "cepstral_lifter": 16.2782, "vtln_high": 5573, "vtln_low": 4988, "vtln_warp": 1.0, "window_type": "rectangular", "dither": 0.0} +{"blackman_coeff": 0.5495, "energy_floor": 2.9502, "frame_length": 1.1875, "frame_shift": 1.1875, "high_freq": 3873, "htk_compat": true, "low_freq": 1564, "num_mel_bins": 5, "preemphasis_coefficient": 0.05, "raw_energy": false, "remove_dc_offset": true, "round_to_power_of_two": true, "snip_edges": false, "subtract_mean": true, "use_energy": false, "num_ceps": 5, "cepstral_lifter": 59.0075, "vtln_high": 3870, "vtln_low": 3750, "vtln_warp": 1.0, "window_type": "hanning", "dither": 0.0} +{"blackman_coeff": 0.6457, "energy_floor": 2.0199, "frame_length": 0.875, "frame_shift": 0.8125, "high_freq": 6510, "htk_compat": false, "low_freq": 1482, "num_mel_bins": 4, "preemphasis_coefficient": 0.26, "raw_energy": false, "remove_dc_offset": true, "round_to_power_of_two": false, "snip_edges": true, "subtract_mean": false, "use_energy": true, "num_ceps": 2, "cepstral_lifter": 49.7663, "vtln_high": 5461, "vtln_low": 4039, "vtln_warp": 1.0, "window_type": "blackman", "dither": 0.0} +{"blackman_coeff": 0.7031, "energy_floor": 4.038, "frame_length": 1.125, "frame_shift": 0.6875, "high_freq": 6433, "htk_compat": true, "low_freq": 2336, "num_mel_bins": 8, "preemphasis_coefficient": 0.7, "raw_energy": false, "remove_dc_offset": true, "round_to_power_of_two": false, "snip_edges": true, "subtract_mean": true, "use_energy": false, "num_ceps": 3, "cepstral_lifter": 18.0061, "vtln_high": 5902, "vtln_low": 3191, "vtln_warp": 1.0, "window_type": "rectangular", "dither": 0.0} +{"blackman_coeff": 0.7197, "energy_floor": 3.2075, "frame_length": 1.0625, "frame_shift": 0.25, "high_freq": 4448, "htk_compat": true, "low_freq": 378, "num_mel_bins": 4, "preemphasis_coefficient": 0.31, "raw_energy": true, "remove_dc_offset": false, "round_to_power_of_two": true, "snip_edges": false, "subtract_mean": false, "use_energy": false, "num_ceps": 2, "cepstral_lifter": 71.591, "vtln_high": 3497, "vtln_low": 3331, "vtln_warp": 1.0, "window_type": "hanning", "dither": 0.0} +{"blackman_coeff": 0.7238, "energy_floor": 1.9087, "frame_length": 1.1875, "frame_shift": 0.75, "high_freq": 5457, "htk_compat": true, "low_freq": 1775, "num_mel_bins": 7, "preemphasis_coefficient": 0.48, "raw_energy": true, "remove_dc_offset": false, "round_to_power_of_two": true, "snip_edges": true, "subtract_mean": true, "use_energy": true, "num_ceps": 3, "cepstral_lifter": 29.2858, "vtln_high": 5349, "vtln_low": 3987, "vtln_warp": 1.0, "window_type": "rectangular", "dither": 0.0} +{"blackman_coeff": 0.7507, "energy_floor": 0.2754, "frame_length": 0.875, "frame_shift": 0.8125, "high_freq": 6405, "htk_compat": false, "low_freq": 1972, "num_mel_bins": 5, "preemphasis_coefficient": 0.83, "raw_energy": false, "remove_dc_offset": true, "round_to_power_of_two": false, "snip_edges": true, "subtract_mean": true, "use_energy": true, "num_ceps": 2, "cepstral_lifter": 52.5962, "vtln_high": 4597, "vtln_low": 4417, "vtln_warp": 1.0, "window_type": "povey", "dither": 0.0} +{"blackman_coeff": 0.7954, "energy_floor": 0.3451, "frame_length": 1.1875, "frame_shift": 0.625, "high_freq": 4078, "htk_compat": false, "low_freq": 796, "num_mel_bins": 8, "preemphasis_coefficient": 0.47, "raw_energy": true, "remove_dc_offset": false, "round_to_power_of_two": true, "snip_edges": true, "subtract_mean": false, "use_energy": true, "num_ceps": 8, "cepstral_lifter": 42.3128, "vtln_high": 2299, "vtln_low": 1094, "vtln_warp": 1.0, "window_type": "blackman", "dither": 0.0} +{"blackman_coeff": 0.8432, "energy_floor": 1.3765, "frame_length": 0.9375, "frame_shift": 1.1875, "high_freq": 6004, "htk_compat": true, "low_freq": 2302, "num_mel_bins": 4, "preemphasis_coefficient": 0.6, "raw_energy": false, "remove_dc_offset": false, "round_to_power_of_two": true, "snip_edges": false, "subtract_mean": true, "use_energy": true, "num_ceps": 4, "cepstral_lifter": 74.1116, "vtln_high": 4129, "vtln_low": 2898, "vtln_warp": 1.0, "window_type": "hamming", "dither": 0.0} +{"blackman_coeff": 0.8549, "energy_floor": 4.8924, "frame_length": 0.3125, "frame_shift": 1.125, "high_freq": 5643, "htk_compat": true, "low_freq": 956, "num_mel_bins": 4, "preemphasis_coefficient": 0.32, "raw_energy": true, "remove_dc_offset": false, "round_to_power_of_two": true, "snip_edges": false, "subtract_mean": false, "use_energy": true, "num_ceps": 2, "cepstral_lifter": 76.0384, "vtln_high": 2672, "vtln_low": 1762, "vtln_warp": 1.0, "window_type": "rectangular", "dither": 0.0} +{"blackman_coeff": 0.9502, "energy_floor": 1.9738, "frame_length": 0.75, "frame_shift": 0.25, "high_freq": 7773, "htk_compat": true, "low_freq": 1205, "num_mel_bins": 7, "preemphasis_coefficient": 0.5, "raw_energy": false, "remove_dc_offset": false, "round_to_power_of_two": true, "snip_edges": false, "subtract_mean": false, "use_energy": true, "num_ceps": 3, "cepstral_lifter": 62.9038, "vtln_high": 7460, "vtln_low": 7174, "vtln_warp": 1.0, "window_type": "blackman", "dither": 0.0} +{"blackman_coeff": 1.0759, "energy_floor": 1.9132, "frame_length": 1.1875, "frame_shift": 0.625, "high_freq": 3529, "htk_compat": false, "low_freq": 227, "num_mel_bins": 8, "preemphasis_coefficient": 0.26, "raw_energy": true, "remove_dc_offset": false, "round_to_power_of_two": true, "snip_edges": true, "subtract_mean": false, "use_energy": true, "num_ceps": 4, "cepstral_lifter": 4.1559, "vtln_high": 1976, "vtln_low": 972, "vtln_warp": 1.0, "window_type": "hanning", "dither": 0.0} +{"blackman_coeff": 1.147, "energy_floor": 4.3972, "frame_length": 0.9375, "frame_shift": 0.75, "high_freq": 6393, "htk_compat": true, "low_freq": 2451, "num_mel_bins": 4, "preemphasis_coefficient": 0.06, "raw_energy": true, "remove_dc_offset": false, "round_to_power_of_two": true, "snip_edges": true, "subtract_mean": false, "use_energy": true, "num_ceps": 4, "cepstral_lifter": 67.4571, "vtln_high": 5460, "vtln_low": 3654, "vtln_warp": 1.0, "window_type": "povey", "dither": 0.0} +{"blackman_coeff": 1.2069, "energy_floor": 0.4607, "frame_length": 1.125, "frame_shift": 0.5625, "high_freq": 5864, "htk_compat": true, "low_freq": 1512, "num_mel_bins": 7, "preemphasis_coefficient": 0.17, "raw_energy": false, "remove_dc_offset": true, "round_to_power_of_two": true, "snip_edges": false, "subtract_mean": false, "use_energy": true, "num_ceps": 3, "cepstral_lifter": 33.0194, "vtln_high": 5438, "vtln_low": 3920, "vtln_warp": 1.0, "window_type": "blackman", "dither": 0.0} +{"blackman_coeff": 1.3369, "energy_floor": 4.2619, "frame_length": 0.6875, "frame_shift": 0.375, "high_freq": 5307, "htk_compat": true, "low_freq": 666, "num_mel_bins": 6, "preemphasis_coefficient": 0.19, "raw_energy": false, "remove_dc_offset": false, "round_to_power_of_two": true, "snip_edges": true, "subtract_mean": false, "use_energy": true, "num_ceps": 4, "cepstral_lifter": 88.3186, "vtln_high": 4677, "vtln_low": 2590, "vtln_warp": 1.0, "window_type": "hamming", "dither": 0.0} +{"blackman_coeff": 1.3699, "energy_floor": 3.0236, "frame_length": 1.0625, "frame_shift": 0.75, "high_freq": 3720, "htk_compat": true, "low_freq": 1980, "num_mel_bins": 4, "preemphasis_coefficient": 0.13, "raw_energy": true, "remove_dc_offset": true, "round_to_power_of_two": true, "snip_edges": false, "subtract_mean": false, "use_energy": true, "num_ceps": 3, "cepstral_lifter": 57.6793, "vtln_high": 3441, "vtln_low": 3396, "vtln_warp": 1.0, "window_type": "blackman", "dither": 0.0} +{"blackman_coeff": 1.3763, "energy_floor": 1.6574, "frame_length": 1.125, "frame_shift": 0.8125, "high_freq": 2816, "htk_compat": false, "low_freq": 1021, "num_mel_bins": 4, "preemphasis_coefficient": 0.91, "raw_energy": true, "remove_dc_offset": false, "round_to_power_of_two": true, "snip_edges": true, "subtract_mean": true, "use_energy": true, "num_ceps": 2, "cepstral_lifter": 45.2819, "vtln_high": 2547, "vtln_low": 1123, "vtln_warp": 1.0, "window_type": "rectangular", "dither": 0.0} +{"blackman_coeff": 1.4097, "energy_floor": 4.1523, "frame_length": 0.875, "frame_shift": 0.375, "high_freq": 6164, "htk_compat": false, "low_freq": 987, "num_mel_bins": 4, "preemphasis_coefficient": 0.06, "raw_energy": false, "remove_dc_offset": true, "round_to_power_of_two": true, "snip_edges": true, "subtract_mean": false, "use_energy": false, "num_ceps": 3, "cepstral_lifter": 75.0589, "vtln_high": 5873, "vtln_low": 5807, "vtln_warp": 1.0, "window_type": "hamming", "dither": 0.0} +{"blackman_coeff": 1.4295, "energy_floor": 3.7938, "frame_length": 1.125, "frame_shift": 0.75, "high_freq": 3382, "htk_compat": false, "low_freq": 471, "num_mel_bins": 4, "preemphasis_coefficient": 0.42, "raw_energy": false, "remove_dc_offset": false, "round_to_power_of_two": false, "snip_edges": false, "subtract_mean": true, "use_energy": true, "num_ceps": 2, "cepstral_lifter": 78.588, "vtln_high": 3299, "vtln_low": 2540, "vtln_warp": 1.0, "window_type": "hanning", "dither": 0.0} +{"blackman_coeff": 1.4677, "energy_floor": 4.0728, "frame_length": 1.125, "frame_shift": 1.0625, "high_freq": 7698, "htk_compat": true, "low_freq": 569, "num_mel_bins": 6, "preemphasis_coefficient": 0.5, "raw_energy": true, "remove_dc_offset": true, "round_to_power_of_two": false, "snip_edges": true, "subtract_mean": true, "use_energy": false, "num_ceps": 3, "cepstral_lifter": 76.8484, "vtln_high": 7453, "vtln_low": 7251, "vtln_warp": 1.0, "window_type": "rectangular", "dither": 0.0} +{"blackman_coeff": 1.4979, "energy_floor": 1.1705, "frame_length": 1.1875, "frame_shift": 0.375, "high_freq": 4474, "htk_compat": true, "low_freq": 1123, "num_mel_bins": 7, "preemphasis_coefficient": 0.09, "raw_energy": true, "remove_dc_offset": false, "round_to_power_of_two": true, "snip_edges": true, "subtract_mean": false, "use_energy": true, "num_ceps": 4, "cepstral_lifter": 38.6407, "vtln_high": 3043, "vtln_low": 2934, "vtln_warp": 1.0, "window_type": "hamming", "dither": 0.0} +{"blackman_coeff": 1.555, "energy_floor": 1.8728, "frame_length": 0.875, "frame_shift": 0.9375, "high_freq": 5191, "htk_compat": true, "low_freq": 2262, "num_mel_bins": 4, "preemphasis_coefficient": 0.24, "raw_energy": true, "remove_dc_offset": true, "round_to_power_of_two": true, "snip_edges": false, "subtract_mean": true, "use_energy": false, "num_ceps": 2, "cepstral_lifter": 11.982, "vtln_high": 4607, "vtln_low": 4483, "vtln_warp": 1.0, "window_type": "povey", "dither": 0.0} +{"blackman_coeff": 1.5626, "energy_floor": 3.7117, "frame_length": 1.125, "frame_shift": 0.125, "high_freq": 3008, "htk_compat": true, "low_freq": 534, "num_mel_bins": 5, "preemphasis_coefficient": 0.65, "raw_energy": true, "remove_dc_offset": false, "round_to_power_of_two": false, "snip_edges": true, "subtract_mean": true, "use_energy": true, "num_ceps": 2, "cepstral_lifter": 75.6661, "vtln_high": 2592, "vtln_low": 1621, "vtln_warp": 1.0, "window_type": "hamming", "dither": 0.0} +{"blackman_coeff": 1.5707, "energy_floor": 3.0409, "frame_length": 0.75, "frame_shift": 0.625, "high_freq": 7441, "htk_compat": true, "low_freq": 1554, "num_mel_bins": 6, "preemphasis_coefficient": 0.95, "raw_energy": true, "remove_dc_offset": false, "round_to_power_of_two": true, "snip_edges": true, "subtract_mean": true, "use_energy": true, "num_ceps": 4, "cepstral_lifter": 80.1563, "vtln_high": 7152, "vtln_low": 6151, "vtln_warp": 1.0, "window_type": "rectangular", "dither": 0.0} +{"blackman_coeff": 1.5966, "energy_floor": 2.3442, "frame_length": 0.5625, "frame_shift": 0.5, "high_freq": 7944, "htk_compat": true, "low_freq": 1616, "num_mel_bins": 5, "preemphasis_coefficient": 0.49, "raw_energy": true, "remove_dc_offset": true, "round_to_power_of_two": true, "snip_edges": false, "subtract_mean": false, "use_energy": true, "num_ceps": 2, "cepstral_lifter": 80.8779, "vtln_high": 5720, "vtln_low": 4080, "vtln_warp": 1.0, "window_type": "povey", "dither": 0.0} +{"blackman_coeff": 1.6229, "energy_floor": 2.0519, "frame_length": 1.1875, "frame_shift": 0.3125, "high_freq": 4871, "htk_compat": true, "low_freq": 1567, "num_mel_bins": 4, "preemphasis_coefficient": 0.79, "raw_energy": false, "remove_dc_offset": true, "round_to_power_of_two": true, "snip_edges": true, "subtract_mean": false, "use_energy": true, "num_ceps": 2, "cepstral_lifter": 42.9569, "vtln_high": 3483, "vtln_low": 3287, "vtln_warp": 1.0, "window_type": "hanning", "dither": 0.0} +{"blackman_coeff": 1.736, "energy_floor": 0.4063, "frame_length": 0.6875, "frame_shift": 0.0625, "high_freq": 6475, "htk_compat": true, "low_freq": 4439, "num_mel_bins": 4, "preemphasis_coefficient": 0.23, "raw_energy": true, "remove_dc_offset": false, "round_to_power_of_two": true, "snip_edges": false, "subtract_mean": false, "use_energy": false, "num_ceps": 2, "cepstral_lifter": 30.0984, "vtln_high": 5450, "vtln_low": 4909, "vtln_warp": 1.0, "window_type": "rectangular", "dither": 0.0} +{"blackman_coeff": 1.7411, "energy_floor": 2.0918, "frame_length": 1.0625, "frame_shift": 0.8125, "high_freq": 6107, "htk_compat": true, "low_freq": 2523, "num_mel_bins": 4, "preemphasis_coefficient": 0.69, "raw_energy": true, "remove_dc_offset": false, "round_to_power_of_two": true, "snip_edges": true, "subtract_mean": false, "use_energy": false, "num_ceps": 3, "cepstral_lifter": 92.6839, "vtln_high": 5085, "vtln_low": 4771, "vtln_warp": 1.0, "window_type": "povey", "dither": 0.0} +{"blackman_coeff": 1.7439, "energy_floor": 2.3782, "frame_length": 0.875, "frame_shift": 1.1875, "high_freq": 7669, "htk_compat": false, "low_freq": 4499, "num_mel_bins": 4, "preemphasis_coefficient": 0.81, "raw_energy": false, "remove_dc_offset": true, "round_to_power_of_two": false, "snip_edges": true, "subtract_mean": false, "use_energy": false, "num_ceps": 2, "cepstral_lifter": 95.7035, "vtln_high": 7521, "vtln_low": 7417, "vtln_warp": 1.0, "window_type": "hamming", "dither": 0.0} +{"blackman_coeff": 1.7611, "energy_floor": 4.2965, "frame_length": 0.8125, "frame_shift": 0.6875, "high_freq": 6607, "htk_compat": false, "low_freq": 454, "num_mel_bins": 7, "preemphasis_coefficient": 0.35, "raw_energy": true, "remove_dc_offset": true, "round_to_power_of_two": true, "snip_edges": false, "subtract_mean": true, "use_energy": false, "num_ceps": 2, "cepstral_lifter": 17.8265, "vtln_high": 6387, "vtln_low": 6105, "vtln_warp": 1.0, "window_type": "hanning", "dither": 0.0} +{"blackman_coeff": 1.7893, "energy_floor": 1.8005, "frame_length": 0.625, "frame_shift": 0.375, "high_freq": 2791, "htk_compat": true, "low_freq": 617, "num_mel_bins": 4, "preemphasis_coefficient": 0.96, "raw_energy": true, "remove_dc_offset": false, "round_to_power_of_two": true, "snip_edges": true, "subtract_mean": false, "use_energy": true, "num_ceps": 4, "cepstral_lifter": 93.405, "vtln_high": 1751, "vtln_low": 1690, "vtln_warp": 1.0, "window_type": "povey", "dither": 0.0} +{"blackman_coeff": 1.8392, "energy_floor": 4.3711, "frame_length": 0.9375, "frame_shift": 0.75, "high_freq": 6978, "htk_compat": true, "low_freq": 453, "num_mel_bins": 4, "preemphasis_coefficient": 0.48, "raw_energy": true, "remove_dc_offset": true, "round_to_power_of_two": true, "snip_edges": true, "subtract_mean": true, "use_energy": false, "num_ceps": 3, "cepstral_lifter": 42.9768, "vtln_high": 6315, "vtln_low": 3995, "vtln_warp": 1.1059, "window_type": "rectangular", "dither": 0.0} +{"blackman_coeff": 1.9561, "energy_floor": 0.8419, "frame_length": 0.8125, "frame_shift": 1.125, "high_freq": 5308, "htk_compat": false, "low_freq": 1471, "num_mel_bins": 5, "preemphasis_coefficient": 0.62, "raw_energy": true, "remove_dc_offset": false, "round_to_power_of_two": true, "snip_edges": true, "subtract_mean": false, "use_energy": true, "num_ceps": 3, "cepstral_lifter": 51.0514, "vtln_high": 5221, "vtln_low": 5071, "vtln_warp": 1.0, "window_type": "rectangular", "dither": 0.0} +{"blackman_coeff": 1.998, "energy_floor": 1.6949, "frame_length": 1.125, "frame_shift": 0.8125, "high_freq": 4678, "htk_compat": true, "low_freq": 2340, "num_mel_bins": 5, "preemphasis_coefficient": 0.44, "raw_energy": true, "remove_dc_offset": false, "round_to_power_of_two": false, "snip_edges": true, "subtract_mean": false, "use_energy": true, "num_ceps": 3, "cepstral_lifter": 70.1988, "vtln_high": 4041, "vtln_low": 2424, "vtln_warp": 1.0, "window_type": "rectangular", "dither": 0.0} +{"blackman_coeff": 2.0106, "energy_floor": 4.5392, "frame_length": 0.6875, "frame_shift": 0.1875, "high_freq": 4776, "htk_compat": true, "low_freq": 1297, "num_mel_bins": 5, "preemphasis_coefficient": 0.14, "raw_energy": false, "remove_dc_offset": false, "round_to_power_of_two": true, "snip_edges": false, "subtract_mean": false, "use_energy": true, "num_ceps": 2, "cepstral_lifter": 37.5837, "vtln_high": 3995, "vtln_low": 2991, "vtln_warp": 1.0, "window_type": "hanning", "dither": 0.0} +{"blackman_coeff": 2.0835, "energy_floor": 2.8454, "frame_length": 0.9375, "frame_shift": 0.3125, "high_freq": 7496, "htk_compat": false, "low_freq": 1207, "num_mel_bins": 6, "preemphasis_coefficient": 0.76, "raw_energy": true, "remove_dc_offset": false, "round_to_power_of_two": true, "snip_edges": true, "subtract_mean": false, "use_energy": false, "num_ceps": 6, "cepstral_lifter": 4.5734, "vtln_high": 3935, "vtln_low": 3932, "vtln_warp": 1.0, "window_type": "blackman", "dither": 0.0} +{"blackman_coeff": 2.2801, "energy_floor": 1.7051, "frame_length": 1.1875, "frame_shift": 0.125, "high_freq": 7958, "htk_compat": true, "low_freq": 561, "num_mel_bins": 4, "preemphasis_coefficient": 0.9, "raw_energy": false, "remove_dc_offset": false, "round_to_power_of_two": true, "snip_edges": true, "subtract_mean": true, "use_energy": true, "num_ceps": 2, "cepstral_lifter": 60.4649, "vtln_high": 7218, "vtln_low": 5709, "vtln_warp": 1.0, "window_type": "rectangular", "dither": 0.0} +{"blackman_coeff": 2.315, "energy_floor": 0.4964, "frame_length": 0.5, "frame_shift": 0.4375, "high_freq": 6582, "htk_compat": false, "low_freq": 1010, "num_mel_bins": 4, "preemphasis_coefficient": 0.98, "raw_energy": false, "remove_dc_offset": false, "round_to_power_of_two": true, "snip_edges": true, "subtract_mean": false, "use_energy": false, "num_ceps": 3, "cepstral_lifter": 71.516, "vtln_high": 6157, "vtln_low": 4430, "vtln_warp": 1.0, "window_type": "rectangular", "dither": 0.0} +{"blackman_coeff": 2.3236, "energy_floor": 0.7825, "frame_length": 0.8125, "frame_shift": 0.25, "high_freq": 7488, "htk_compat": true, "low_freq": 1363, "num_mel_bins": 4, "preemphasis_coefficient": 0.3, "raw_energy": false, "remove_dc_offset": true, "round_to_power_of_two": true, "snip_edges": true, "subtract_mean": true, "use_energy": true, "num_ceps": 4, "cepstral_lifter": 68.9678, "vtln_high": 3555, "vtln_low": 1851, "vtln_warp": 1.0, "window_type": "blackman", "dither": 0.0} +{"blackman_coeff": 2.3805, "energy_floor": 2.934, "frame_length": 0.75, "frame_shift": 0.25, "high_freq": 6076, "htk_compat": true, "low_freq": 80, "num_mel_bins": 4, "preemphasis_coefficient": 0.85, "raw_energy": false, "remove_dc_offset": true, "round_to_power_of_two": true, "snip_edges": false, "subtract_mean": true, "use_energy": true, "num_ceps": 3, "cepstral_lifter": 31.0805, "vtln_high": 2257, "vtln_low": 1533, "vtln_warp": 1.0, "window_type": "hamming", "dither": 0.0} +{"blackman_coeff": 2.4091, "energy_floor": 2.8812, "frame_length": 1.125, "frame_shift": 0.9375, "high_freq": 6086, "htk_compat": false, "low_freq": 1210, "num_mel_bins": 5, "preemphasis_coefficient": 0.59, "raw_energy": true, "remove_dc_offset": false, "round_to_power_of_two": false, "snip_edges": false, "subtract_mean": false, "use_energy": true, "num_ceps": 3, "cepstral_lifter": 96.1612, "vtln_high": 4840, "vtln_low": 1905, "vtln_warp": 1.0, "window_type": "hamming", "dither": 0.0} +{"blackman_coeff": 2.4134, "energy_floor": 2.6379, "frame_length": 1.1875, "frame_shift": 0.375, "high_freq": 3318, "htk_compat": false, "low_freq": 770, "num_mel_bins": 5, "preemphasis_coefficient": 0.6, "raw_energy": false, "remove_dc_offset": true, "round_to_power_of_two": true, "snip_edges": false, "subtract_mean": false, "use_energy": false, "num_ceps": 3, "cepstral_lifter": 73.9427, "vtln_high": 2044, "vtln_low": 1481, "vtln_warp": 1.0, "window_type": "hanning", "dither": 0.0} +{"blackman_coeff": 2.5228, "energy_floor": 3.1056, "frame_length": 1.125, "frame_shift": 1.1875, "high_freq": 5422, "htk_compat": false, "low_freq": 2825, "num_mel_bins": 7, "preemphasis_coefficient": 0.88, "raw_energy": false, "remove_dc_offset": false, "round_to_power_of_two": true, "snip_edges": false, "subtract_mean": false, "use_energy": false, "num_ceps": 7, "cepstral_lifter": 4.6719, "vtln_high": 5337, "vtln_low": 5243, "vtln_warp": 1.0, "window_type": "hanning", "dither": 0.0} +{"blackman_coeff": 2.5577, "energy_floor": 0.7393, "frame_length": 0.8125, "frame_shift": 0.5, "high_freq": 5291, "htk_compat": true, "low_freq": 1445, "num_mel_bins": 5, "preemphasis_coefficient": 0.01, "raw_energy": false, "remove_dc_offset": true, "round_to_power_of_two": true, "snip_edges": false, "subtract_mean": true, "use_energy": false, "num_ceps": 2, "cepstral_lifter": 5.8944, "vtln_high": 4338, "vtln_low": 4330, "vtln_warp": 1.0, "window_type": "hanning", "dither": 0.0} +{"blackman_coeff": 2.5854, "energy_floor": 3.2219, "frame_length": 0.875, "frame_shift": 0.4375, "high_freq": 6924, "htk_compat": false, "low_freq": 4024, "num_mel_bins": 4, "preemphasis_coefficient": 1.0, "raw_energy": false, "remove_dc_offset": true, "round_to_power_of_two": true, "snip_edges": false, "subtract_mean": true, "use_energy": false, "num_ceps": 2, "cepstral_lifter": 0.0578, "vtln_high": 5707, "vtln_low": 5025, "vtln_warp": 1.0, "window_type": "rectangular", "dither": 0.0} +{"blackman_coeff": 2.6674, "energy_floor": 2.777, "frame_length": 1.0625, "frame_shift": 0.3125, "high_freq": 3129, "htk_compat": true, "low_freq": 1706, "num_mel_bins": 4, "preemphasis_coefficient": 0.91, "raw_energy": false, "remove_dc_offset": true, "round_to_power_of_two": true, "snip_edges": false, "subtract_mean": true, "use_energy": true, "num_ceps": 3, "cepstral_lifter": 50.9241, "vtln_high": 2593, "vtln_low": 2198, "vtln_warp": 1.0, "window_type": "hanning", "dither": 0.0} +{"blackman_coeff": 2.6816, "energy_floor": 4.0548, "frame_length": 1.1875, "frame_shift": 0.625, "high_freq": 3182, "htk_compat": false, "low_freq": 157, "num_mel_bins": 6, "preemphasis_coefficient": 0.04, "raw_energy": false, "remove_dc_offset": true, "round_to_power_of_two": true, "snip_edges": true, "subtract_mean": true, "use_energy": false, "num_ceps": 5, "cepstral_lifter": 31.3652, "vtln_high": 1203, "vtln_low": 1174, "vtln_warp": 1.0, "window_type": "povey", "dither": 0.0} +{"blackman_coeff": 2.7879, "energy_floor": 3.3482, "frame_length": 0.6875, "frame_shift": 0.375, "high_freq": 4262, "htk_compat": true, "low_freq": 150, "num_mel_bins": 4, "preemphasis_coefficient": 0.68, "raw_energy": true, "remove_dc_offset": false, "round_to_power_of_two": true, "snip_edges": true, "subtract_mean": false, "use_energy": true, "num_ceps": 2, "cepstral_lifter": 92.794, "vtln_high": 3276, "vtln_low": 1685, "vtln_warp": 1.0, "window_type": "rectangular", "dither": 0.0} +{"blackman_coeff": 2.8683, "energy_floor": 3.8162, "frame_length": 1.125, "frame_shift": 0.375, "high_freq": 6620, "htk_compat": false, "low_freq": 3389, "num_mel_bins": 7, "preemphasis_coefficient": 0.83, "raw_energy": false, "remove_dc_offset": true, "round_to_power_of_two": true, "snip_edges": true, "subtract_mean": true, "use_energy": true, "num_ceps": 5, "cepstral_lifter": 82.2365, "vtln_high": 5365, "vtln_low": 4579, "vtln_warp": 1.0, "window_type": "rectangular", "dither": 0.0} +{"blackman_coeff": 2.869, "energy_floor": 3.2618, "frame_length": 1.1875, "frame_shift": 0.9375, "high_freq": 5646, "htk_compat": true, "low_freq": 491, "num_mel_bins": 8, "preemphasis_coefficient": 0.89, "raw_energy": false, "remove_dc_offset": false, "round_to_power_of_two": true, "snip_edges": false, "subtract_mean": false, "use_energy": true, "num_ceps": 2, "cepstral_lifter": 59.9812, "vtln_high": 5397, "vtln_low": 2639, "vtln_warp": 1.0, "window_type": "hamming", "dither": 0.0} +{"blackman_coeff": 2.9211, "energy_floor": 4.144, "frame_length": 0.75, "frame_shift": 0.375, "high_freq": 7210, "htk_compat": true, "low_freq": 3666, "num_mel_bins": 4, "preemphasis_coefficient": 0.93, "raw_energy": false, "remove_dc_offset": false, "round_to_power_of_two": true, "snip_edges": true, "subtract_mean": false, "use_energy": false, "num_ceps": 4, "cepstral_lifter": 94.5907, "vtln_high": 6682, "vtln_low": 4979, "vtln_warp": 1.0, "window_type": "hamming", "dither": 0.0} +{"blackman_coeff": 2.9464, "energy_floor": 0.6798, "frame_length": 1.125, "frame_shift": 0.0625, "high_freq": 4445, "htk_compat": true, "low_freq": 323, "num_mel_bins": 6, "preemphasis_coefficient": 0.46, "raw_energy": false, "remove_dc_offset": true, "round_to_power_of_two": true, "snip_edges": false, "subtract_mean": true, "use_energy": false, "num_ceps": 6, "cepstral_lifter": 7.8133, "vtln_high": 3755, "vtln_low": 1137, "vtln_warp": 1.0, "window_type": "hanning", "dither": 0.0} +{"blackman_coeff": 2.9633, "energy_floor": 1.9565, "frame_length": 0.875, "frame_shift": 0.0625, "high_freq": 6835, "htk_compat": false, "low_freq": 649, "num_mel_bins": 5, "preemphasis_coefficient": 0.77, "raw_energy": false, "remove_dc_offset": false, "round_to_power_of_two": false, "snip_edges": true, "subtract_mean": false, "use_energy": false, "num_ceps": 2, "cepstral_lifter": 80.8871, "vtln_high": 6691, "vtln_low": 6581, "vtln_warp": 1.0, "window_type": "povey", "dither": 0.0} +{"blackman_coeff": 2.9643, "energy_floor": 3.8883, "frame_length": 0.75, "frame_shift": 0.25, "high_freq": 7373, "htk_compat": false, "low_freq": 1698, "num_mel_bins": 4, "preemphasis_coefficient": 0.92, "raw_energy": false, "remove_dc_offset": false, "round_to_power_of_two": true, "snip_edges": false, "subtract_mean": true, "use_energy": true, "num_ceps": 4, "cepstral_lifter": 63.3036, "vtln_high": 6650, "vtln_low": 5500, "vtln_warp": 1.0, "window_type": "povey", "dither": 0.0} +{"blackman_coeff": 2.9697, "energy_floor": 2.0241, "frame_length": 1.125, "frame_shift": 0.6875, "high_freq": 2170, "htk_compat": false, "low_freq": 180, "num_mel_bins": 5, "preemphasis_coefficient": 0.28, "raw_energy": false, "remove_dc_offset": true, "round_to_power_of_two": true, "snip_edges": true, "subtract_mean": true, "use_energy": true, "num_ceps": 3, "cepstral_lifter": 95.8111, "vtln_high": 1266, "vtln_low": 521, "vtln_warp": 1.0, "window_type": "blackman", "dither": 0.0} +{"blackman_coeff": 3.0358, "energy_floor": 1.7295, "frame_length": 1.1875, "frame_shift": 1.0, "high_freq": 7222, "htk_compat": true, "low_freq": 858, "num_mel_bins": 4, "preemphasis_coefficient": 0.16, "raw_energy": false, "remove_dc_offset": true, "round_to_power_of_two": true, "snip_edges": false, "subtract_mean": false, "use_energy": true, "num_ceps": 4, "cepstral_lifter": 64.7537, "vtln_high": 6220, "vtln_low": 5229, "vtln_warp": 1.0, "window_type": "povey", "dither": 0.0} +{"blackman_coeff": 3.0421, "energy_floor": 3.3343, "frame_length": 1.0, "frame_shift": 0.9375, "high_freq": 6477, "htk_compat": false, "low_freq": 1402, "num_mel_bins": 5, "preemphasis_coefficient": 0.99, "raw_energy": false, "remove_dc_offset": true, "round_to_power_of_two": true, "snip_edges": true, "subtract_mean": true, "use_energy": true, "num_ceps": 4, "cepstral_lifter": 26.1743, "vtln_high": 6381, "vtln_low": 5017, "vtln_warp": 1.0, "window_type": "hamming", "dither": 0.0} +{"blackman_coeff": 3.0919, "energy_floor": 4.5103, "frame_length": 0.625, "frame_shift": 1.0, "high_freq": 5323, "htk_compat": true, "low_freq": 937, "num_mel_bins": 5, "preemphasis_coefficient": 0.95, "raw_energy": false, "remove_dc_offset": false, "round_to_power_of_two": true, "snip_edges": true, "subtract_mean": true, "use_energy": false, "num_ceps": 5, "cepstral_lifter": 82.2405, "vtln_high": 5130, "vtln_low": 5086, "vtln_warp": 1.0, "window_type": "hanning", "dither": 0.0} +{"blackman_coeff": 3.1463, "energy_floor": 4.5068, "frame_length": 0.6875, "frame_shift": 0.3125, "high_freq": 7587, "htk_compat": true, "low_freq": 3542, "num_mel_bins": 7, "preemphasis_coefficient": 0.78, "raw_energy": true, "remove_dc_offset": false, "round_to_power_of_two": true, "snip_edges": true, "subtract_mean": true, "use_energy": true, "num_ceps": 4, "cepstral_lifter": 28.5808, "vtln_high": 7478, "vtln_low": 7326, "vtln_warp": 1.0, "window_type": "blackman", "dither": 0.0} +{"blackman_coeff": 3.2007, "energy_floor": 1.3677, "frame_length": 1.125, "frame_shift": 0.1875, "high_freq": 4726, "htk_compat": true, "low_freq": 2027, "num_mel_bins": 4, "preemphasis_coefficient": 0.74, "raw_energy": false, "remove_dc_offset": true, "round_to_power_of_two": false, "snip_edges": false, "subtract_mean": true, "use_energy": false, "num_ceps": 4, "cepstral_lifter": 3.5732, "vtln_high": 4583, "vtln_low": 3742, "vtln_warp": 1.0, "window_type": "povey", "dither": 0.0} +{"blackman_coeff": 3.2416, "energy_floor": 1.0604, "frame_length": 0.875, "frame_shift": 0.5, "high_freq": 4730, "htk_compat": false, "low_freq": 968, "num_mel_bins": 4, "preemphasis_coefficient": 0.11, "raw_energy": true, "remove_dc_offset": true, "round_to_power_of_two": true, "snip_edges": false, "subtract_mean": true, "use_energy": true, "num_ceps": 3, "cepstral_lifter": 60.5751, "vtln_high": 3542, "vtln_low": 1943, "vtln_warp": 1.0, "window_type": "blackman", "dither": 0.0} +{"blackman_coeff": 3.2698, "energy_floor": 3.0361, "frame_length": 1.0625, "frame_shift": 0.75, "high_freq": 4870, "htk_compat": true, "low_freq": 1281, "num_mel_bins": 7, "preemphasis_coefficient": 0.64, "raw_energy": false, "remove_dc_offset": true, "round_to_power_of_two": true, "snip_edges": false, "subtract_mean": true, "use_energy": true, "num_ceps": 3, "cepstral_lifter": 28.536, "vtln_high": 4401, "vtln_low": 3315, "vtln_warp": 1.0, "window_type": "blackman", "dither": 0.0} +{"blackman_coeff": 3.3078, "energy_floor": 4.9217, "frame_length": 1.0, "frame_shift": 0.3125, "high_freq": 6758, "htk_compat": true, "low_freq": 760, "num_mel_bins": 5, "preemphasis_coefficient": 0.98, "raw_energy": true, "remove_dc_offset": true, "round_to_power_of_two": true, "snip_edges": true, "subtract_mean": false, "use_energy": true, "num_ceps": 3, "cepstral_lifter": 97.4694, "vtln_high": 6022, "vtln_low": 5650, "vtln_warp": 1.0, "window_type": "rectangular", "dither": 0.0} +{"blackman_coeff": 3.3206, "energy_floor": 0.023, "frame_length": 1.0625, "frame_shift": 0.5625, "high_freq": 5744, "htk_compat": true, "low_freq": 3901, "num_mel_bins": 5, "preemphasis_coefficient": 0.94, "raw_energy": true, "remove_dc_offset": false, "round_to_power_of_two": true, "snip_edges": true, "subtract_mean": true, "use_energy": false, "num_ceps": 2, "cepstral_lifter": 47.6031, "vtln_high": 5741, "vtln_low": 5524, "vtln_warp": 1.0, "window_type": "hanning", "dither": 0.0} +{"blackman_coeff": 3.4022, "energy_floor": 1.2172, "frame_length": 0.875, "frame_shift": 0.375, "high_freq": 7737, "htk_compat": false, "low_freq": 612, "num_mel_bins": 5, "preemphasis_coefficient": 0.35, "raw_energy": true, "remove_dc_offset": true, "round_to_power_of_two": true, "snip_edges": false, "subtract_mean": false, "use_energy": false, "num_ceps": 2, "cepstral_lifter": 65.1166, "vtln_high": 6852, "vtln_low": 5820, "vtln_warp": 1.0, "window_type": "blackman", "dither": 0.0} +{"blackman_coeff": 3.4339, "energy_floor": 2.6197, "frame_length": 1.125, "frame_shift": 0.1875, "high_freq": 3341, "htk_compat": true, "low_freq": 1275, "num_mel_bins": 7, "preemphasis_coefficient": 0.41, "raw_energy": true, "remove_dc_offset": false, "round_to_power_of_two": true, "snip_edges": false, "subtract_mean": true, "use_energy": true, "num_ceps": 2, "cepstral_lifter": 76.6062, "vtln_high": 3005, "vtln_low": 1680, "vtln_warp": 1.0, "window_type": "rectangular", "dither": 0.0} +{"blackman_coeff": 3.4369, "energy_floor": 3.9198, "frame_length": 0.9375, "frame_shift": 0.125, "high_freq": 6218, "htk_compat": true, "low_freq": 904, "num_mel_bins": 5, "preemphasis_coefficient": 0.47, "raw_energy": true, "remove_dc_offset": true, "round_to_power_of_two": true, "snip_edges": true, "subtract_mean": false, "use_energy": false, "num_ceps": 5, "cepstral_lifter": 92.8036, "vtln_high": 4870, "vtln_low": 1901, "vtln_warp": 1.0, "window_type": "blackman", "dither": 0.0} +{"blackman_coeff": 3.4557, "energy_floor": 1.5553, "frame_length": 0.75, "frame_shift": 0.375, "high_freq": 6642, "htk_compat": true, "low_freq": 1530, "num_mel_bins": 4, "preemphasis_coefficient": 0.72, "raw_energy": false, "remove_dc_offset": true, "round_to_power_of_two": false, "snip_edges": false, "subtract_mean": false, "use_energy": true, "num_ceps": 2, "cepstral_lifter": 28.8828, "vtln_high": 4490, "vtln_low": 2980, "vtln_warp": 1.0, "window_type": "hamming", "dither": 0.0} +{"blackman_coeff": 3.4753, "energy_floor": 4.7166, "frame_length": 0.75, "frame_shift": 0.3125, "high_freq": 7637, "htk_compat": true, "low_freq": 4992, "num_mel_bins": 4, "preemphasis_coefficient": 0.92, "raw_energy": true, "remove_dc_offset": false, "round_to_power_of_two": true, "snip_edges": true, "subtract_mean": false, "use_energy": true, "num_ceps": 3, "cepstral_lifter": 2.5456, "vtln_high": 6925, "vtln_low": 5486, "vtln_warp": 1.0, "window_type": "hamming", "dither": 0.0} +{"blackman_coeff": 3.5134, "energy_floor": 2.0285, "frame_length": 0.625, "frame_shift": 0.1875, "high_freq": 5229, "htk_compat": false, "low_freq": 595, "num_mel_bins": 4, "preemphasis_coefficient": 0.65, "raw_energy": true, "remove_dc_offset": true, "round_to_power_of_two": true, "snip_edges": true, "subtract_mean": false, "use_energy": false, "num_ceps": 3, "cepstral_lifter": 30.6069, "vtln_high": 5090, "vtln_low": 3467, "vtln_warp": 1.0, "window_type": "hamming", "dither": 0.0} +{"blackman_coeff": 3.5212, "energy_floor": 3.8251, "frame_length": 0.875, "frame_shift": 0.3125, "high_freq": 4092, "htk_compat": true, "low_freq": 545, "num_mel_bins": 5, "preemphasis_coefficient": 0.09, "raw_energy": false, "remove_dc_offset": true, "round_to_power_of_two": true, "snip_edges": false, "subtract_mean": true, "use_energy": false, "num_ceps": 2, "cepstral_lifter": 2.9422, "vtln_high": 1634, "vtln_low": 1000, "vtln_warp": 1.0, "window_type": "hanning", "dither": 0.0} +{"blackman_coeff": 3.5261, "energy_floor": 2.0251, "frame_length": 0.875, "frame_shift": 0.625, "high_freq": 7926, "htk_compat": false, "low_freq": 3916, "num_mel_bins": 7, "preemphasis_coefficient": 0.45, "raw_energy": false, "remove_dc_offset": false, "round_to_power_of_two": true, "snip_edges": true, "subtract_mean": true, "use_energy": false, "num_ceps": 2, "cepstral_lifter": 48.8818, "vtln_high": 7889, "vtln_low": 7527, "vtln_warp": 1.0, "window_type": "hanning", "dither": 0.0} +{"blackman_coeff": 3.539, "energy_floor": 1.6456, "frame_length": 1.125, "frame_shift": 0.1875, "high_freq": 5425, "htk_compat": true, "low_freq": 2326, "num_mel_bins": 7, "preemphasis_coefficient": 0.72, "raw_energy": false, "remove_dc_offset": false, "round_to_power_of_two": true, "snip_edges": false, "subtract_mean": true, "use_energy": false, "num_ceps": 4, "cepstral_lifter": 39.4555, "vtln_high": 4290, "vtln_low": 2715, "vtln_warp": 1.0, "window_type": "povey", "dither": 0.0} +{"blackman_coeff": 3.5643, "energy_floor": 2.2424, "frame_length": 1.1875, "frame_shift": 0.875, "high_freq": 2140, "htk_compat": true, "low_freq": 59, "num_mel_bins": 4, "preemphasis_coefficient": 0.98, "raw_energy": true, "remove_dc_offset": true, "round_to_power_of_two": true, "snip_edges": false, "subtract_mean": false, "use_energy": false, "num_ceps": 2, "cepstral_lifter": 36.7118, "vtln_high": 1463, "vtln_low": 1358, "vtln_warp": 1.0, "window_type": "hanning", "dither": 0.0} +{"blackman_coeff": 3.5959, "energy_floor": 4.8866, "frame_length": 1.125, "frame_shift": 1.0625, "high_freq": 5150, "htk_compat": false, "low_freq": 3697, "num_mel_bins": 4, "preemphasis_coefficient": 0.46, "raw_energy": true, "remove_dc_offset": true, "round_to_power_of_two": true, "snip_edges": false, "subtract_mean": true, "use_energy": true, "num_ceps": 3, "cepstral_lifter": 74.0966, "vtln_high": 4277, "vtln_low": 3777, "vtln_warp": 1.0, "window_type": "rectangular", "dither": 0.0} +{"blackman_coeff": 3.7223, "energy_floor": 3.4282, "frame_length": 1.0, "frame_shift": 0.125, "high_freq": 6601, "htk_compat": true, "low_freq": 1923, "num_mel_bins": 6, "preemphasis_coefficient": 0.05, "raw_energy": false, "remove_dc_offset": true, "round_to_power_of_two": true, "snip_edges": false, "subtract_mean": false, "use_energy": true, "num_ceps": 4, "cepstral_lifter": 19.2839, "vtln_high": 6596, "vtln_low": 6594, "vtln_warp": 1.0, "window_type": "hanning", "dither": 0.0} +{"blackman_coeff": 3.7376, "energy_floor": 0.2093, "frame_length": 1.1875, "frame_shift": 0.75, "high_freq": 7830, "htk_compat": true, "low_freq": 4448, "num_mel_bins": 5, "preemphasis_coefficient": 0.27, "raw_energy": true, "remove_dc_offset": false, "round_to_power_of_two": true, "snip_edges": false, "subtract_mean": false, "use_energy": true, "num_ceps": 5, "cepstral_lifter": 5.5865, "vtln_high": 5459, "vtln_low": 5056, "vtln_warp": 1.0, "window_type": "blackman", "dither": 0.0} +{"blackman_coeff": 3.812, "energy_floor": 0.4393, "frame_length": 0.75, "frame_shift": 1.0625, "high_freq": 5917, "htk_compat": false, "low_freq": 1272, "num_mel_bins": 4, "preemphasis_coefficient": 0.97, "raw_energy": false, "remove_dc_offset": false, "round_to_power_of_two": false, "snip_edges": false, "subtract_mean": true, "use_energy": true, "num_ceps": 3, "cepstral_lifter": 91.4723, "vtln_high": 3532, "vtln_low": 3056, "vtln_warp": 1.0, "window_type": "povey", "dither": 0.0} +{"blackman_coeff": 3.8613, "energy_floor": 4.6574, "frame_length": 1.125, "frame_shift": 1.0, "high_freq": 3399, "htk_compat": true, "low_freq": 1576, "num_mel_bins": 5, "preemphasis_coefficient": 0.71, "raw_energy": true, "remove_dc_offset": false, "round_to_power_of_two": true, "snip_edges": false, "subtract_mean": false, "use_energy": true, "num_ceps": 3, "cepstral_lifter": 29.1497, "vtln_high": 2440, "vtln_low": 1852, "vtln_warp": 1.0, "window_type": "blackman", "dither": 0.0} +{"blackman_coeff": 3.9117, "energy_floor": 4.6803, "frame_length": 0.5625, "frame_shift": 0.625, "high_freq": 5009, "htk_compat": false, "low_freq": 2542, "num_mel_bins": 4, "preemphasis_coefficient": 0.25, "raw_energy": true, "remove_dc_offset": true, "round_to_power_of_two": true, "snip_edges": false, "subtract_mean": false, "use_energy": false, "num_ceps": 4, "cepstral_lifter": 65.8362, "vtln_high": 4734, "vtln_low": 3050, "vtln_warp": 1.0, "window_type": "povey", "dither": 0.0} +{"blackman_coeff": 4.1851, "energy_floor": 3.5211, "frame_length": 1.125, "frame_shift": 0.875, "high_freq": 4768, "htk_compat": false, "low_freq": 562, "num_mel_bins": 4, "preemphasis_coefficient": 0.05, "raw_energy": true, "remove_dc_offset": true, "round_to_power_of_two": true, "snip_edges": true, "subtract_mean": false, "use_energy": false, "num_ceps": 2, "cepstral_lifter": 36.961, "vtln_high": 1982, "vtln_low": 741, "vtln_warp": 1.0, "window_type": "povey", "dither": 0.0} +{"blackman_coeff": 4.2197, "energy_floor": 3.7252, "frame_length": 0.9375, "frame_shift": 0.8125, "high_freq": 7453, "htk_compat": true, "low_freq": 1561, "num_mel_bins": 4, "preemphasis_coefficient": 0.06, "raw_energy": false, "remove_dc_offset": false, "round_to_power_of_two": true, "snip_edges": true, "subtract_mean": true, "use_energy": false, "num_ceps": 2, "cepstral_lifter": 44.78, "vtln_high": 6612, "vtln_low": 4074, "vtln_warp": 1.0, "window_type": "blackman", "dither": 0.0} +{"blackman_coeff": 4.2736, "energy_floor": 4.9552, "frame_length": 0.75, "frame_shift": 1.0, "high_freq": 5145, "htk_compat": false, "low_freq": 1705, "num_mel_bins": 4, "preemphasis_coefficient": 0.33, "raw_energy": false, "remove_dc_offset": false, "round_to_power_of_two": false, "snip_edges": true, "subtract_mean": false, "use_energy": false, "num_ceps": 4, "cepstral_lifter": 70.9332, "vtln_high": 4857, "vtln_low": 2223, "vtln_warp": 1.0, "window_type": "blackman", "dither": 0.0} +{"blackman_coeff": 4.3762, "energy_floor": 4.7209, "frame_length": 0.9375, "frame_shift": 0.0625, "high_freq": 5564, "htk_compat": true, "low_freq": 712, "num_mel_bins": 4, "preemphasis_coefficient": 0.74, "raw_energy": false, "remove_dc_offset": false, "round_to_power_of_two": true, "snip_edges": true, "subtract_mean": true, "use_energy": true, "num_ceps": 2, "cepstral_lifter": 39.2887, "vtln_high": 4353, "vtln_low": 3521, "vtln_warp": 1.0, "window_type": "rectangular", "dither": 0.0} +{"blackman_coeff": 4.4229, "energy_floor": 0.4222, "frame_length": 1.0625, "frame_shift": 1.1875, "high_freq": 7822, "htk_compat": true, "low_freq": 4837, "num_mel_bins": 5, "preemphasis_coefficient": 0.04, "raw_energy": true, "remove_dc_offset": false, "round_to_power_of_two": true, "snip_edges": true, "subtract_mean": true, "use_energy": false, "num_ceps": 5, "cepstral_lifter": 36.9181, "vtln_high": 7261, "vtln_low": 5703, "vtln_warp": 1.0, "window_type": "blackman", "dither": 0.0} +{"blackman_coeff": 4.4663, "energy_floor": 3.5767, "frame_length": 1.125, "frame_shift": 1.125, "high_freq": 5844, "htk_compat": false, "low_freq": 799, "num_mel_bins": 7, "preemphasis_coefficient": 0.37, "raw_energy": false, "remove_dc_offset": false, "round_to_power_of_two": true, "snip_edges": true, "subtract_mean": true, "use_energy": false, "num_ceps": 4, "cepstral_lifter": 34.2098, "vtln_high": 4554, "vtln_low": 1148, "vtln_warp": 1.0, "window_type": "hamming", "dither": 0.0} +{"blackman_coeff": 4.53, "energy_floor": 3.1492, "frame_length": 1.0625, "frame_shift": 0.375, "high_freq": 7706, "htk_compat": false, "low_freq": 3813, "num_mel_bins": 6, "preemphasis_coefficient": 0.74, "raw_energy": false, "remove_dc_offset": false, "round_to_power_of_two": true, "snip_edges": false, "subtract_mean": true, "use_energy": false, "num_ceps": 2, "cepstral_lifter": 71.8337, "vtln_high": 7672, "vtln_low": 5265, "vtln_warp": 1.0, "window_type": "povey", "dither": 0.0} +{"blackman_coeff": 4.5474, "energy_floor": 0.7883, "frame_length": 0.5625, "frame_shift": 1.0, "high_freq": 7283, "htk_compat": false, "low_freq": 2418, "num_mel_bins": 4, "preemphasis_coefficient": 0.68, "raw_energy": true, "remove_dc_offset": true, "round_to_power_of_two": true, "snip_edges": false, "subtract_mean": true, "use_energy": true, "num_ceps": 4, "cepstral_lifter": 70.0635, "vtln_high": 7277, "vtln_low": 7265, "vtln_warp": 1.0, "window_type": "hamming", "dither": 0.0} +{"blackman_coeff": 4.5663, "energy_floor": 1.127, "frame_length": 1.125, "frame_shift": 0.8125, "high_freq": 6069, "htk_compat": true, "low_freq": 167, "num_mel_bins": 8, "preemphasis_coefficient": 0.68, "raw_energy": false, "remove_dc_offset": false, "round_to_power_of_two": true, "snip_edges": false, "subtract_mean": false, "use_energy": true, "num_ceps": 6, "cepstral_lifter": 1.624, "vtln_high": 2148, "vtln_low": 461, "vtln_warp": 1.0, "window_type": "rectangular", "dither": 0.0} +{"blackman_coeff": 4.5896, "energy_floor": 2.7617, "frame_length": 1.0625, "frame_shift": 0.8125, "high_freq": 3851, "htk_compat": true, "low_freq": 1115, "num_mel_bins": 4, "preemphasis_coefficient": 0.03, "raw_energy": true, "remove_dc_offset": false, "round_to_power_of_two": true, "snip_edges": true, "subtract_mean": false, "use_energy": false, "num_ceps": 4, "cepstral_lifter": 49.7637, "vtln_high": 2897, "vtln_low": 2701, "vtln_warp": 1.0, "window_type": "hanning", "dither": 0.0} +{"blackman_coeff": 4.6128, "energy_floor": 0.1203, "frame_length": 1.1875, "frame_shift": 0.9375, "high_freq": 6901, "htk_compat": false, "low_freq": 3577, "num_mel_bins": 6, "preemphasis_coefficient": 0.25, "raw_energy": false, "remove_dc_offset": false, "round_to_power_of_two": true, "snip_edges": false, "subtract_mean": true, "use_energy": false, "num_ceps": 3, "cepstral_lifter": 70.5509, "vtln_high": 5962, "vtln_low": 4190, "vtln_warp": 1.0, "window_type": "rectangular", "dither": 0.0} +{"blackman_coeff": 4.6262, "energy_floor": 4.1656, "frame_length": 1.1875, "frame_shift": 0.8125, "high_freq": 6147, "htk_compat": false, "low_freq": 1684, "num_mel_bins": 6, "preemphasis_coefficient": 0.58, "raw_energy": true, "remove_dc_offset": false, "round_to_power_of_two": true, "snip_edges": true, "subtract_mean": true, "use_energy": true, "num_ceps": 5, "cepstral_lifter": 54.2056, "vtln_high": 5259, "vtln_low": 2363, "vtln_warp": 1.0, "window_type": "rectangular", "dither": 0.0} +{"blackman_coeff": 4.6741, "energy_floor": 4.3867, "frame_length": 1.125, "frame_shift": 1.125, "high_freq": 6273, "htk_compat": false, "low_freq": 2481, "num_mel_bins": 4, "preemphasis_coefficient": 0.15, "raw_energy": true, "remove_dc_offset": false, "round_to_power_of_two": false, "snip_edges": true, "subtract_mean": false, "use_energy": false, "num_ceps": 4, "cepstral_lifter": 75.6122, "vtln_high": 3701, "vtln_low": 2992, "vtln_warp": 1.0, "window_type": "hamming", "dither": 0.0} +{"blackman_coeff": 4.6765, "energy_floor": 1.2644, "frame_length": 1.125, "frame_shift": 0.75, "high_freq": 5204, "htk_compat": false, "low_freq": 276, "num_mel_bins": 4, "preemphasis_coefficient": 0.04, "raw_energy": true, "remove_dc_offset": false, "round_to_power_of_two": false, "snip_edges": true, "subtract_mean": true, "use_energy": false, "num_ceps": 3, "cepstral_lifter": 96.116, "vtln_high": 5148, "vtln_low": 2541, "vtln_warp": 1.0, "window_type": "hamming", "dither": 0.0} +{"blackman_coeff": 4.7216, "energy_floor": 2.4818, "frame_length": 0.8125, "frame_shift": 0.375, "high_freq": 6723, "htk_compat": true, "low_freq": 2352, "num_mel_bins": 6, "preemphasis_coefficient": 0.14, "raw_energy": false, "remove_dc_offset": false, "round_to_power_of_two": true, "snip_edges": false, "subtract_mean": true, "use_energy": false, "num_ceps": 3, "cepstral_lifter": 32.0303, "vtln_high": 5598, "vtln_low": 2579, "vtln_warp": 1.0, "window_type": "hanning", "dither": 0.0} +{"blackman_coeff": 4.7919, "energy_floor": 2.6435, "frame_length": 0.625, "frame_shift": 0.5, "high_freq": 7971, "htk_compat": false, "low_freq": 1812, "num_mel_bins": 4, "preemphasis_coefficient": 0.65, "raw_energy": false, "remove_dc_offset": false, "round_to_power_of_two": false, "snip_edges": false, "subtract_mean": true, "use_energy": false, "num_ceps": 4, "cepstral_lifter": 27.7648, "vtln_high": 7735, "vtln_low": 7419, "vtln_warp": 1.0, "window_type": "povey", "dither": 0.0} +{"blackman_coeff": 4.814, "energy_floor": 0.468, "frame_length": 1.0625, "frame_shift": 0.6875, "high_freq": 5252, "htk_compat": true, "low_freq": 569, "num_mel_bins": 6, "preemphasis_coefficient": 0.85, "raw_energy": true, "remove_dc_offset": false, "round_to_power_of_two": true, "snip_edges": true, "subtract_mean": false, "use_energy": false, "num_ceps": 6, "cepstral_lifter": 56.449, "vtln_high": 4397, "vtln_low": 4332, "vtln_warp": 1.0, "window_type": "hamming", "dither": 0.0} +{"blackman_coeff": 4.95, "energy_floor": 4.5916, "frame_length": 1.125, "frame_shift": 1.0625, "high_freq": 5044, "htk_compat": true, "low_freq": 617, "num_mel_bins": 8, "preemphasis_coefficient": 0.89, "raw_energy": false, "remove_dc_offset": false, "round_to_power_of_two": false, "snip_edges": false, "subtract_mean": true, "use_energy": true, "num_ceps": 8, "cepstral_lifter": 23.3238, "vtln_high": 2732, "vtln_low": 2677, "vtln_warp": 1.0, "window_type": "hanning", "dither": 0.0} +{"blackman_coeff": 4.9663, "energy_floor": 4.7867, "frame_length": 1.1875, "frame_shift": 0.5, "high_freq": 2424, "htk_compat": false, "low_freq": 350, "num_mel_bins": 4, "preemphasis_coefficient": 0.39, "raw_energy": false, "remove_dc_offset": false, "round_to_power_of_two": true, "snip_edges": false, "subtract_mean": true, "use_energy": true, "num_ceps": 2, "cepstral_lifter": 59.4319, "vtln_high": 1202, "vtln_low": 1063, "vtln_warp": 1.0, "window_type": "hamming", "dither": 0.0} diff --git a/test/kaldi_compatibility_impl.py b/test/kaldi_compatibility_impl.py index 8fbdff75cb..2d3313d007 100644 --- a/test/kaldi_compatibility_impl.py +++ b/test/kaldi_compatibility_impl.py @@ -1,4 +1,5 @@ """Test suites for checking numerical compatibility against Kaldi""" +import json import shutil import unittest import subprocess @@ -9,6 +10,7 @@ import torchaudio.compliance.kaldi from . import common_utils +from parameterized import parameterized, param def _not_available(cmd): @@ -47,6 +49,11 @@ def _run_kaldi(command, input_type, input_value): return torch.from_numpy(result.copy()) # copy supresses some torch warning +def _load_params(path): + with open(path, 'r') as file: + return [param(json.loads(line)) for line in file] + + class Kaldi(common_utils.TestBaseMixin): def assert_equal(self, output, *, expected, rtol=None, atol=None): expected = expected.to(dtype=self.dtype, device=self.device) @@ -68,37 +75,24 @@ def test_sliding_window_cmn(self): kaldi_result = _run_kaldi(command, 'ark', tensor) self.assert_equal(result, expected=kaldi_result) + @parameterized.expand(_load_params(common_utils.get_asset_path('kaldi_test_fbank_args.json'))) @unittest.skipIf(_not_available('compute-fbank-feats'), '`compute-fbank-feats` not available') - def test_fbank(self): + def test_fbank(self, kwargs): """fbank should be numerically compatible with compute-fbank-feats""" - kwargs = { - 'blackman_coeff': 4.3926, - 'dither': 0.0, - 'energy_floor': 2.0617, - 'frame_length': 0.5625, - 'frame_shift': 0.0625, - 'high_freq': 4253, - 'htk_compat': True, - 'low_freq': 1367, - 'num_mel_bins': 5, - 'preemphasis_coefficient': 0.84, - 'raw_energy': False, - 'remove_dc_offset': True, - 'round_to_power_of_two': True, - 'snip_edges': True, - 'subtract_mean': False, - 'use_energy': True, - 'use_log_fbank': True, - 'use_power': False, - 'vtln_high': 2112, - 'vtln_low': 1445, - 'vtln_warp': 1.0000, - 'window_type': 'hamming', - - } wave_file = common_utils.get_asset_path('kaldi_file.wav') waveform = torchaudio.load_wav(wave_file)[0].to(dtype=self.dtype, device=self.device) result = torchaudio.compliance.kaldi.fbank(waveform, **kwargs) command = ['compute-fbank-feats'] + _convert_args(**kwargs) + ['scp:-', 'ark:-'] kaldi_result = _run_kaldi(command, 'scp', wave_file) self.assert_equal(result, expected=kaldi_result, rtol=1e-4, atol=1e-8) + + @parameterized.expand(_load_params(common_utils.get_asset_path('kaldi_test_mfcc_args.json'))) + @unittest.skipIf(_not_available('compute-mfcc-feats'), '`compute-mfcc-feats` not available') + def test_mfcc(self, kwargs): + """mfcc should be numerically compatible with compute-mfcc-feats""" + wave_file = common_utils.get_asset_path('kaldi_file.wav') + waveform = torchaudio.load_wav(wave_file)[0].to(dtype=self.dtype, device=self.device) + result = torchaudio.compliance.kaldi.mfcc(waveform, **kwargs) + command = ['compute-mfcc-feats'] + _convert_args(**kwargs) + ['scp:-', 'ark:-'] + kaldi_result = _run_kaldi(command, 'scp', wave_file) + self.assert_equal(result, expected=kaldi_result, rtol=1e-4, atol=1e-8) diff --git a/test/test_batch_consistency.py b/test/test_batch_consistency.py index c10652d9ca..103d83bb84 100644 --- a/test/test_batch_consistency.py +++ b/test/test_batch_consistency.py @@ -84,6 +84,12 @@ def test_phaser(self): waveform, sample_rate = torchaudio.load(filepath) self.assert_batch_consistencies(F.phaser, waveform, sample_rate) + def test_flanger(self): + torch.random.manual_seed(40) + waveform = torch.rand(2, 100) - 0.5 + sample_rate = 44100 + self.assert_batch_consistencies(F.flanger, waveform, sample_rate) + def test_sliding_window_cmn(self): waveform = torch.randn(2, 1024) - 0.5 self.assert_batch_consistencies(F.sliding_window_cmn, waveform, center=True, norm_vars=True) diff --git a/test/test_datasets.py b/test/test_datasets.py index 96c12884d6..ab1e74e888 100644 --- a/test/test_datasets.py +++ b/test/test_datasets.py @@ -7,6 +7,7 @@ from torchaudio.datasets.vctk import VCTK from torchaudio.datasets.yesno import YESNO from torchaudio.datasets.ljspeech import LJSPEECH +from torchaudio.datasets.gtzan import GTZAN from . import common_utils @@ -55,6 +56,10 @@ def test_speechcommands(self): data = SPEECHCOMMANDS(self.path) data[0] + def test_gtzan(self): + data = GTZAN(self.path) + data[0] + if __name__ == "__main__": unittest.main() diff --git a/test/test_sox_compatibility.py b/test/test_sox_compatibility.py index dfa57cec47..b6e6dbaedd 100644 --- a/test/test_sox_compatibility.py +++ b/test/test_sox_compatibility.py @@ -265,6 +265,28 @@ def test_treble(self): self.assertEqual(output_waveform, sox_output_waveform, atol=1e-4, rtol=1e-5) + @unittest.skipIf("sox" not in BACKENDS, "sox not available") + @AudioBackendScope("sox") + def test_bass(self): + """ + Test biquad bass filter, compare to SoX implementation + """ + + central_freq = 1000 + q = 0.707 + gain = 40 + + noise_filepath = common_utils.get_asset_path('whitenoise.wav') + E = torchaudio.sox_effects.SoxEffectsChain() + E.set_input_file(noise_filepath) + E.append_effect_to_chain("bass", [gain, central_freq, str(q) + 'q']) + sox_output_waveform, sr = E.sox_build_flow_effects() + + waveform, sample_rate = torchaudio.load(noise_filepath, normalization=True) + output_waveform = F.bass_biquad(waveform, sample_rate, gain, central_freq, q) + + self.assertEqual(output_waveform, sox_output_waveform, atol=1.5e-4, rtol=1e-5) + @unittest.skipIf("sox" not in BACKENDS, "sox not available") @AudioBackendScope("sox") def test_deemph(self): @@ -419,6 +441,102 @@ def test_phaser_triangle(self): self.assertEqual(output_waveform, sox_output_waveform, atol=1e-4, rtol=1e-5) + @unittest.skipIf("sox" not in BACKENDS, "sox not available") + @AudioBackendScope("sox") + def test_flanger_triangle_linear(self): + """ + Test flanger effect with triangle modulation and linear interpolation, compare to SoX implementation + """ + delay = 0.6 + depth = 0.87 + regen = 3.0 + width = 0.9 + speed = 0.5 + phase = 30 + noise_filepath = common_utils.get_asset_path('whitenoise.wav') + E = torchaudio.sox_effects.SoxEffectsChain() + E.set_input_file(noise_filepath) + E.append_effect_to_chain("flanger", [delay, depth, regen, width, speed, "triangle", phase, "linear"]) + sox_output_waveform, sr = E.sox_build_flow_effects() + + waveform, sample_rate = torchaudio.load(noise_filepath, normalization=True) + output_waveform = F.flanger(waveform, sample_rate, delay, depth, regen, width, speed, phase, + modulation='triangular', interpolation='linear') + + torch.testing.assert_allclose(output_waveform, sox_output_waveform, atol=1e-4, rtol=1e-5) + + @unittest.skipIf("sox" not in BACKENDS, "sox not available") + @AudioBackendScope("sox") + def test_flanger_triangle_quad(self): + """ + Test flanger effect with triangle modulation and quadratic interpolation, compare to SoX implementation + """ + delay = 0.8 + depth = 0.88 + regen = 3.0 + width = 0.4 + speed = 0.5 + phase = 40 + noise_filepath = common_utils.get_asset_path('whitenoise.wav') + E = torchaudio.sox_effects.SoxEffectsChain() + E.set_input_file(noise_filepath) + E.append_effect_to_chain("flanger", [delay, depth, regen, width, speed, "triangle", phase, "quadratic"]) + sox_output_waveform, sr = E.sox_build_flow_effects() + + waveform, sample_rate = torchaudio.load(noise_filepath, normalization=True) + output_waveform = F.flanger(waveform, sample_rate, delay, depth, regen, width, speed, phase, + modulation='triangular', interpolation='quadratic') + + torch.testing.assert_allclose(output_waveform, sox_output_waveform, atol=1e-4, rtol=1e-5) + + @unittest.skipIf("sox" not in BACKENDS, "sox not available") + @AudioBackendScope("sox") + def test_flanger_sine_linear(self): + """ + Test flanger effect with sine modulation and linear interpolation, compare to SoX implementation + """ + delay = 0.8 + depth = 0.88 + regen = 3.0 + width = 0.23 + speed = 1.3 + phase = 60 + noise_filepath = common_utils.get_asset_path('whitenoise.wav') + E = torchaudio.sox_effects.SoxEffectsChain() + E.set_input_file(noise_filepath) + E.append_effect_to_chain("flanger", [delay, depth, regen, width, speed, "sine", phase, "linear"]) + sox_output_waveform, sr = E.sox_build_flow_effects() + + waveform, sample_rate = torchaudio.load(noise_filepath, normalization=True) + output_waveform = F.flanger(waveform, sample_rate, delay, depth, regen, width, speed, phase, + modulation='sinusoidal', interpolation='linear') + + torch.testing.assert_allclose(output_waveform, sox_output_waveform, atol=1e-4, rtol=1e-5) + + @unittest.skipIf("sox" not in BACKENDS, "sox not available") + @AudioBackendScope("sox") + def test_flanger_sine_quad(self): + """ + Test flanger effect with sine modulation and quadratic interpolation, compare to SoX implementation + """ + delay = 0.9 + depth = 0.9 + regen = 4.0 + width = 0.23 + speed = 1.3 + phase = 25 + noise_filepath = common_utils.get_asset_path('whitenoise.wav') + E = torchaudio.sox_effects.SoxEffectsChain() + E.set_input_file(noise_filepath) + E.append_effect_to_chain("flanger", [delay, depth, regen, width, speed, "sine", phase, "quadratic"]) + sox_output_waveform, sr = E.sox_build_flow_effects() + + waveform, sample_rate = torchaudio.load(noise_filepath, normalization=True) + output_waveform = F.flanger(waveform, sample_rate, delay, depth, regen, width, speed, phase, + modulation='sinusoidal', interpolation='quadratic') + + torch.testing.assert_allclose(output_waveform, sox_output_waveform, atol=1e-4, rtol=1e-5) + @unittest.skipIf("sox" not in BACKENDS, "sox not available") @AudioBackendScope("sox") def test_equalizer(self): diff --git a/test/test_transforms.py b/test/test_transforms.py index 02faa68992..ad8a55fb4b 100644 --- a/test/test_transforms.py +++ b/test/test_transforms.py @@ -31,7 +31,10 @@ def test_mu_law_companding(self): quantization_channels = 256 waveform = self.waveform.clone() + if not waveform.is_floating_point(): + waveform = waveform.to(torch.get_default_dtype()) waveform /= torch.abs(waveform).max() + self.assertTrue(waveform.min() >= -1. and waveform.max() <= 1.) waveform_mu = transforms.MuLawEncoding(quantization_channels)(waveform) diff --git a/test/torchscript_consistency_impl.py b/test/torchscript_consistency_impl.py index a4d3cc79cf..a84b629bd7 100644 --- a/test/torchscript_consistency_impl.py +++ b/test/torchscript_consistency_impl.py @@ -367,6 +367,21 @@ def func(tensor): self._assert_consistency(func, waveform) + def test_bass(self): + if self.dtype == torch.float64: + raise unittest.SkipTest("This test is known to fail for float64") + + waveform = common_utils.get_whitenoise(sample_rate=44100) + + def func(tensor): + sample_rate = 44100 + gain = 40. + central_freq = 1000. + q = 0.707 + return F.bass_biquad(tensor, sample_rate, gain, central_freq, q) + + self._assert_consistency(func, waveform) + def test_deemph(self): if self.dtype == torch.float64: raise unittest.SkipTest("This test is known to fail for float64") @@ -497,6 +512,23 @@ def func(tensor): self._assert_consistency(func, waveform) + def test_flanger(self): + torch.random.manual_seed(40) + waveform = torch.rand(2, 100) - 0.5 + + def func(tensor): + delay = 0.8 + depth = 0.88 + regen = 3.0 + width = 0.23 + speed = 1.3 + phase = 60. + sample_rate = 44100 + return F.flanger(tensor, sample_rate, delay, depth, regen, width, speed, + phase, modulation='sinusoidal', interpolation='linear') + + self._assert_consistency(func, waveform) + class Transforms(common_utils.TestBaseMixin): """Implements test for Transforms that are performed for different devices""" diff --git a/torchaudio/compliance/kaldi.py b/torchaudio/compliance/kaldi.py index 8115c3a25f..bdf5f407ba 100644 --- a/torchaudio/compliance/kaldi.py +++ b/torchaudio/compliance/kaldi.py @@ -696,6 +696,8 @@ def mfcc( """ assert num_ceps <= num_mel_bins, 'num_ceps cannot be larger than num_mel_bins: %d vs %d' % (num_ceps, num_mel_bins) + device, dtype = waveform.device, waveform.dtype + # The mel_energies should not be squared (use_power=True), not have mean subtracted # (subtract_mean=False), and use log (use_log_fbank=True). # size (m, num_mel_bins + use_energy) @@ -717,7 +719,7 @@ def mfcc( feature = feature[:, mel_offset:(num_mel_bins + mel_offset)] # size (num_mel_bins, num_ceps) - dct_matrix = _get_dct_matrix(num_ceps, num_mel_bins) + dct_matrix = _get_dct_matrix(num_ceps, num_mel_bins).to(dtype=dtype, device=device) # size (m, num_ceps) feature = feature.matmul(dct_matrix) @@ -725,7 +727,7 @@ def mfcc( if cepstral_lifter != 0.0: # size (1, num_ceps) lifter_coeffs = _get_lifter_coeffs(num_ceps, cepstral_lifter).unsqueeze(0) - feature *= lifter_coeffs + feature *= lifter_coeffs.to(device=device, dtype=dtype) # if use_energy then replace the last column for htk_compat == true else first column if use_energy: diff --git a/torchaudio/datasets/__init__.py b/torchaudio/datasets/__init__.py index 26d8216114..1741889029 100644 --- a/torchaudio/datasets/__init__.py +++ b/torchaudio/datasets/__init__.py @@ -3,6 +3,7 @@ from .speechcommands import SPEECHCOMMANDS from .utils import bg_iterator, diskcache_iterator from .vctk import VCTK +from .gtzan import GTZAN from .yesno import YESNO from .ljspeech import LJSPEECH @@ -13,6 +14,7 @@ "VCTK", "YESNO", "LJSPEECH", + "GTZAN", "diskcache_iterator", "bg_iterator", ) diff --git a/torchaudio/datasets/gtzan.py b/torchaudio/datasets/gtzan.py new file mode 100644 index 0000000000..13d7e8b68b --- /dev/null +++ b/torchaudio/datasets/gtzan.py @@ -0,0 +1,1054 @@ +import os +import warnings +from typing import Any, Tuple + +import torchaudio +from torch import Tensor +from torch.utils.data import Dataset +from torchaudio.datasets.utils import ( + download_url, + extract_archive, + walk_files, +) + +# The following lists prefixed with `filtered_` provide a filtered split +# that: +# +# a. Mitigate a known issue with GTZAN (duplication) +# +# b. Provide a standard split for testing it against other +# methods (e.g. the one in jordipons/sklearn-audio-transfer-learning). +# +# Those are used when GTZAN is initialised with the `filtered` keyword. +# The split was taken from (github) jordipons/sklearn-audio-transfer-learning. + +filtered_test = [ + "blues.00012", + "blues.00013", + "blues.00014", + "blues.00015", + "blues.00016", + "blues.00017", + "blues.00018", + "blues.00019", + "blues.00020", + "blues.00021", + "blues.00022", + "blues.00023", + "blues.00024", + "blues.00025", + "blues.00026", + "blues.00027", + "blues.00028", + "blues.00061", + "blues.00062", + "blues.00063", + "blues.00064", + "blues.00065", + "blues.00066", + "blues.00067", + "blues.00068", + "blues.00069", + "blues.00070", + "blues.00071", + "blues.00072", + "blues.00098", + "blues.00099", + "classical.00011", + "classical.00012", + "classical.00013", + "classical.00014", + "classical.00015", + "classical.00016", + "classical.00017", + "classical.00018", + "classical.00019", + "classical.00020", + "classical.00021", + "classical.00022", + "classical.00023", + "classical.00024", + "classical.00025", + "classical.00026", + "classical.00027", + "classical.00028", + "classical.00029", + "classical.00034", + "classical.00035", + "classical.00036", + "classical.00037", + "classical.00038", + "classical.00039", + "classical.00040", + "classical.00041", + "classical.00049", + "classical.00077", + "classical.00078", + "classical.00079", + "country.00030", + "country.00031", + "country.00032", + "country.00033", + "country.00034", + "country.00035", + "country.00036", + "country.00037", + "country.00038", + "country.00039", + "country.00040", + "country.00043", + "country.00044", + "country.00046", + "country.00047", + "country.00048", + "country.00050", + "country.00051", + "country.00053", + "country.00054", + "country.00055", + "country.00056", + "country.00057", + "country.00058", + "country.00059", + "country.00060", + "country.00061", + "country.00062", + "country.00063", + "country.00064", + "disco.00001", + "disco.00021", + "disco.00058", + "disco.00062", + "disco.00063", + "disco.00064", + "disco.00065", + "disco.00066", + "disco.00069", + "disco.00076", + "disco.00077", + "disco.00078", + "disco.00079", + "disco.00080", + "disco.00081", + "disco.00082", + "disco.00083", + "disco.00084", + "disco.00085", + "disco.00086", + "disco.00087", + "disco.00088", + "disco.00091", + "disco.00092", + "disco.00093", + "disco.00094", + "disco.00096", + "disco.00097", + "disco.00099", + "hiphop.00000", + "hiphop.00026", + "hiphop.00027", + "hiphop.00030", + "hiphop.00040", + "hiphop.00043", + "hiphop.00044", + "hiphop.00045", + "hiphop.00051", + "hiphop.00052", + "hiphop.00053", + "hiphop.00054", + "hiphop.00062", + "hiphop.00063", + "hiphop.00064", + "hiphop.00065", + "hiphop.00066", + "hiphop.00067", + "hiphop.00068", + "hiphop.00069", + "hiphop.00070", + "hiphop.00071", + "hiphop.00072", + "hiphop.00073", + "hiphop.00074", + "hiphop.00075", + "hiphop.00099", + "jazz.00073", + "jazz.00074", + "jazz.00075", + "jazz.00076", + "jazz.00077", + "jazz.00078", + "jazz.00079", + "jazz.00080", + "jazz.00081", + "jazz.00082", + "jazz.00083", + "jazz.00084", + "jazz.00085", + "jazz.00086", + "jazz.00087", + "jazz.00088", + "jazz.00089", + "jazz.00090", + "jazz.00091", + "jazz.00092", + "jazz.00093", + "jazz.00094", + "jazz.00095", + "jazz.00096", + "jazz.00097", + "jazz.00098", + "jazz.00099", + "metal.00012", + "metal.00013", + "metal.00014", + "metal.00015", + "metal.00022", + "metal.00023", + "metal.00025", + "metal.00026", + "metal.00027", + "metal.00028", + "metal.00029", + "metal.00030", + "metal.00031", + "metal.00032", + "metal.00033", + "metal.00038", + "metal.00039", + "metal.00067", + "metal.00070", + "metal.00073", + "metal.00074", + "metal.00075", + "metal.00078", + "metal.00083", + "metal.00085", + "metal.00087", + "metal.00088", + "pop.00000", + "pop.00001", + "pop.00013", + "pop.00014", + "pop.00043", + "pop.00063", + "pop.00064", + "pop.00065", + "pop.00066", + "pop.00069", + "pop.00070", + "pop.00071", + "pop.00072", + "pop.00073", + "pop.00074", + "pop.00075", + "pop.00076", + "pop.00077", + "pop.00078", + "pop.00079", + "pop.00082", + "pop.00088", + "pop.00089", + "pop.00090", + "pop.00091", + "pop.00092", + "pop.00093", + "pop.00094", + "pop.00095", + "pop.00096", + "reggae.00034", + "reggae.00035", + "reggae.00036", + "reggae.00037", + "reggae.00038", + "reggae.00039", + "reggae.00040", + "reggae.00046", + "reggae.00047", + "reggae.00048", + "reggae.00052", + "reggae.00053", + "reggae.00064", + "reggae.00065", + "reggae.00066", + "reggae.00067", + "reggae.00068", + "reggae.00071", + "reggae.00079", + "reggae.00082", + "reggae.00083", + "reggae.00084", + "reggae.00087", + "reggae.00088", + "reggae.00089", + "reggae.00090", + "rock.00010", + "rock.00011", + "rock.00012", + "rock.00013", + "rock.00014", + "rock.00015", + "rock.00027", + "rock.00028", + "rock.00029", + "rock.00030", + "rock.00031", + "rock.00032", + "rock.00033", + "rock.00034", + "rock.00035", + "rock.00036", + "rock.00037", + "rock.00039", + "rock.00040", + "rock.00041", + "rock.00042", + "rock.00043", + "rock.00044", + "rock.00045", + "rock.00046", + "rock.00047", + "rock.00048", + "rock.00086", + "rock.00087", + "rock.00088", + "rock.00089", + "rock.00090", +] + +filtered_train = [ + "blues.00029", + "blues.00030", + "blues.00031", + "blues.00032", + "blues.00033", + "blues.00034", + "blues.00035", + "blues.00036", + "blues.00037", + "blues.00038", + "blues.00039", + "blues.00040", + "blues.00041", + "blues.00042", + "blues.00043", + "blues.00044", + "blues.00045", + "blues.00046", + "blues.00047", + "blues.00048", + "blues.00049", + "blues.00073", + "blues.00074", + "blues.00075", + "blues.00076", + "blues.00077", + "blues.00078", + "blues.00079", + "blues.00080", + "blues.00081", + "blues.00082", + "blues.00083", + "blues.00084", + "blues.00085", + "blues.00086", + "blues.00087", + "blues.00088", + "blues.00089", + "blues.00090", + "blues.00091", + "blues.00092", + "blues.00093", + "blues.00094", + "blues.00095", + "blues.00096", + "blues.00097", + "classical.00030", + "classical.00031", + "classical.00032", + "classical.00033", + "classical.00043", + "classical.00044", + "classical.00045", + "classical.00046", + "classical.00047", + "classical.00048", + "classical.00050", + "classical.00051", + "classical.00052", + "classical.00053", + "classical.00054", + "classical.00055", + "classical.00056", + "classical.00057", + "classical.00058", + "classical.00059", + "classical.00060", + "classical.00061", + "classical.00062", + "classical.00063", + "classical.00064", + "classical.00065", + "classical.00066", + "classical.00067", + "classical.00080", + "classical.00081", + "classical.00082", + "classical.00083", + "classical.00084", + "classical.00085", + "classical.00086", + "classical.00087", + "classical.00088", + "classical.00089", + "classical.00090", + "classical.00091", + "classical.00092", + "classical.00093", + "classical.00094", + "classical.00095", + "classical.00096", + "classical.00097", + "classical.00098", + "classical.00099", + "country.00019", + "country.00020", + "country.00021", + "country.00022", + "country.00023", + "country.00024", + "country.00025", + "country.00026", + "country.00028", + "country.00029", + "country.00065", + "country.00066", + "country.00067", + "country.00068", + "country.00069", + "country.00070", + "country.00071", + "country.00072", + "country.00073", + "country.00074", + "country.00075", + "country.00076", + "country.00077", + "country.00078", + "country.00079", + "country.00080", + "country.00081", + "country.00082", + "country.00083", + "country.00084", + "country.00085", + "country.00086", + "country.00087", + "country.00088", + "country.00089", + "country.00090", + "country.00091", + "country.00092", + "country.00093", + "country.00094", + "country.00095", + "country.00096", + "country.00097", + "country.00098", + "country.00099", + "disco.00005", + "disco.00015", + "disco.00016", + "disco.00017", + "disco.00018", + "disco.00019", + "disco.00020", + "disco.00022", + "disco.00023", + "disco.00024", + "disco.00025", + "disco.00026", + "disco.00027", + "disco.00028", + "disco.00029", + "disco.00030", + "disco.00031", + "disco.00032", + "disco.00033", + "disco.00034", + "disco.00035", + "disco.00036", + "disco.00037", + "disco.00039", + "disco.00040", + "disco.00041", + "disco.00042", + "disco.00043", + "disco.00044", + "disco.00045", + "disco.00047", + "disco.00049", + "disco.00053", + "disco.00054", + "disco.00056", + "disco.00057", + "disco.00059", + "disco.00061", + "disco.00070", + "disco.00073", + "disco.00074", + "disco.00089", + "hiphop.00002", + "hiphop.00003", + "hiphop.00004", + "hiphop.00005", + "hiphop.00006", + "hiphop.00007", + "hiphop.00008", + "hiphop.00009", + "hiphop.00010", + "hiphop.00011", + "hiphop.00012", + "hiphop.00013", + "hiphop.00014", + "hiphop.00015", + "hiphop.00016", + "hiphop.00017", + "hiphop.00018", + "hiphop.00019", + "hiphop.00020", + "hiphop.00021", + "hiphop.00022", + "hiphop.00023", + "hiphop.00024", + "hiphop.00025", + "hiphop.00028", + "hiphop.00029", + "hiphop.00031", + "hiphop.00032", + "hiphop.00033", + "hiphop.00034", + "hiphop.00035", + "hiphop.00036", + "hiphop.00037", + "hiphop.00038", + "hiphop.00041", + "hiphop.00042", + "hiphop.00055", + "hiphop.00056", + "hiphop.00057", + "hiphop.00058", + "hiphop.00059", + "hiphop.00060", + "hiphop.00061", + "hiphop.00077", + "hiphop.00078", + "hiphop.00079", + "hiphop.00080", + "jazz.00000", + "jazz.00001", + "jazz.00011", + "jazz.00012", + "jazz.00013", + "jazz.00014", + "jazz.00015", + "jazz.00016", + "jazz.00017", + "jazz.00018", + "jazz.00019", + "jazz.00020", + "jazz.00021", + "jazz.00022", + "jazz.00023", + "jazz.00024", + "jazz.00041", + "jazz.00047", + "jazz.00048", + "jazz.00049", + "jazz.00050", + "jazz.00051", + "jazz.00052", + "jazz.00053", + "jazz.00054", + "jazz.00055", + "jazz.00056", + "jazz.00057", + "jazz.00058", + "jazz.00059", + "jazz.00060", + "jazz.00061", + "jazz.00062", + "jazz.00063", + "jazz.00064", + "jazz.00065", + "jazz.00066", + "jazz.00067", + "jazz.00068", + "jazz.00069", + "jazz.00070", + "jazz.00071", + "jazz.00072", + "metal.00002", + "metal.00003", + "metal.00005", + "metal.00021", + "metal.00024", + "metal.00035", + "metal.00046", + "metal.00047", + "metal.00048", + "metal.00049", + "metal.00050", + "metal.00051", + "metal.00052", + "metal.00053", + "metal.00054", + "metal.00055", + "metal.00056", + "metal.00057", + "metal.00059", + "metal.00060", + "metal.00061", + "metal.00062", + "metal.00063", + "metal.00064", + "metal.00065", + "metal.00066", + "metal.00069", + "metal.00071", + "metal.00072", + "metal.00079", + "metal.00080", + "metal.00084", + "metal.00086", + "metal.00089", + "metal.00090", + "metal.00091", + "metal.00092", + "metal.00093", + "metal.00094", + "metal.00095", + "metal.00096", + "metal.00097", + "metal.00098", + "metal.00099", + "pop.00002", + "pop.00003", + "pop.00004", + "pop.00005", + "pop.00006", + "pop.00007", + "pop.00008", + "pop.00009", + "pop.00011", + "pop.00012", + "pop.00016", + "pop.00017", + "pop.00018", + "pop.00019", + "pop.00020", + "pop.00023", + "pop.00024", + "pop.00025", + "pop.00026", + "pop.00027", + "pop.00028", + "pop.00029", + "pop.00031", + "pop.00032", + "pop.00033", + "pop.00034", + "pop.00035", + "pop.00036", + "pop.00038", + "pop.00039", + "pop.00040", + "pop.00041", + "pop.00042", + "pop.00044", + "pop.00046", + "pop.00049", + "pop.00050", + "pop.00080", + "pop.00097", + "pop.00098", + "pop.00099", + "reggae.00000", + "reggae.00001", + "reggae.00002", + "reggae.00004", + "reggae.00006", + "reggae.00009", + "reggae.00011", + "reggae.00012", + "reggae.00014", + "reggae.00015", + "reggae.00016", + "reggae.00017", + "reggae.00018", + "reggae.00019", + "reggae.00020", + "reggae.00021", + "reggae.00022", + "reggae.00023", + "reggae.00024", + "reggae.00025", + "reggae.00026", + "reggae.00027", + "reggae.00028", + "reggae.00029", + "reggae.00030", + "reggae.00031", + "reggae.00032", + "reggae.00042", + "reggae.00043", + "reggae.00044", + "reggae.00045", + "reggae.00049", + "reggae.00050", + "reggae.00051", + "reggae.00054", + "reggae.00055", + "reggae.00056", + "reggae.00057", + "reggae.00058", + "reggae.00059", + "reggae.00060", + "reggae.00063", + "reggae.00069", + "rock.00000", + "rock.00001", + "rock.00002", + "rock.00003", + "rock.00004", + "rock.00005", + "rock.00006", + "rock.00007", + "rock.00008", + "rock.00009", + "rock.00016", + "rock.00017", + "rock.00018", + "rock.00019", + "rock.00020", + "rock.00021", + "rock.00022", + "rock.00023", + "rock.00024", + "rock.00025", + "rock.00026", + "rock.00057", + "rock.00058", + "rock.00059", + "rock.00060", + "rock.00061", + "rock.00062", + "rock.00063", + "rock.00064", + "rock.00065", + "rock.00066", + "rock.00067", + "rock.00068", + "rock.00069", + "rock.00070", + "rock.00091", + "rock.00092", + "rock.00093", + "rock.00094", + "rock.00095", + "rock.00096", + "rock.00097", + "rock.00098", + "rock.00099", +] + +filtered_valid = [ + "blues.00000", + "blues.00001", + "blues.00002", + "blues.00003", + "blues.00004", + "blues.00005", + "blues.00006", + "blues.00007", + "blues.00008", + "blues.00009", + "blues.00010", + "blues.00011", + "blues.00050", + "blues.00051", + "blues.00052", + "blues.00053", + "blues.00054", + "blues.00055", + "blues.00056", + "blues.00057", + "blues.00058", + "blues.00059", + "blues.00060", + "classical.00000", + "classical.00001", + "classical.00002", + "classical.00003", + "classical.00004", + "classical.00005", + "classical.00006", + "classical.00007", + "classical.00008", + "classical.00009", + "classical.00010", + "classical.00068", + "classical.00069", + "classical.00070", + "classical.00071", + "classical.00072", + "classical.00073", + "classical.00074", + "classical.00075", + "classical.00076", + "country.00000", + "country.00001", + "country.00002", + "country.00003", + "country.00004", + "country.00005", + "country.00006", + "country.00007", + "country.00009", + "country.00010", + "country.00011", + "country.00012", + "country.00013", + "country.00014", + "country.00015", + "country.00016", + "country.00017", + "country.00018", + "country.00027", + "country.00041", + "country.00042", + "country.00045", + "country.00049", + "disco.00000", + "disco.00002", + "disco.00003", + "disco.00004", + "disco.00006", + "disco.00007", + "disco.00008", + "disco.00009", + "disco.00010", + "disco.00011", + "disco.00012", + "disco.00013", + "disco.00014", + "disco.00046", + "disco.00048", + "disco.00052", + "disco.00067", + "disco.00068", + "disco.00072", + "disco.00075", + "disco.00090", + "disco.00095", + "hiphop.00081", + "hiphop.00082", + "hiphop.00083", + "hiphop.00084", + "hiphop.00085", + "hiphop.00086", + "hiphop.00087", + "hiphop.00088", + "hiphop.00089", + "hiphop.00090", + "hiphop.00091", + "hiphop.00092", + "hiphop.00093", + "hiphop.00094", + "hiphop.00095", + "hiphop.00096", + "hiphop.00097", + "hiphop.00098", + "jazz.00002", + "jazz.00003", + "jazz.00004", + "jazz.00005", + "jazz.00006", + "jazz.00007", + "jazz.00008", + "jazz.00009", + "jazz.00010", + "jazz.00025", + "jazz.00026", + "jazz.00027", + "jazz.00028", + "jazz.00029", + "jazz.00030", + "jazz.00031", + "jazz.00032", + "metal.00000", + "metal.00001", + "metal.00006", + "metal.00007", + "metal.00008", + "metal.00009", + "metal.00010", + "metal.00011", + "metal.00016", + "metal.00017", + "metal.00018", + "metal.00019", + "metal.00020", + "metal.00036", + "metal.00037", + "metal.00068", + "metal.00076", + "metal.00077", + "metal.00081", + "metal.00082", + "pop.00010", + "pop.00053", + "pop.00055", + "pop.00058", + "pop.00059", + "pop.00060", + "pop.00061", + "pop.00062", + "pop.00081", + "pop.00083", + "pop.00084", + "pop.00085", + "pop.00086", + "reggae.00061", + "reggae.00062", + "reggae.00070", + "reggae.00072", + "reggae.00074", + "reggae.00076", + "reggae.00077", + "reggae.00078", + "reggae.00085", + "reggae.00092", + "reggae.00093", + "reggae.00094", + "reggae.00095", + "reggae.00096", + "reggae.00097", + "reggae.00098", + "reggae.00099", + "rock.00038", + "rock.00049", + "rock.00050", + "rock.00051", + "rock.00052", + "rock.00053", + "rock.00054", + "rock.00055", + "rock.00056", + "rock.00071", + "rock.00072", + "rock.00073", + "rock.00074", + "rock.00075", + "rock.00076", + "rock.00077", + "rock.00078", + "rock.00079", + "rock.00080", + "rock.00081", + "rock.00082", + "rock.00083", + "rock.00084", + "rock.00085", +] + + +URL = "http://opihi.cs.uvic.ca/sound/genres.tar.gz" +FOLDER_IN_ARCHIVE = "genres" +_CHECKSUMS = {"http://opihi.cs.uvic.ca/sound/genres.tar.gz": "5b3d6dddb579ab49814ab86dba69e7c7"} + + +def load_gtzan_item(fileid: str, path: str, ext_audio: str) -> Tuple[Tensor, str]: + """ + Loads a file from the dataset and returns the raw waveform + as a Torch Tensor, its sample rate as an integer, and its + genre as a string. + """ + # Filenames are of the form label.id, e.g. blues.00078 + label, _ = fileid.split(".") + + # Read wav + file_audio = os.path.join(path, label, fileid + ext_audio) + waveform, sample_rate = torchaudio.load(file_audio) + + return waveform, sample_rate, label + + +class GTZAN(Dataset): + """ + Create a Dataset for GTZAN. Each item is a tuple of the form: + waveform, sample_rate, label. + + Please see http://marsyas.info/downloads/datasets.html + if you are planning to use this dataset to publish results. + """ + + _ext_audio = ".wav" + + def __init__( + self, + root: str, + url: str = URL, + folder_in_archive: str = FOLDER_IN_ARCHIVE, + download: bool = False, + subset: Any = None, + ) -> None: + + # super(GTZAN, self).__init__() + self.root = root + self.url = url + self.folder_in_archive = folder_in_archive + self.download = download + self.subset = subset + + assert subset is None or subset in ["training", "validation", "testing"], ( + "When `subset` not None, it must take a value from " + + "{'training', 'validation', 'testing'}." + ) + + archive = os.path.basename(url) + archive = os.path.join(root, archive) + self._path = os.path.join(root, folder_in_archive) + + if download: + if not os.path.isdir(self._path): + if not os.path.isfile(archive): + checksum = _CHECKSUMS.get(url, None) + download_url(url, root, hash_value=checksum, hash_type="md5") + extract_archive(archive) + + if not os.path.isdir(self._path): + raise RuntimeError( + "Dataset not found. Please use `download=True` to download it." + ) + + if self.subset is None: + walker = walk_files( + self._path, suffix=self._ext_audio, prefix=False, remove_suffix=True + ) + self._walker = list(walker) + else: + if self.subset == "training": + self._walker = filtered_train + elif self.subset == "validation": + self._walker = filtered_valid + elif self.subset == "testing": + self._walker = filtered_test + + def __getitem__(self, n: int) -> Tuple[Tensor, int, str]: + fileid = self._walker[n] + item = load_gtzan_item(fileid, self._path, self._ext_audio) + waveform, sample_rate, label = item + return waveform, sample_rate, label + + def __len__(self) -> int: + return len(self._walker) diff --git a/torchaudio/functional.py b/torchaudio/functional.py index f59c46eb14..92580e1d9e 100644 --- a/torchaudio/functional.py +++ b/torchaudio/functional.py @@ -29,6 +29,7 @@ "equalizer_biquad", "band_biquad", "treble_biquad", + "bass_biquad", "deemph_biquad", "riaa_biquad", "biquad", @@ -36,6 +37,7 @@ "dcshift", "overdrive", "phaser", + "flanger", 'mask_along_axis', 'mask_along_axis_iid', 'sliding_window_cmn', @@ -987,6 +989,47 @@ def treble_biquad( return biquad(waveform, b0, b1, b2, a0, a1, a2) +def bass_biquad( + waveform: Tensor, + sample_rate: int, + gain: float, + central_freq: float = 100, + Q: float = 0.707 +) -> Tensor: + r"""Design a bass tone-control effect. Similar to SoX implementation. + + Args: + waveform (Tensor): audio waveform of dimension of `(..., time)` + sample_rate (int): sampling rate of the waveform, e.g. 44100 (Hz) + gain (float): desired gain at the boost (or attenuation) in dB. + central_freq (float, optional): central frequency (in Hz). (Default: ``100``) + Q (float, optional): https://en.wikipedia.org/wiki/Q_factor (Default: ``0.707``). + + Returns: + Tensor: Waveform of dimension of `(..., time)` + + References: + http://sox.sourceforge.net/sox.html + https://www.w3.org/2011/audio/audio-eq-cookbook.html#APF + """ + w0 = 2 * math.pi * central_freq / sample_rate + alpha = math.sin(w0) / 2 / Q + A = math.exp(gain / 40 * math.log(10)) + + temp1 = 2 * math.sqrt(A) * alpha + temp2 = (A - 1) * math.cos(w0) + temp3 = (A + 1) * math.cos(w0) + + b0 = A * ((A + 1) - temp2 + temp1) + b1 = 2 * A * ((A - 1) - temp3) + b2 = A * ((A + 1) - temp2 - temp1) + a0 = (A + 1) + temp2 + temp1 + a1 = -2 * ((A - 1) + temp3) + a2 = (A + 1) + temp2 - temp1 + + return biquad(waveform, b0 / a0, b1 / a0, b2 / a0, a0 / a0, a1 / a0, a2 / a0) + + def deemph_biquad( waveform: Tensor, sample_rate: int @@ -1357,6 +1400,156 @@ def _generate_wave_table( return d +def flanger( + waveform: Tensor, + sample_rate: int, + delay: float = 0., + depth: float = 2., + regen: float = 0., + width: float = 71., + speed: float = 0.5, + phase: float = 25., + modulation: str = 'sinusoidal', + interpolation: str = 'linear' +) -> Tensor: + r"""Apply a flanger effect to the audio. Similar to SoX implementation. + + Args: + waveform (Tensor): audio waveform of dimension of `(..., channel, time)` . + Max 4 channels allowed + sample_rate (int): sampling rate of the waveform, e.g. 44100 (Hz) + delay (float): desired delay in milliseconds(ms) + Allowed range of values are 0 to 30 + depth (float): desired delay depth in milliseconds(ms) + Allowed range of values are 0 to 10 + regen (float): desired regen(feeback gain) in dB + Allowed range of values are -95 to 95 + width (float): desired width(delay gain) in dB + Allowed range of values are 0 to 100 + speed (float): modulation speed in Hz + Allowed range of values are 0.1 to 10 + phase (float): percentage phase-shift for multi-channel + Allowed range of values are 0 to 100 + modulation (str): Use either "sinusoidal" or "triangular" modulation. (Default: ``sinusoidal``) + interpolation (str): Use either "linear" or "quadratic" for delay-line interpolation. (Default: ``linear``) + + Returns: + Tensor: Waveform of dimension of `(..., channel, time)` + + References: + http://sox.sourceforge.net/sox.html + + Scott Lehman, Effects Explained, + https://web.archive.org/web/20051125072557/http://www.harmony-central.com/Effects/effects-explained.html + """ + + if modulation not in ('sinusoidal', 'triangular'): + raise ValueError("Only 'sinusoidal' or 'triangular' modulation allowed") + + if interpolation not in ('linear', 'quadratic'): + raise ValueError("Only 'linear' or 'quadratic' interpolation allowed") + + actual_shape = waveform.shape + device, dtype = waveform.device, waveform.dtype + + if actual_shape[-2] > 4: + raise ValueError("Max 4 channels allowed") + + # convert to 3D (batch, channels, time) + waveform = waveform.view(-1, actual_shape[-2], actual_shape[-1]) + + # Scaling + feedback_gain = regen / 100 + delay_gain = width / 100 + channel_phase = phase / 100 + delay_min = delay / 1000 + delay_depth = depth / 1000 + + n_channels = waveform.shape[-2] + + if modulation == 'sinusoidal': + wave_type = 'SINE' + else: + wave_type = 'TRIANGLE' + + # Balance output: + in_gain = 1. / (1 + delay_gain) + delay_gain = delay_gain / (1 + delay_gain) + + # Balance feedback loop: + delay_gain = delay_gain * (1 - abs(feedback_gain)) + + delay_buf_length = int((delay_min + delay_depth) * sample_rate + 0.5) + delay_buf_length = delay_buf_length + 2 + + delay_bufs = torch.zeros(waveform.shape[0], n_channels, delay_buf_length, dtype=dtype, device=device) + delay_last = torch.zeros(waveform.shape[0], n_channels, dtype=dtype, device=device) + + lfo_length = int(sample_rate / speed) + + lfo = torch.zeros(lfo_length, dtype=dtype, device=device) + + table_min = math.floor(delay_min * sample_rate + 0.5) + table_max = delay_buf_length - 2. + + lfo = _generate_wave_table(wave_type=wave_type, + data_type='FLOAT', + table_size=lfo_length, + min=float(table_min), + max=float(table_max), + phase=3 * math.pi / 2) + + output_waveform = torch.zeros_like(waveform, dtype=dtype, device=device) + + delay_buf_pos = 0 + lfo_pos = 0 + channel_idxs = torch.arange(0, n_channels) + + for i in range(waveform.shape[-1]): + + delay_buf_pos = (delay_buf_pos + delay_buf_length - 1) % delay_buf_length + + cur_channel_phase = (channel_idxs * lfo_length * channel_phase + .5).to(torch.int64) + delay_tensor = lfo[(lfo_pos + cur_channel_phase) % lfo_length] + frac_delay = torch.frac(delay_tensor) + delay_tensor = torch.floor(delay_tensor) + + int_delay = delay_tensor.to(torch.int64) + + temp = waveform[:, :, i] + + delay_bufs[:, :, delay_buf_pos] = temp + delay_last * feedback_gain + + delayed_0 = delay_bufs[:, channel_idxs, (delay_buf_pos + int_delay) % delay_buf_length] + + int_delay = int_delay + 1 + + delayed_1 = delay_bufs[:, channel_idxs, (delay_buf_pos + int_delay) % delay_buf_length] + + int_delay = int_delay + 1 + + if interpolation == 'linear': + delayed = delayed_0 + (delayed_1 - delayed_0) * frac_delay + else: + delayed_2 = delay_bufs[:, channel_idxs, (delay_buf_pos + int_delay) % delay_buf_length] + + int_delay = int_delay + 1 + + delayed_2 = delayed_2 - delayed_0 + delayed_1 = delayed_1 - delayed_0 + a = delayed_2 * .5 - delayed_1 + b = delayed_1 * 2 - delayed_2 * .5 + + delayed = delayed_0 + (a * frac_delay + b) * frac_delay + + delay_last = delayed + output_waveform[:, :, i] = waveform[:, :, i] * in_gain + delayed * delay_gain + + lfo_pos = (lfo_pos + 1) % lfo_length + + return output_waveform.clamp(min=-1, max=1).view(actual_shape) + + def mask_along_axis_iid( specgrams: Tensor, mask_param: int, From 0af364402e4764a60e8da0874d3434925d5f1ca7 Mon Sep 17 00:00:00 2001 From: Ben Mehne Date: Wed, 10 Jun 2020 10:46:43 -0700 Subject: [PATCH 08/73] Change parameterized testing system to be compatible with unittest Summary: The previous implementation of parameterized testing worked by modifying test.common_utils inplace. This doesn't work in general because unittest's contract with test modules is such that it must be able to load the module and run the test itself. Because the previous implementation needed to load the module and modify it, it is incompatible. Reviewed By: mthrok Differential Revision: D21964676 fbshipit-source-id: 9bb71e8c3f9fab074239b22306f3bbddb0f3975b --- test/common_utils.py | 9 +++++++++ test/torchscript_consistency_cpu_test.py | 13 +++++++++++-- 2 files changed, 20 insertions(+), 2 deletions(-) diff --git a/test/common_utils.py b/test/common_utils.py index 5d1dc8abe1..00d10a6df1 100644 --- a/test/common_utils.py +++ b/test/common_utils.py @@ -119,6 +119,15 @@ def define_test_suites( scope[t.__name__] = t +def common_test_class_parameters( + dtypes: Iterable[str] = ("float32", "float64"), + devices: Iterable[str] = ("cpu", "cuda"), +): + for device in devices: + for dtype in dtypes: + yield {"device": torch.device(device), "dtype": getattr(torch, dtype)} + + def get_whitenoise( *, sample_rate: int = 16000, diff --git a/test/torchscript_consistency_cpu_test.py b/test/torchscript_consistency_cpu_test.py index 51a3a477f0..81e6616821 100644 --- a/test/torchscript_consistency_cpu_test.py +++ b/test/torchscript_consistency_cpu_test.py @@ -1,5 +1,14 @@ -from .common_utils import define_test_suites +from parameterized import parameterized_class + +from .common_utils import TestCase, common_test_class_parameters from .torchscript_consistency_impl import Functional, Transforms +parameters = list(common_test_class_parameters(devices=['cpu'])) +@parameterized_class(parameters) +class TestFunctional(Functional, TestCase): + pass + -define_test_suites(globals(), [Functional, Transforms], devices=['cpu']) +@parameterized_class(parameters) +class TestTransforms(Transforms, TestCase): + pass From 9a2d018f8356ea93542990079755ad64d2bde15c Mon Sep 17 00:00:00 2001 From: Moto Hira Date: Mon, 22 Jun 2020 16:41:11 -0700 Subject: [PATCH 09/73] Import torchaudio 20200618 #718 Summary: Import torchaudio up to #719 Reviewed By: zhangguanheng66 Differential Revision: D22119491 fbshipit-source-id: e14842278a32c9373179fc132e8111a0ffe66d93 --- docs/source/datasets.rst | 8 + test/README.md | 10 + .../cmu_us_aew_arctic/etc/txt.done.data | 1 + .../cmu_us_aew_arctic/wav/arctic_a0024.wav | Bin 0 -> 441078 bytes ...ue-true-false-1832-1824-1.0000-hanning.ark | Bin 45 -> 0 bytes ...true-false-true-4587-2289-1.0000-povey.ark | Bin 105 -> 0 bytes ...alse-false-1700-870-0.3104-rectangular.ark | Bin 45 -> 0 bytes ...ue-false-true-7138-5172-1.0000-hamming.ark | Bin 45 -> 0 bytes ...false-true-true-4782-4492-1.0000-povey.ark | Bin 45 -> 0 bytes ...lse-true-true-5274-3268-1.0000-hamming.ark | Bin 69 -> 0 bytes ...alse-true-6881-4659-1.0000-rectangular.ark | Bin 45 -> 0 bytes ...se-false-true-6506-2549-1.0000-hamming.ark | Bin 37 -> 0 bytes ...lse-true-true-3979-1023-1.0000-hanning.ark | Bin 81 -> 0 bytes ...-false-false-3373-3354-1.0000-blackman.ark | Bin 45 -> 0 bytes ...e-true-false-5918-4804-1.0000-blackman.ark | Bin 501 -> 0 bytes ...true-false-true-5417-1170-1.0000-povey.ark | Bin 41 -> 0 bytes ...se-false-true-6491-6262-1.0000-hamming.ark | Bin 49 -> 0 bytes ...ue-false-true-2494-2015-1.0000-hamming.ark | Bin 41 -> 0 bytes ...rue-true-true-4652-2559-1.0000-hanning.ark | Bin 301 -> 0 bytes ...-false-false-4613-4001-1.4073-blackman.ark | Bin 117 -> 0 bytes ...true-true-false-1175-1038-1.0000-povey.ark | Bin 41 -> 0 bytes ...lse-true-true-6483-5671-1.0000-hamming.ark | Bin 69 -> 0 bytes ...lse-true-true-3917-1620-1.0000-hanning.ark | Bin 45 -> 0 bytes ...alse-true-6874-5861-1.1718-rectangular.ark | Bin 45 -> 0 bytes ...e-false-false-5868-5848-1.0000-hamming.ark | Bin 45 -> 0 bytes ...true-true-6204-5887-1.0000-rectangular.ark | Bin 45 -> 0 bytes ...e-true-false-2114-2024-1.0000-blackman.ark | Bin 161 -> 0 bytes ...e-false-false-1118-947-1.0000-blackman.ark | Bin 93 -> 0 bytes ...e-false-false-1226-960-1.0000-blackman.ark | Bin 37 -> 0 bytes ...e-false-true-1731-1582-1.0000-blackman.ark | Bin 121 -> 0 bytes ...e-true-false-4191-3264-1.0000-blackman.ark | Bin 53 -> 0 bytes ...alse-false-true-3183-2975-1.0000-povey.ark | Bin 53 -> 0 bytes ...se-false-true-4062-3715-1.0000-hanning.ark | Bin 53 -> 0 bytes ...alse-true-false-4426-2811-1.0000-povey.ark | Bin 45 -> 0 bytes ...e-false-false-6065-4599-1.0000-hamming.ark | Bin 37 -> 0 bytes ...lse-true-true-4787-3163-1.0000-hanning.ark | Bin 45 -> 0 bytes ...se-false-true-4228-2903-1.0000-hanning.ark | Bin 41 -> 0 bytes ...lse-false-false-6163-5973-1.0000-povey.ark | Bin 49 -> 0 bytes ...rue-false-6523-5708-1.0000-rectangular.ark | Bin 45 -> 0 bytes ...lse-false-false-5479-4173-1.0000-povey.ark | Bin 141 -> 0 bytes ...-false-false-7300-5299-1.0000-blackman.ark | Bin 41 -> 0 bytes ...e-true-false-4540-3168-1.0000-blackman.ark | Bin 161 -> 0 bytes ...rue-false-4930-4316-1.0000-rectangular.ark | Bin 61 -> 0 bytes ...false-true-2759-306-1.0000-rectangular.ark | Bin 49 -> 0 bytes ...lse-false-3816-1550-1.0000-rectangular.ark | Bin 61 -> 0 bytes ...rue-false-false-4168-1531-1.0000-povey.ark | Bin 45 -> 0 bytes ...e-false-false-4365-3721-1.0000-hanning.ark | Bin 61 -> 0 bytes ...rue-true-true-3970-3355-1.0000-hamming.ark | Bin 49 -> 0 bytes ...e-false-true-7749-7478-1.0000-blackman.ark | Bin 57 -> 0 bytes ...-true-true-true-5348-4645-1.0000-povey.ark | Bin 45 -> 0 bytes ...ue-false-true-3122-2865-1.0000-hanning.ark | Bin 105 -> 0 bytes ...e-false-false-5297-2747-1.0000-hamming.ark | Bin 41 -> 0 bytes ...alse-true-4178-2891-1.0000-rectangular.ark | Bin 41 -> 0 bytes ...se-false-true-6819-3764-1.0000-hanning.ark | Bin 53 -> 0 bytes ...lse-true-true-5081-4539-1.0000-hamming.ark | Bin 133 -> 0 bytes ...lse-false-5452-5271-1.0000-rectangular.ark | Bin 37 -> 0 bytes ...-true-true-true-6790-6501-1.0000-povey.ark | Bin 53 -> 0 bytes ...true-false-true-6635-6360-0.7856-povey.ark | Bin 117 -> 0 bytes ...lse-true-true-4565-3464-1.0000-hamming.ark | Bin 61 -> 0 bytes ...se-false-true-7263-6361-1.0000-hamming.ark | Bin 53 -> 0 bytes ...false-true-true-4974-3139-1.0000-povey.ark | Bin 49 -> 0 bytes ...true-true-false-2920-1121-1.0000-povey.ark | Bin 45 -> 0 bytes ...ue-false-true-1293-771-1.0000-blackman.ark | Bin 45 -> 0 bytes ...rue-false-false-3704-1013-1.0000-povey.ark | Bin 53 -> 0 bytes ...alse-true-6542-5821-1.0000-rectangular.ark | Bin 37 -> 0 bytes ...e-false-false-3368-3286-1.0000-hamming.ark | Bin 45 -> 0 bytes ...e-false-false-7470-6783-1.0000-hamming.ark | Bin 45 -> 0 bytes ...e-false-false-5573-4642-1.0000-hanning.ark | Bin 49 -> 0 bytes ...ue-true-false-4997-4836-1.9525-hamming.ark | Bin 41 -> 0 bytes ...true-true-false-3273-3199-1.0000-povey.ark | Bin 217 -> 0 bytes ...true-true-5077-4977-0.8739-rectangular.ark | Bin 117 -> 0 bytes ...lse-true-false-2831-696-1.0000-hanning.ark | Bin 41 -> 0 bytes ...e-true-false-5827-5388-1.0000-blackman.ark | Bin 85 -> 0 bytes ...ue-true-false-7667-2993-1.0000-hamming.ark | Bin 45 -> 0 bytes ...lse-false-false-7088-6494-1.0000-povey.ark | Bin 41 -> 0 bytes ...-true-true-true-6878-6036-1.0000-povey.ark | Bin 45 -> 0 bytes ...ue-false-true-4084-3955-1.0000-hamming.ark | Bin 77 -> 0 bytes ...alse-true-4726-2918-1.0000-rectangular.ark | Bin 77 -> 0 bytes ...lse-false-3158-2865-1.0000-rectangular.ark | Bin 37 -> 0 bytes ...se-false-true-3640-2770-1.0000-hanning.ark | Bin 133 -> 0 bytes ...ue-true-false-2408-1892-1.0000-hanning.ark | Bin 105 -> 0 bytes ...true-false-1490-645-1.0000-rectangular.ark | Bin 341 -> 0 bytes ...-true-true-true-6446-6419-1.0000-povey.ark | Bin 261 -> 0 bytes ...true-true-5637-3692-1.0000-rectangular.ark | Bin 581 -> 0 bytes ...lse-false-5458-5400-1.0000-rectangular.ark | Bin 53 -> 0 bytes ...true-true-false-5769-5699-1.0000-povey.ark | Bin 81 -> 0 bytes ...ue-false-true-3686-2010-1.0000-hamming.ark | Bin 41 -> 0 bytes ...e-true-false-5178-4628-1.0000-blackman.ark | Bin 41 -> 0 bytes ...e-false-true-2884-1773-1.0000-blackman.ark | Bin 41 -> 0 bytes ...true-true-5820-4635-1.0000-rectangular.ark | Bin 93 -> 0 bytes ...se-true-false-7486-4238-1.0000-hamming.ark | Bin 41 -> 0 bytes ...ue-true-false-7421-3707-1.0000-hanning.ark | Bin 49 -> 0 bytes ...-false-false-6900-2344-1.0000-blackman.ark | Bin 61 -> 0 bytes ...alse-true-5001-4046-1.0000-rectangular.ark | Bin 41 -> 0 bytes ...ue-true-false-2112-1445-1.0000-hamming.ark | Bin 309 -> 0 bytes ...e-false-false-3717-304-1.0000-blackman.ark | Bin 45 -> 0 bytes ...rue-false-2231-1432-1.0000-rectangular.ark | Bin 117 -> 0 bytes ...lse-false-false-4253-2427-0.7049-povey.ark | Bin 37 -> 0 bytes ...e-false-false-3287-1478-0.9406-hanning.ark | Bin 41 -> 0 bytes ...rue-false-2588-2346-1.0000-rectangular.ark | Bin 53 -> 0 bytes ...e-false-false-3706-2840-1.0000-hamming.ark | Bin 41 -> 0 bytes ...ue-2-73.5792-5749-4449-1.0000-blackman.ark | Bin 109 -> 0 bytes ...rue-3-8.1048-7497-7397-1.0000-blackman.ark | Bin 45 -> 0 bytes ...5-34.0918-4400-2737-1.0000-rectangular.ark | Bin 61 -> 0 bytes ...true-5-21.3007-1352-280-1.0000-hanning.ark | Bin 41 -> 0 bytes ...e-true-6-2.6493-3145-3119-1.0000-povey.ark | Bin 45 -> 0 bytes ...rue-4-24.5097-5231-3888-1.0000-hamming.ark | Bin 53 -> 0 bytes ...2-88.0941-7042-5298-1.0000-rectangular.ark | Bin 29 -> 0 bytes ...-true-4-73.5838-5816-3997-1.0000-povey.ark | Bin 37 -> 0 bytes ...lse-3-19.4145-7169-6751-1.0000-hanning.ark | Bin 33 -> 0 bytes ...ue-3-34.4790-3390-1536-1.0000-blackman.ark | Bin 33 -> 0 bytes ...true-3-48.7991-4833-513-1.0000-hanning.ark | Bin 33 -> 0 bytes ...se-3-48.6724-3138-2247-1.0000-blackman.ark | Bin 33 -> 0 bytes ...ue-5-69.3653-7087-2800-1.0000-blackman.ark | Bin 41 -> 0 bytes ...ue-2-77.7066-5622-5544-1.0000-blackman.ark | Bin 37 -> 0 bytes ...4-57.0398-4519-3600-1.0000-rectangular.ark | Bin 37 -> 0 bytes ...3-96.3721-4277-2466-1.0000-rectangular.ark | Bin 141 -> 0 bytes ...false-2-99.8710-4957-3549-1.0000-povey.ark | Bin 37 -> 0 bytes ...se-3-74.4735-5601-4966-1.0000-blackman.ark | Bin 33 -> 0 bytes ...lse-3-57.1750-3578-2101-1.0000-hanning.ark | Bin 141 -> 0 bytes ...rue-4-85.3570-3181-3129-1.0000-hamming.ark | Bin 37 -> 0 bytes ...2-16.2782-5573-4988-1.0000-rectangular.ark | Bin 29 -> 0 bytes ...lse-5-59.0075-3870-3750-1.0000-hanning.ark | Bin 41 -> 0 bytes ...lse-6-55.7891-4641-2879-1.0000-hanning.ark | Bin 261 -> 0 bytes ...ue-2-49.7663-5461-4039-1.0000-blackman.ark | Bin 29 -> 0 bytes ...3-18.0061-5902-3191-1.0000-rectangular.ark | Bin 33 -> 0 bytes ...ue-2-58.5051-4692-2757-1.0000-blackman.ark | Bin 101 -> 0 bytes ...lse-2-71.5910-3497-3331-1.0000-hanning.ark | Bin 61 -> 0 bytes ...3-29.2858-5349-3987-1.0000-rectangular.ark | Bin 33 -> 0 bytes ...-true-2-52.5962-4597-4417-1.0000-povey.ark | Bin 29 -> 0 bytes ...ue-8-42.3128-2299-1094-1.0000-blackman.ark | Bin 53 -> 0 bytes ...rue-4-74.1116-4129-2898-1.0000-hamming.ark | Bin 37 -> 0 bytes ...2-76.0384-2672-1762-1.0000-rectangular.ark | Bin 29 -> 0 bytes ...lse-6-49.2912-5518-5442-1.0000-hamming.ark | Bin 45 -> 0 bytes ...ue-3-62.9038-7460-7174-1.0000-blackman.ark | Bin 81 -> 0 bytes ...-true-4-4.1559-1976-972-1.0000-hanning.ark | Bin 37 -> 0 bytes ...-true-4-67.4571-5460-3654-1.0000-povey.ark | Bin 37 -> 0 bytes ...rue-3-73.6328-3496-2890-1.0000-hamming.ark | Bin 261 -> 0 bytes ...ue-3-33.0194-5438-3920-1.0000-blackman.ark | Bin 45 -> 0 bytes ...lse-7-81.2017-5809-5654-1.0000-hamming.ark | Bin 77 -> 0 bytes ...rue-4-88.3186-4677-2590-1.0000-hamming.ark | Bin 53 -> 0 bytes ...ue-3-57.6793-3441-3396-1.0000-blackman.ark | Bin 45 -> 0 bytes ...2-45.2819-2547-1123-1.0000-rectangular.ark | Bin 29 -> 0 bytes ...lse-3-75.0589-5873-5807-1.0000-hamming.ark | Bin 45 -> 0 bytes ...rue-2-78.5880-3299-2540-1.0000-hanning.ark | Bin 37 -> 0 bytes ...3-76.8484-7453-7251-1.0000-rectangular.ark | Bin 33 -> 0 bytes ...-true-3-44.8604-5099-4429-1.0000-povey.ark | Bin 57 -> 0 bytes ...rue-4-38.6407-3043-2934-1.0000-hamming.ark | Bin 37 -> 0 bytes ...2-17.5040-4228-1009-1.0000-rectangular.ark | Bin 77 -> 0 bytes ...rue-4-98.3869-7445-7362-1.0000-hamming.ark | Bin 53 -> 0 bytes ...false-2-11.9820-4607-4483-1.0000-povey.ark | Bin 29 -> 0 bytes ...rue-2-75.6661-2592-1621-1.0000-hamming.ark | Bin 37 -> 0 bytes ...4-80.1563-7152-6151-1.0000-rectangular.ark | Bin 37 -> 0 bytes ...-true-2-80.8779-5720-4080-1.0000-povey.ark | Bin 45 -> 0 bytes ...rue-2-42.9569-3483-3287-1.0000-hanning.ark | Bin 29 -> 0 bytes ...4-31.0832-5457-4742-1.0000-rectangular.ark | Bin 101 -> 0 bytes ...2-30.0984-5450-4909-1.0000-rectangular.ark | Bin 181 -> 0 bytes ...false-3-92.6839-5085-4771-1.0000-povey.ark | Bin 33 -> 0 bytes ...lse-2-95.7035-7521-7417-1.0000-hamming.ark | Bin 29 -> 0 bytes ...lse-2-17.8265-6387-6105-1.0000-hanning.ark | Bin 37 -> 0 bytes ...-true-4-93.4050-1751-1690-1.0000-povey.ark | Bin 53 -> 0 bytes ...3-42.9768-6315-3995-1.1059-rectangular.ark | Bin 33 -> 0 bytes ...false-5-33.6608-6998-6740-1.0000-povey.ark | Bin 221 -> 0 bytes ...3-51.0514-5221-5071-1.0000-rectangular.ark | Bin 33 -> 0 bytes ...3-70.1988-4041-2424-1.0000-rectangular.ark | Bin 33 -> 0 bytes ...rue-2-37.5837-3995-2991-1.0000-hanning.ark | Bin 77 -> 0 bytes ...lse-4-59.0671-7431-7014-1.0000-hamming.ark | Bin 53 -> 0 bytes ...lse-6-4.5734-3935-3932-1.0000-blackman.ark | Bin 69 -> 0 bytes ...lse-6-35.3731-4786-4226-1.0000-hamming.ark | Bin 141 -> 0 bytes ...2-60.4649-7218-5709-1.0000-rectangular.ark | Bin 29 -> 0 bytes ...3-71.5160-6157-4430-1.0000-rectangular.ark | Bin 45 -> 0 bytes ...ue-4-68.9678-3555-1851-1.0000-blackman.ark | Bin 53 -> 0 bytes ...false-6-91.3952-6769-5907-1.0000-povey.ark | Bin 261 -> 0 bytes ...rue-3-31.0805-2257-1533-1.0000-hamming.ark | Bin 81 -> 0 bytes ...rue-3-96.1612-4840-1905-1.0000-hamming.ark | Bin 33 -> 0 bytes ...lse-3-73.9427-2044-1481-1.0000-hanning.ark | Bin 57 -> 0 bytes ...alse-7-4.6719-5337-5243-1.0000-hanning.ark | Bin 49 -> 0 bytes ...rue-4-83.2329-5090-1185-1.0000-hanning.ark | Bin 69 -> 0 bytes ...alse-2-5.8944-4338-4330-1.0000-hanning.ark | Bin 45 -> 0 bytes ...-2-0.0578-5707-5025-1.0000-rectangular.ark | Bin 45 -> 0 bytes ...-true-7-31.0763-7031-6291-1.0000-povey.ark | Bin 77 -> 0 bytes ...rue-3-50.9241-2593-2198-1.0000-hanning.ark | Bin 69 -> 0 bytes ...false-5-31.3652-1203-1174-1.0000-povey.ark | Bin 41 -> 0 bytes ...2-92.7940-3276-1685-1.0000-rectangular.ark | Bin 37 -> 0 bytes ...5-82.2365-5365-4579-1.0000-rectangular.ark | Bin 41 -> 0 bytes ...rue-2-59.9812-5397-2639-1.0000-hamming.ark | Bin 29 -> 0 bytes ...lse-4-94.5907-6682-4979-1.0000-hamming.ark | Bin 53 -> 0 bytes ...alse-6-7.8133-3755-1137-1.0000-hanning.ark | Bin 501 -> 0 bytes ...false-2-80.8871-6691-6581-1.0000-povey.ark | Bin 77 -> 0 bytes ...-true-4-63.3036-6650-5500-1.0000-povey.ark | Bin 101 -> 0 bytes ...rue-3-95.8111-1266-521-1.0000-blackman.ark | Bin 33 -> 0 bytes ...-true-4-64.7537-6220-5229-1.0000-povey.ark | Bin 37 -> 0 bytes ...rue-4-26.1743-6381-5017-1.0000-hamming.ark | Bin 37 -> 0 bytes ...lse-5-82.2405-5130-5086-1.0000-hanning.ark | Bin 41 -> 0 bytes ...ue-4-28.5808-7478-7326-1.0000-blackman.ark | Bin 53 -> 0 bytes ...-false-4-3.5732-4583-3742-1.0000-povey.ark | Bin 133 -> 0 bytes ...ue-3-60.5751-3542-1943-1.0000-blackman.ark | Bin 57 -> 0 bytes ...4-90.4067-3617-3615-1.0000-rectangular.ark | Bin 37 -> 0 bytes ...ue-3-28.5360-4401-3315-1.0000-blackman.ark | Bin 45 -> 0 bytes ...3-97.4694-6022-5650-1.0000-rectangular.ark | Bin 33 -> 0 bytes ...lse-2-47.6031-5741-5524-1.0000-hanning.ark | Bin 29 -> 0 bytes ...se-2-65.1166-6852-5820-1.0000-blackman.ark | Bin 45 -> 0 bytes ...-false-7-7.0295-4988-4931-1.0000-povey.ark | Bin 161 -> 0 bytes ...2-76.6062-3005-1680-1.0000-rectangular.ark | Bin 77 -> 0 bytes ...se-5-92.8036-4870-1901-1.0000-blackman.ark | Bin 81 -> 0 bytes ...rue-2-28.8828-4490-2980-1.0000-hamming.ark | Bin 45 -> 0 bytes ...true-3-2.5456-6925-5486-1.0000-hamming.ark | Bin 45 -> 0 bytes ...lse-3-30.6069-5090-3467-1.0000-hamming.ark | Bin 69 -> 0 bytes ...alse-2-2.9422-1634-1000-1.0000-hanning.ark | Bin 53 -> 0 bytes ...lse-2-48.8818-7889-7527-1.0000-hanning.ark | Bin 29 -> 0 bytes ...false-4-39.4555-4290-2715-1.0000-povey.ark | Bin 133 -> 0 bytes ...lse-2-36.7118-1463-1358-1.0000-hanning.ark | Bin 29 -> 0 bytes ...3-74.0966-4277-3777-1.0000-rectangular.ark | Bin 33 -> 0 bytes ...lse-7-1.1255-4890-3923-1.0000-blackman.ark | Bin 301 -> 0 bytes ...rue-4-19.2839-6596-6594-1.0000-hanning.ark | Bin 181 -> 0 bytes ...rue-5-5.5865-5459-5056-1.0000-blackman.ark | Bin 61 -> 0 bytes ...lse-2-32.2463-4992-4951-1.0000-hamming.ark | Bin 37 -> 0 bytes ...-true-3-91.4723-3532-3056-1.0000-povey.ark | Bin 33 -> 0 bytes ...ue-3-29.1497-2440-1852-1.0000-blackman.ark | Bin 33 -> 0 bytes ...lse-3-17.4711-5295-4742-0.6284-hanning.ark | Bin 45 -> 0 bytes ...false-4-65.8362-4734-3050-1.0000-povey.ark | Bin 53 -> 0 bytes ...rue-3-85.2464-3982-3760-1.0000-hamming.ark | Bin 45 -> 0 bytes ...-true-3-84.6108-655-525-1.0000-hamming.ark | Bin 69 -> 0 bytes ...false-6-88.1580-5517-3249-1.0000-povey.ark | Bin 141 -> 0 bytes ...-false-2-36.9610-1982-741-1.0000-povey.ark | Bin 29 -> 0 bytes ...se-2-44.7800-6612-4074-1.0000-blackman.ark | Bin 29 -> 0 bytes ...se-4-70.9332-4857-2223-1.0000-blackman.ark | Bin 37 -> 0 bytes ...7-86.3861-7554-7506-1.0000-rectangular.ark | Bin 49 -> 0 bytes ...2-39.2887-4353-3521-1.0000-rectangular.ark | Bin 69 -> 0 bytes ...se-5-36.9181-7261-5703-1.0000-blackman.ark | Bin 41 -> 0 bytes ...lse-4-34.2098-4554-1148-1.0000-hamming.ark | Bin 37 -> 0 bytes ...false-2-71.8337-7672-5265-1.0000-povey.ark | Bin 45 -> 0 bytes ...rue-4-70.0635-7277-7265-1.0000-hamming.ark | Bin 37 -> 0 bytes ...lse-5-76.9780-7368-7310-1.0000-hanning.ark | Bin 81 -> 0 bytes ...e-6-1.6240-2148-461-1.0000-rectangular.ark | Bin 69 -> 0 bytes ...lse-4-49.7637-2897-2701-1.0000-hanning.ark | Bin 37 -> 0 bytes ...3-70.5509-5962-4190-1.0000-rectangular.ark | Bin 33 -> 0 bytes ...5-54.2056-5259-2363-1.0000-rectangular.ark | Bin 41 -> 0 bytes ...lse-4-75.6122-3701-2992-1.0000-hamming.ark | Bin 37 -> 0 bytes ...lse-3-96.1160-5148-2541-1.0000-hamming.ark | Bin 33 -> 0 bytes ...alse-5-6.6500-7634-6587-1.0000-hanning.ark | Bin 421 -> 0 bytes ...lse-3-32.0303-5598-2579-1.0000-hanning.ark | Bin 57 -> 0 bytes ...false-4-27.7648-7735-7419-1.0000-povey.ark | Bin 69 -> 0 bytes ...lse-6-56.4490-4397-4332-1.0000-hamming.ark | Bin 45 -> 0 bytes ...rue-8-23.3238-2732-2677-1.0000-hanning.ark | Bin 53 -> 0 bytes ...rue-2-59.4319-1202-1063-1.0000-hamming.ark | Bin 45 -> 0 bytes ...82-false-false-false-false-false-povey.ark | Bin 141 -> 0 bytes ...lse-false-false-true-false-rectangular.ark | Bin 117 -> 0 bytes ...76-false-true-true-true-false-blackman.ark | Bin 61 -> 0 bytes ...0.81-false-true-true-true-true-hanning.ark | Bin 57 -> 0 bytes ...9-false-false-true-true-false-blackman.ark | Bin 93 -> 0 bytes ...-0.51-true-true-false-true-false-povey.ark | Bin 61 -> 0 bytes ...6-true-false-false-true-false-blackman.ark | Bin 57 -> 0 bytes ...-0.96-true-false-true-false-true-povey.ark | Bin 81 -> 0 bytes ...0.98-true-false-false-false-true-povey.ark | Bin 101 -> 0 bytes ...8-false-true-false-true-false-blackman.ark | Bin 45 -> 0 bytes ....52-true-false-false-true-true-hamming.ark | Bin 149 -> 0 bytes ...38-false-false-true-false-true-hamming.ark | Bin 45 -> 0 bytes ...0.95-true-true-true-true-false-hamming.ark | Bin 453 -> 0 bytes ...-0.27-false-true-false-true-true-povey.ark | Bin 61 -> 0 bytes ...-0.15-true-false-true-false-true-povey.ark | Bin 129 -> 0 bytes ...alse-false-true-false-true-rectangular.ark | Bin 41 -> 0 bytes ...3-true-true-true-true-true-rectangular.ark | Bin 57 -> 0 bytes ...-false-false-false-true-false-blackman.ark | Bin 61 -> 0 bytes ...0.69-true-false-false-false-true-povey.ark | Bin 93 -> 0 bytes ...74-false-false-false-true-true-hamming.ark | Bin 41 -> 0 bytes ...48-false-false-true-true-false-hanning.ark | Bin 101 -> 0 bytes ...0.10-true-false-true-false-false-povey.ark | Bin 93 -> 0 bytes ...7-true-false-false-true-false-blackman.ark | Bin 53 -> 0 bytes ...06-false-true-true-true-false-blackman.ark | Bin 57 -> 0 bytes ...alse-false-true-false-true-rectangular.ark | Bin 61 -> 0 bytes ...0.54-true-false-false-false-true-povey.ark | Bin 33 -> 0 bytes ...23-false-false-true-false-true-hamming.ark | Bin 157 -> 0 bytes ...9-false-true-false-true-false-blackman.ark | Bin 53 -> 0 bytes ...-0.39-true-true-true-true-true-hanning.ark | Bin 89 -> 0 bytes ...-0.53-true-true-true-true-true-hanning.ark | Bin 69 -> 0 bytes ...0.54-true-false-false-false-true-povey.ark | Bin 341 -> 0 bytes ...02-false-false-true-true-false-hamming.ark | Bin 45 -> 0 bytes ...3-true-false-false-false-false-hanning.ark | Bin 117 -> 0 bytes ...50-1.00-true-true-true-true-true-povey.ark | Bin 237 -> 0 bytes ...4-true-true-false-false-false-blackman.ark | Bin 245 -> 0 bytes ...8-false-false-false-false-true-hamming.ark | Bin 61 -> 0 bytes ...7-false-false-true-false-true-blackman.ark | Bin 33 -> 0 bytes ...-false-false-false-true-false-blackman.ark | Bin 53 -> 0 bytes ...66-false-false-true-true-true-blackman.ark | Bin 273 -> 0 bytes ...4-false-false-true-false-false-hanning.ark | Bin 221 -> 0 bytes ....69-false-false-true-false-false-povey.ark | Bin 129 -> 0 bytes ....95-true-true-true-true-false-blackman.ark | Bin 57 -> 0 bytes ...9-true-false-true-false-false-blackman.ark | Bin 361 -> 0 bytes ...alse-true-false-false-true-rectangular.ark | Bin 105 -> 0 bytes ...56-true-true-false-false-true-blackman.ark | Bin 181 -> 0 bytes ...false-false-true-true-true-rectangular.ark | Bin 57 -> 0 bytes ...0.14-true-true-true-true-false-hanning.ark | Bin 57 -> 0 bytes ...rue-false-true-false-false-rectangular.ark | Bin 57 -> 0 bytes ...-true-true-true-true-false-rectangular.ark | Bin 89 -> 0 bytes ...33-true-true-false-false-false-hamming.ark | Bin 221 -> 0 bytes ...4-false-true-false-true-false-blackman.ark | Bin 45 -> 0 bytes ...96-false-true-true-false-false-hanning.ark | Bin 121 -> 0 bytes ...false-true-true-false-true-rectangular.ark | Bin 273 -> 0 bytes ....40-false-false-true-true-true-hanning.ark | Bin 57 -> 0 bytes ...3-true-true-true-true-true-rectangular.ark | Bin 61 -> 0 bytes ...-0.35-true-true-true-true-true-hanning.ark | Bin 89 -> 0 bytes ...47-true-false-true-false-true-blackman.ark | Bin 129 -> 0 bytes ...61-false-false-true-false-true-hanning.ark | Bin 121 -> 0 bytes ...-true-false-true-true-true-rectangular.ark | Bin 57 -> 0 bytes ...8-true-false-true-false-false-blackman.ark | Bin 93 -> 0 bytes ...0.61-true-true-false-false-false-povey.ark | Bin 33 -> 0 bytes ...0.58-true-true-false-true-true-hamming.ark | Bin 61 -> 0 bytes ....45-false-true-false-false-false-povey.ark | Bin 85 -> 0 bytes ...98-true-false-false-false-true-hamming.ark | Bin 77 -> 0 bytes ...80-true-false-true-false-false-hanning.ark | Bin 57 -> 0 bytes ...-true-false-true-true-true-rectangular.ark | Bin 57 -> 0 bytes ...0.54-true-false-true-true-true-hamming.ark | Bin 57 -> 0 bytes ...0-0.34-true-true-true-false-true-povey.ark | Bin 33 -> 0 bytes ....77-true-true-true-false-false-hanning.ark | Bin 165 -> 0 bytes ...true-false-true-true-false-rectangular.ark | Bin 57 -> 0 bytes ...lse-true-false-false-false-rectangular.ark | Bin 57 -> 0 bytes ...false-true-true-false-true-rectangular.ark | Bin 57 -> 0 bytes ...5-false-true-false-false-false-hanning.ark | Bin 53 -> 0 bytes ...lse-false-false-false-true-rectangular.ark | Bin 77 -> 0 bytes ...0.63-true-true-true-true-false-hanning.ark | Bin 89 -> 0 bytes ...false-true-true-true-false-rectangular.ark | Bin 57 -> 0 bytes ....14-true-true-false-false-true-hamming.ark | Bin 101 -> 0 bytes ...lse-false-true-false-false-rectangular.ark | Bin 93 -> 0 bytes ...74-false-true-false-true-true-blackman.ark | Bin 45 -> 0 bytes ...00-false-true-true-false-false-hamming.ark | Bin 41 -> 0 bytes ...5-true-true-true-true-true-rectangular.ark | Bin 57 -> 0 bytes ....25-false-true-true-true-false-hanning.ark | Bin 61 -> 0 bytes ...9-false-true-true-false-false-blackman.ark | Bin 157 -> 0 bytes ...-true-false-true-true-true-rectangular.ark | Bin 61 -> 0 bytes ...0.96-false-true-false-true-false-povey.ark | Bin 49 -> 0 bytes ...5-0.20-true-true-true-true-false-povey.ark | Bin 81 -> 0 bytes ....55-false-false-true-true-true-hanning.ark | Bin 81 -> 0 bytes ...false-false-true-true-true-rectangular.ark | Bin 101 -> 0 bytes ...lse-true-false-false-false-rectangular.ark | Bin 221 -> 0 bytes ....17-false-true-true-false-true-hamming.ark | Bin 41 -> 0 bytes ...4-true-true-true-true-true-rectangular.ark | Bin 45 -> 0 bytes ....79-false-false-false-true-false-povey.ark | Bin 57 -> 0 bytes ...65-false-true-true-true-false-blackman.ark | Bin 89 -> 0 bytes ...-false-true-true-true-true-rectangular.ark | Bin 341 -> 0 bytes ...false-true-true-false-true-rectangular.ark | Bin 57 -> 0 bytes ...88-false-true-false-true-true-blackman.ark | Bin 45 -> 0 bytes ....19-true-false-true-true-true-blackman.ark | Bin 93 -> 0 bytes ...alse-true-false-false-true-rectangular.ark | Bin 37 -> 0 bytes ...true-true-true-false-false-rectangular.ark | Bin 45 -> 0 bytes ...-0.86-true-true-true-true-true-hamming.ark | Bin 93 -> 0 bytes ....42-false-false-true-true-true-hamming.ark | Bin 89 -> 0 bytes ...54-true-true-true-false-false-blackman.ark | Bin 33 -> 0 bytes ...06-false-true-true-false-true-blackman.ark | Bin 61 -> 0 bytes ....82-false-true-false-true-true-hamming.ark | Bin 45 -> 0 bytes ...1.00-true-true-true-true-false-hanning.ark | Bin 89 -> 0 bytes ....55-false-true-true-false-true-hamming.ark | Bin 61 -> 0 bytes ...true-false-false-true-true-rectangular.ark | Bin 61 -> 0 bytes ...alse-false-true-false-true-rectangular.ark | Bin 57 -> 0 bytes ...74-false-false-true-false-true-hanning.ark | Bin 57 -> 0 bytes ...68-true-true-false-false-false-hanning.ark | Bin 53 -> 0 bytes ...8-true-true-true-true-true-rectangular.ark | Bin 89 -> 0 bytes ...-false-true-true-true-true-rectangular.ark | Bin 141 -> 0 bytes ...89-false-false-false-false-false-povey.ark | Bin 45 -> 0 bytes ...0.82-false-true-true-true-true-hamming.ark | Bin 89 -> 0 bytes ...39-false-true-true-false-false-hanning.ark | Bin 221 -> 0 bytes ...true-false-true-true-false-rectangular.ark | Bin 93 -> 0 bytes ...74-true-false-true-false-false-hamming.ark | Bin 45 -> 0 bytes ...01-true-false-true-false-false-hamming.ark | Bin 221 -> 0 bytes ...30-false-false-true-false-true-hanning.ark | Bin 93 -> 0 bytes ...0.92-true-false-true-false-false-povey.ark | Bin 57 -> 0 bytes ....27-false-true-true-true-true-blackman.ark | Bin 57 -> 0 bytes ...77-false-false-true-true-false-hanning.ark | Bin 61 -> 0 bytes ...29-false-false-true-false-true-hanning.ark | Bin 105 -> 0 bytes ....08-false-true-false-false-false-povey.ark | Bin 261 -> 0 bytes ...91-false-false-true-false-true-hanning.ark | Bin 33 -> 0 bytes ...0.21-true-false-true-true-true-hanning.ark | Bin 41 -> 0 bytes ...0.04-true-false-true-true-true-hamming.ark | Bin 57 -> 0 bytes ...8-false-true-false-false-true-blackman.ark | Bin 133 -> 0 bytes ...alse-false-true-true-false-rectangular.ark | Bin 101 -> 0 bytes ....48-false-true-false-false-false-povey.ark | Bin 81 -> 0 bytes ...4-false-true-false-true-false-blackman.ark | Bin 53 -> 0 bytes test/assets/kaldi_test_mfcc_args.json | 3 - test/assets/kaldi_test_spectrogram_args.json | 109 +++++ test/common_utils.py | 80 ++-- ...t_functional.py => functional_cpu_test.py} | 44 +- test/functional_cuda_test.py | 16 + test/functional_impl.py | 31 ++ test/kaldi_compatibility_cpu_test.py | 11 +- test/kaldi_compatibility_cuda_test.py | 13 +- test/kaldi_compatibility_impl.py | 13 + test/test_backend.py | 42 ++ test/test_batch_consistency.py | 9 +- test/test_compliance_kaldi.py | 99 +--- test/test_dataloader.py | 8 +- test/test_datasets.py | 41 +- test/test_io.py | 59 +-- test/test_kaldi_io.py | 2 +- test/test_librosa_compatibility.py | 27 +- test/test_models.py | 51 ++- test/test_sox_compatibility.py | 61 +-- test/test_sox_effects.py | 47 +- test/test_transforms.py | 4 +- test/torchscript_consistency_cpu_test.py | 28 +- test/torchscript_consistency_cuda_test.py | 27 +- test/torchscript_consistency_impl.py | 1 + torchaudio/__init__.py | 430 ++---------------- torchaudio/_backend.py | 68 --- torchaudio/_internal/__init__.py | 0 torchaudio/_internal/misc_ops.py | 30 ++ torchaudio/_internal/module_utils.py | 56 +++ torchaudio/_sox_backend.py | 72 --- torchaudio/backend/__init__.py | 21 + torchaudio/backend/common.py | 143 ++++++ torchaudio/backend/no_backend.py | 35 ++ .../soundfile_backend.py} | 69 ++- torchaudio/backend/sox_backend.py | 275 +++++++++++ torchaudio/backend/utils.py | 74 +++ torchaudio/common_utils.py | 38 -- torchaudio/compliance/kaldi.py | 5 +- torchaudio/csrc/register.cpp | 18 + torchaudio/csrc/typedefs.cpp | 23 + torchaudio/csrc/typedefs.h | 23 + torchaudio/datasets/__init__.py | 2 + torchaudio/datasets/cmuarctic.py | 150 ++++++ torchaudio/extension/__init__.py | 7 + torchaudio/extension/extension.py | 49 ++ torchaudio/functional.py | 24 +- torchaudio/kaldi_io.py | 16 +- torchaudio/models/__init__.py | 1 + torchaudio/models/_wavernn.py | 105 +++++ torchaudio/sox_effects/__init__.py | 12 + torchaudio/{ => sox_effects}/sox_effects.py | 93 +++- 428 files changed, 1659 insertions(+), 1025 deletions(-) create mode 100644 test/assets/ARCTIC/cmu_us_aew_arctic/etc/txt.done.data create mode 100644 test/assets/ARCTIC/cmu_us_aew_arctic/wav/arctic_a0024.wav delete mode 100644 test/assets/kaldi/fbank-0.0939-4.5062-1.0625-0.6875-1841-true-479-5-0.84-true-true-true-true-true-true-true-false-1832-1824-1.0000-hanning.ark delete mode 100644 test/assets/kaldi/fbank-0.1660-1.7875-1.1250-0.5000-4999-true-1740-6-0.29-true-false-true-false-false-true-false-true-4587-2289-1.0000-povey.ark delete mode 100644 test/assets/kaldi/fbank-0.2215-1.3444-1.1250-0.7500-7468-true-87-5-0.17-true-true-false-true-false-true-false-false-1700-870-0.3104-rectangular.ark delete mode 100644 test/assets/kaldi/fbank-0.2512-0.2607-0.8750-0.8750-7380-true-4471-5-0.76-true-true-true-true-true-true-false-true-7138-5172-1.0000-hamming.ark delete mode 100644 test/assets/kaldi/fbank-0.2834-1.7885-1.1875-0.9375-5385-false-2579-6-0.82-false-false-true-false-true-false-true-true-4782-4492-1.0000-povey.ark delete mode 100644 test/assets/kaldi/fbank-0.3188-1.6288-1.0000-0.5000-6258-true-2043-4-0.57-true-false-false-false-false-false-true-true-5274-3268-1.0000-hamming.ark delete mode 100644 test/assets/kaldi/fbank-0.3637-4.7928-1.0000-0.5625-7671-false-2385-5-0.81-true-false-true-true-false-true-false-true-6881-4659-1.0000-rectangular.ark delete mode 100644 test/assets/kaldi/fbank-0.4702-2.6680-1.0000-1.0000-7231-true-1515-4-0.92-true-false-false-false-true-false-false-true-6506-2549-1.0000-hamming.ark delete mode 100644 test/assets/kaldi/fbank-0.5177-2.3803-0.8750-0.3750-5535-true-194-5-0.22-false-true-true-false-true-false-true-true-3979-1023-1.0000-hanning.ark delete mode 100644 test/assets/kaldi/fbank-0.5988-0.8014-1.1250-0.8750-3663-true-1941-6-0.59-false-false-true-false-true-false-false-false-3373-3354-1.0000-blackman.ark delete mode 100644 test/assets/kaldi/fbank-0.6342-1.2603-1.0625-0.0625-6044-false-77-5-0.85-true-true-true-false-true-true-true-false-5918-4804-1.0000-blackman.ark delete mode 100644 test/assets/kaldi/fbank-0.6421-2.1404-0.7500-1.0625-6031-false-57-4-0.03-true-true-true-false-false-true-false-true-5417-1170-1.0000-povey.ark delete mode 100644 test/assets/kaldi/fbank-0.6740-1.3778-1.0000-0.8750-6623-true-2402-7-0.50-true-false-true-false-true-false-false-true-6491-6262-1.0000-hamming.ark delete mode 100644 test/assets/kaldi/fbank-0.7979-1.4223-1.1250-0.3125-2534-false-810-4-0.77-true-true-true-true-true-true-false-true-2494-2015-1.0000-hamming.ark delete mode 100644 test/assets/kaldi/fbank-0.8161-1.2937-0.9375-0.1250-5030-false-966-6-0.03-false-false-true-false-false-true-true-true-4652-2559-1.0000-hanning.ark delete mode 100644 test/assets/kaldi/fbank-0.8873-1.2866-1.1250-0.4375-5558-true-1464-8-0.77-true-true-true-false-true-false-false-false-4613-4001-1.4073-blackman.ark delete mode 100644 test/assets/kaldi/fbank-0.8997-2.8795-0.8750-0.5000-3383-false-259-4-0.08-true-true-true-true-false-true-true-false-1175-1038-1.0000-povey.ark delete mode 100644 test/assets/kaldi/fbank-0.9113-0.9909-0.6875-0.3750-7562-true-3978-4-0.03-false-true-true-false-false-false-true-true-6483-5671-1.0000-hamming.ark delete mode 100644 test/assets/kaldi/fbank-0.9312-3.3768-0.8125-1.1250-5824-false-1366-6-0.28-true-true-true-false-false-false-true-true-3917-1620-1.0000-hanning.ark delete mode 100644 test/assets/kaldi/fbank-0.9472-2.4134-0.7500-1.0000-7959-false-1770-6-0.12-true-true-true-true-true-false-false-true-6874-5861-1.1718-rectangular.ark delete mode 100644 test/assets/kaldi/fbank-0.9483-4.0177-1.1250-1.1250-7854-false-4793-5-0.47-true-true-false-false-false-true-false-false-5868-5848-1.0000-hamming.ark delete mode 100644 test/assets/kaldi/fbank-0.9631-3.3222-1.0000-0.5000-7662-true-1833-6-0.71-false-true-false-true-true-false-true-true-6204-5887-1.0000-rectangular.ark delete mode 100644 test/assets/kaldi/fbank-0.9820-1.6680-0.7500-0.1875-6788-false-1968-4-0.14-false-true-true-false-false-true-true-false-2114-2024-1.0000-blackman.ark delete mode 100644 test/assets/kaldi/fbank-1.0183-2.1572-1.0625-0.3750-2018-true-317-6-0.14-false-false-true-false-true-false-false-false-1118-947-1.0000-blackman.ark delete mode 100644 test/assets/kaldi/fbank-1.0269-0.3681-1.1250-0.5625-4897-true-543-4-0.57-false-true-true-true-true-false-false-false-1226-960-1.0000-blackman.ark delete mode 100644 test/assets/kaldi/fbank-1.0298-2.2490-1.1250-0.2500-2031-true-257-5-0.65-false-true-true-false-true-false-false-true-1731-1582-1.0000-blackman.ark delete mode 100644 test/assets/kaldi/fbank-1.2222-0.0582-1.1875-0.8125-6633-false-1117-8-0.96-false-true-true-true-false-false-true-false-4191-3264-1.0000-blackman.ark delete mode 100644 test/assets/kaldi/fbank-1.2251-0.4403-0.5625-0.6875-3192-false-599-4-0.75-true-false-true-false-false-false-false-true-3183-2975-1.0000-povey.ark delete mode 100644 test/assets/kaldi/fbank-1.2278-1.4848-0.6875-0.6250-5785-true-289-4-0.58-true-true-true-false-true-false-false-true-4062-3715-1.0000-hanning.ark delete mode 100644 test/assets/kaldi/fbank-1.3199-1.1137-1.1250-0.6875-6702-true-390-6-0.54-true-false-false-true-true-false-true-false-4426-2811-1.0000-povey.ark delete mode 100644 test/assets/kaldi/fbank-1.3325-2.6552-1.0000-1.0625-6444-true-759-4-0.67-false-true-true-false-true-false-false-false-6065-4599-1.0000-hamming.ark delete mode 100644 test/assets/kaldi/fbank-1.3426-1.5712-1.1875-1.0000-7444-false-1986-6-0.46-true-false-true-true-true-false-true-true-4787-3163-1.0000-hanning.ark delete mode 100644 test/assets/kaldi/fbank-1.4359-1.2709-1.0000-0.5625-7657-true-1017-5-0.93-true-false-true-true-false-false-false-true-4228-2903-1.0000-hanning.ark delete mode 100644 test/assets/kaldi/fbank-1.4621-1.2891-0.8750-1.0625-6324-true-408-7-0.09-false-true-true-true-false-false-false-false-6163-5973-1.0000-povey.ark delete mode 100644 test/assets/kaldi/fbank-1.4751-2.3567-1.1875-1.0000-7115-false-4236-5-0.65-true-false-true-true-true-true-true-false-6523-5708-1.0000-rectangular.ark delete mode 100644 test/assets/kaldi/fbank-1.4883-4.1237-0.7500-0.2500-5670-true-766-6-0.29-true-true-true-false-true-false-false-false-5479-4173-1.0000-povey.ark delete mode 100644 test/assets/kaldi/fbank-1.4930-1.4719-1.1250-0.2500-7805-true-5052-4-0.90-true-true-false-true-false-true-false-false-7300-5299-1.0000-blackman.ark delete mode 100644 test/assets/kaldi/fbank-1.5718-3.5447-0.6250-0.1875-6777-true-938-4-0.69-true-false-false-false-false-true-true-false-4540-3168-1.0000-blackman.ark delete mode 100644 test/assets/kaldi/fbank-1.5786-1.9016-1.1875-0.7500-5812-true-3000-4-0.14-false-false-true-false-false-true-true-false-4930-4316-1.0000-rectangular.ark delete mode 100644 test/assets/kaldi/fbank-1.6134-0.6389-1.0625-0.8125-7384-false-184-7-0.08-true-false-true-true-false-false-false-true-2759-306-1.0000-rectangular.ark delete mode 100644 test/assets/kaldi/fbank-1.6312-2.6556-0.6250-0.4375-5589-false-1049-5-0.80-false-false-false-true-false-false-false-false-3816-1550-1.0000-rectangular.ark delete mode 100644 test/assets/kaldi/fbank-1.7515-0.5964-1.0625-1.0000-4349-true-702-5-0.36-true-false-true-false-true-true-false-false-4168-1531-1.0000-povey.ark delete mode 100644 test/assets/kaldi/fbank-1.8179-1.3295-0.5625-0.6875-4510-false-122-4-0.56-false-false-true-true-true-true-false-false-4365-3721-1.0000-hanning.ark delete mode 100644 test/assets/kaldi/fbank-1.9387-4.7991-1.0000-0.3750-6123-true-740-6-0.21-true-false-false-true-false-true-true-true-3970-3355-1.0000-hamming.ark delete mode 100644 test/assets/kaldi/fbank-2.0479-1.4296-1.0625-0.6875-7818-true-1628-8-0.27-true-true-true-true-false-true-false-true-7749-7478-1.0000-blackman.ark delete mode 100644 test/assets/kaldi/fbank-2.0809-1.9752-0.7500-1.1875-5933-false-666-5-0.72-false-true-false-false-true-true-true-true-5348-4645-1.0000-povey.ark delete mode 100644 test/assets/kaldi/fbank-2.0971-4.0447-1.1875-0.4375-3361-false-513-6-0.26-false-true-true-false-true-true-false-true-3122-2865-1.0000-hanning.ark delete mode 100644 test/assets/kaldi/fbank-2.1098-2.1356-1.0625-0.9375-7825-true-408-4-0.37-true-true-true-true-true-true-false-false-5297-2747-1.0000-hamming.ark delete mode 100644 test/assets/kaldi/fbank-2.1463-0.3422-0.8125-0.5000-6892-true-65-4-0.47-false-false-true-true-true-true-false-true-4178-2891-1.0000-rectangular.ark delete mode 100644 test/assets/kaldi/fbank-2.1768-3.7820-0.7500-0.8125-7063-false-2703-4-0.99-true-false-false-false-true-false-false-true-6819-3764-1.0000-hanning.ark delete mode 100644 test/assets/kaldi/fbank-2.1792-4.7065-0.6250-0.1875-6808-true-742-4-0.36-false-true-true-false-true-false-true-true-5081-4539-1.0000-hamming.ark delete mode 100644 test/assets/kaldi/fbank-2.1902-4.9973-1.1250-0.5000-7066-false-1699-4-0.95-true-false-true-true-false-false-false-false-5452-5271-1.0000-rectangular.ark delete mode 100644 test/assets/kaldi/fbank-2.2390-2.9557-1.0625-0.8750-7615-true-4707-7-1.00-true-false-true-true-false-true-true-true-6790-6501-1.0000-povey.ark delete mode 100644 test/assets/kaldi/fbank-2.3199-0.8311-0.9375-0.3125-6738-true-1787-5-0.83-false-false-true-false-false-true-false-true-6635-6360-0.7856-povey.ark delete mode 100644 test/assets/kaldi/fbank-2.4071-2.7889-0.9375-0.8125-6598-true-2373-5-0.20-true-true-true-false-false-false-true-true-4565-3464-1.0000-hamming.ark delete mode 100644 test/assets/kaldi/fbank-2.4586-3.3176-0.6250-0.7500-7380-false-4248-4-0.59-true-false-true-false-false-false-false-true-7263-6361-1.0000-hamming.ark delete mode 100644 test/assets/kaldi/fbank-2.6039-1.1619-0.7500-0.5625-6578-true-551-7-0.16-false-true-true-true-true-false-true-true-4974-3139-1.0000-povey.ark delete mode 100644 test/assets/kaldi/fbank-2.6068-3.6411-1.1250-1.1250-3078-false-1003-5-0.12-true-true-true-false-false-true-true-false-2920-1121-1.0000-povey.ark delete mode 100644 test/assets/kaldi/fbank-2.6192-1.7209-1.0625-0.6250-2275-false-367-5-0.27-false-true-true-true-false-true-false-true-1293-771-1.0000-blackman.ark delete mode 100644 test/assets/kaldi/fbank-2.6578-0.9137-1.1875-1.0000-4898-true-886-7-0.57-true-false-true-false-true-true-false-false-3704-1013-1.0000-povey.ark delete mode 100644 test/assets/kaldi/fbank-2.7083-2.8806-0.7500-0.9375-6605-false-3759-4-0.90-true-false-true-true-false-false-false-true-6542-5821-1.0000-rectangular.ark delete mode 100644 test/assets/kaldi/fbank-2.7704-4.5251-1.1250-0.8750-3819-true-787-5-0.23-false-false-true-true-true-true-false-false-3368-3286-1.0000-hamming.ark delete mode 100644 test/assets/kaldi/fbank-2.9255-3.4363-1.1250-1.0000-7660-false-5020-5-0.09-true-false-true-true-true-true-false-false-7470-6783-1.0000-hamming.ark delete mode 100644 test/assets/kaldi/fbank-3.0009-1.8450-1.0625-0.7500-5812-true-1287-6-0.22-false-false-true-true-true-true-false-false-5573-4642-1.0000-hanning.ark delete mode 100644 test/assets/kaldi/fbank-3.0442-4.0677-1.0625-1.1250-5086-true-1013-4-0.99-false-false-true-true-false-true-true-false-4997-4836-1.9525-hamming.ark delete mode 100644 test/assets/kaldi/fbank-3.1610-1.5305-0.8750-0.1875-6634-false-1213-6-0.37-false-true-true-false-true-true-true-false-3273-3199-1.0000-povey.ark delete mode 100644 test/assets/kaldi/fbank-3.2195-2.9858-1.0625-0.0625-6899-true-4117-6-0.85-true-true-true-true-false-false-true-true-5077-4977-0.8739-rectangular.ark delete mode 100644 test/assets/kaldi/fbank-3.3208-1.5569-1.0000-0.3125-4556-false-334-5-0.02-false-true-true-true-true-false-true-false-2831-696-1.0000-hanning.ark delete mode 100644 test/assets/kaldi/fbank-3.3976-3.9462-1.1875-0.5625-6513-false-3398-8-0.38-true-true-true-false-false-false-true-false-5827-5388-1.0000-blackman.ark delete mode 100644 test/assets/kaldi/fbank-3.5842-1.2264-0.9375-1.0000-7744-false-195-5-0.62-false-false-true-false-false-true-true-false-7667-2993-1.0000-hamming.ark delete mode 100644 test/assets/kaldi/fbank-3.5889-3.3559-1.0000-1.1875-7354-true-997-5-0.98-false-true-true-true-true-false-false-false-7088-6494-1.0000-povey.ark delete mode 100644 test/assets/kaldi/fbank-3.5936-2.1701-1.0625-1.0625-7407-true-3649-5-0.65-false-true-true-true-false-true-true-true-6878-6036-1.0000-povey.ark delete mode 100644 test/assets/kaldi/fbank-3.7002-3.5670-1.1875-0.6250-4479-true-2240-6-0.73-false-false-true-false-false-true-false-true-4084-3955-1.0000-hamming.ark delete mode 100644 test/assets/kaldi/fbank-3.7078-0.3892-0.8125-0.3125-7876-true-2830-7-0.46-false-false-true-true-true-false-false-true-4726-2918-1.0000-rectangular.ark delete mode 100644 test/assets/kaldi/fbank-3.7585-2.9425-1.1875-1.0000-3277-true-2244-4-0.76-false-false-true-false-true-false-false-false-3158-2865-1.0000-rectangular.ark delete mode 100644 test/assets/kaldi/fbank-3.7772-2.8211-1.0000-0.1875-3747-false-1244-4-0.64-false-true-true-false-true-false-false-true-3640-2770-1.0000-hanning.ark delete mode 100644 test/assets/kaldi/fbank-3.8514-3.7933-1.0625-0.5000-4136-true-1010-6-0.12-false-false-true-false-false-true-true-false-2408-1892-1.0000-hanning.ark delete mode 100644 test/assets/kaldi/fbank-3.8677-2.5418-1.0625-0.0625-3496-true-309-4-0.47-false-false-true-false-false-false-true-false-1490-645-1.0000-rectangular.ark delete mode 100644 test/assets/kaldi/fbank-3.8988-3.9608-1.1250-0.1250-6973-false-1703-5-0.68-true-false-true-false-true-true-true-true-6446-6419-1.0000-povey.ark delete mode 100644 test/assets/kaldi/fbank-3.9002-4.3071-1.1875-0.0625-6179-false-3450-7-0.39-false-false-true-false-true-false-true-true-5637-3692-1.0000-rectangular.ark delete mode 100644 test/assets/kaldi/fbank-3.9033-2.6770-1.1250-0.8750-5699-false-2960-7-0.52-true-true-true-true-true-true-false-false-5458-5400-1.0000-rectangular.ark delete mode 100644 test/assets/kaldi/fbank-3.9687-0.6295-1.1250-0.0625-5774-false-3495-4-0.48-true-true-true-true-true-true-true-false-5769-5699-1.0000-povey.ark delete mode 100644 test/assets/kaldi/fbank-4.0371-3.7559-1.0625-0.8125-4280-false-1207-4-0.12-true-false-true-true-true-true-false-true-3686-2010-1.0000-hamming.ark delete mode 100644 test/assets/kaldi/fbank-4.0757-4.7442-0.8750-1.1250-6363-true-1524-4-0.32-true-false-false-true-false-true-true-false-5178-4628-1.0000-blackman.ark delete mode 100644 test/assets/kaldi/fbank-4.1248-2.5255-0.6875-0.6875-3527-true-1701-4-0.43-true-true-true-true-true-true-false-true-2884-1773-1.0000-blackman.ark delete mode 100644 test/assets/kaldi/fbank-4.1800-4.6907-1.1875-0.5625-7316-true-3483-8-0.61-false-true-true-false-true-true-true-true-5820-4635-1.0000-rectangular.ark delete mode 100644 test/assets/kaldi/fbank-4.2251-0.5000-0.8750-0.6250-7515-false-1751-5-0.64-true-true-true-true-false-false-true-false-7486-4238-1.0000-hamming.ark delete mode 100644 test/assets/kaldi/fbank-4.3011-1.4663-1.1250-0.9375-7804-false-1208-6-0.18-false-false-true-false-false-true-true-false-7421-3707-1.0000-hanning.ark delete mode 100644 test/assets/kaldi/fbank-4.3252-0.7732-0.6250-0.6875-7389-false-2071-4-0.08-true-false-true-false-false-true-false-false-6900-2344-1.0000-blackman.ark delete mode 100644 test/assets/kaldi/fbank-4.3693-3.9073-0.8750-0.9375-6107-true-3905-4-0.86-true-false-true-false-true-true-false-true-5001-4046-1.0000-rectangular.ark delete mode 100644 test/assets/kaldi/fbank-4.3926-2.0617-0.5625-0.0625-4253-true-1367-5-0.84-false-true-true-true-false-true-true-false-2112-1445-1.0000-hamming.ark delete mode 100644 test/assets/kaldi/fbank-4.4706-1.7516-1.1250-1.1250-7645-false-225-6-0.80-false-false-false-true-false-false-false-false-3717-304-1.0000-blackman.ark delete mode 100644 test/assets/kaldi/fbank-4.5385-2.1519-1.1250-0.0625-5610-false-1239-7-0.87-false-true-false-true-true-true-true-false-2231-1432-1.0000-rectangular.ark delete mode 100644 test/assets/kaldi/fbank-4.6337-2.9020-0.8750-1.1250-5072-true-826-4-0.37-true-true-true-true-false-false-false-false-4253-2427-0.7049-povey.ark delete mode 100644 test/assets/kaldi/fbank-4.7468-2.1835-0.6875-1.0000-5153-true-943-5-0.94-false-false-true-true-true-false-false-false-3287-1478-0.9406-hanning.ark delete mode 100644 test/assets/kaldi/fbank-4.7855-2.1377-0.9375-0.8125-4123-false-587-4-0.92-true-false-true-false-true-false-true-false-2588-2346-1.0000-rectangular.ark delete mode 100644 test/assets/kaldi/fbank-4.9640-3.4931-1.1875-1.0000-4235-true-1036-4-0.43-false-true-true-false-true-true-false-false-3706-2840-1.0000-hamming.ark delete mode 100644 test/assets/kaldi/mfcc-0.0063-3.0323-0.6250-0.0625-5842-false-3240-4-0.29-true-false-true-true-true-true-2-73.5792-5749-4449-1.0000-blackman.ark delete mode 100644 test/assets/kaldi/mfcc-0.0130-1.8509-1.1875-0.6250-7999-false-4330-5-0.38-true-false-true-false-false-true-3-8.1048-7497-7397-1.0000-blackman.ark delete mode 100644 test/assets/kaldi/mfcc-0.0487-1.3641-1.0000-0.8125-7892-true-1904-8-0.26-true-true-true-false-false-false-5-34.0918-4400-2737-1.0000-rectangular.ark delete mode 100644 test/assets/kaldi/mfcc-0.0577-2.4313-1.0625-0.8750-2922-true-274-6-0.48-false-false-true-true-false-true-5-21.3007-1352-280-1.0000-hanning.ark delete mode 100644 test/assets/kaldi/mfcc-0.0718-1.3071-1.1875-0.5000-3159-true-759-8-0.04-false-true-true-true-true-true-6-2.6493-3145-3119-1.0000-povey.ark delete mode 100644 test/assets/kaldi/mfcc-0.0830-2.1607-0.7500-0.7500-5872-true-708-5-0.95-false-false-false-false-false-true-4-24.5097-5231-3888-1.0000-hamming.ark delete mode 100644 test/assets/kaldi/mfcc-0.0933-1.5770-1.1875-1.1875-7519-false-357-4-0.50-false-false-true-true-true-false-2-88.0941-7042-5298-1.0000-rectangular.ark delete mode 100644 test/assets/kaldi/mfcc-0.1048-0.5013-0.7500-1.0625-6426-true-3613-5-0.96-false-false-true-true-false-true-4-73.5838-5816-3997-1.0000-povey.ark delete mode 100644 test/assets/kaldi/mfcc-0.1447-4.7142-1.0625-0.4375-7629-true-3498-7-0.39-true-true-true-true-true-false-3-19.4145-7169-6751-1.0000-hanning.ark delete mode 100644 test/assets/kaldi/mfcc-0.1473-4.9154-1.1250-0.8750-3631-false-1229-8-0.04-true-true-true-false-true-true-3-34.4790-3390-1536-1.0000-blackman.ark delete mode 100644 test/assets/kaldi/mfcc-0.1485-4.2750-0.6875-0.7500-5222-true-311-5-0.31-false-true-true-true-true-true-3-48.7991-4833-513-1.0000-hanning.ark delete mode 100644 test/assets/kaldi/mfcc-0.1829-4.5358-0.9375-0.9375-6148-true-455-5-0.59-true-false-true-false-false-false-3-48.6724-3138-2247-1.0000-blackman.ark delete mode 100644 test/assets/kaldi/mfcc-0.2002-1.4805-0.9375-0.8750-7621-false-2232-5-0.03-false-false-true-true-false-true-5-69.3653-7087-2800-1.0000-blackman.ark delete mode 100644 test/assets/kaldi/mfcc-0.2107-3.4750-1.1250-0.8125-5701-true-1629-4-0.09-true-false-true-false-true-true-2-77.7066-5622-5544-1.0000-blackman.ark delete mode 100644 test/assets/kaldi/mfcc-0.2523-0.1480-1.0000-1.1250-5833-false-556-4-0.66-true-true-true-true-true-false-4-57.0398-4519-3600-1.0000-rectangular.ark delete mode 100644 test/assets/kaldi/mfcc-0.2648-0.5702-1.1875-0.1250-5559-false-932-8-0.92-false-false-true-false-true-false-3-96.3721-4277-2466-1.0000-rectangular.ark delete mode 100644 test/assets/kaldi/mfcc-0.2959-2.3729-0.6250-0.5000-6757-false-1744-6-0.20-true-false-true-true-true-false-2-99.8710-4957-3549-1.0000-povey.ark delete mode 100644 test/assets/kaldi/mfcc-0.3642-3.5246-0.4375-0.9375-7942-false-3282-4-0.52-false-false-true-true-false-false-3-74.4735-5601-4966-1.0000-blackman.ark delete mode 100644 test/assets/kaldi/mfcc-0.4261-0.8487-0.3750-0.1250-6730-false-1273-5-0.71-true-true-true-false-true-false-3-57.1750-3578-2101-1.0000-hanning.ark delete mode 100644 test/assets/kaldi/mfcc-0.4891-1.9890-1.1250-0.8750-3219-true-973-5-0.91-false-false-true-true-true-true-4-85.3570-3181-3129-1.0000-hamming.ark delete mode 100644 test/assets/kaldi/mfcc-0.5428-1.2368-0.5625-1.0000-6700-false-749-4-0.86-false-false-true-true-true-true-2-16.2782-5573-4988-1.0000-rectangular.ark delete mode 100644 test/assets/kaldi/mfcc-0.5495-2.9502-1.1875-1.1875-3873-true-1564-5-0.05-false-true-true-false-true-false-5-59.0075-3870-3750-1.0000-hanning.ark delete mode 100644 test/assets/kaldi/mfcc-0.6055-3.9496-1.0000-0.1250-7949-true-1517-8-0.88-false-true-false-false-true-false-6-55.7891-4641-2879-1.0000-hanning.ark delete mode 100644 test/assets/kaldi/mfcc-0.6457-2.0199-0.8750-0.8125-6510-false-1482-4-0.26-false-true-false-true-false-true-2-49.7663-5461-4039-1.0000-blackman.ark delete mode 100644 test/assets/kaldi/mfcc-0.7031-4.0380-1.1250-0.6875-6433-true-2336-8-0.70-false-true-false-true-true-false-3-18.0061-5902-3191-1.0000-rectangular.ark delete mode 100644 test/assets/kaldi/mfcc-0.7113-4.1529-0.6875-0.1250-6374-false-2129-4-0.76-false-true-true-false-true-true-2-58.5051-4692-2757-1.0000-blackman.ark delete mode 100644 test/assets/kaldi/mfcc-0.7197-3.2075-1.0625-0.2500-4448-true-378-4-0.31-true-false-true-false-false-false-2-71.5910-3497-3331-1.0000-hanning.ark delete mode 100644 test/assets/kaldi/mfcc-0.7238-1.9087-1.1875-0.7500-5457-true-1775-7-0.48-true-false-true-true-true-true-3-29.2858-5349-3987-1.0000-rectangular.ark delete mode 100644 test/assets/kaldi/mfcc-0.7507-0.2754-0.8750-0.8125-6405-false-1972-5-0.83-false-true-false-true-true-true-2-52.5962-4597-4417-1.0000-povey.ark delete mode 100644 test/assets/kaldi/mfcc-0.7954-0.3451-1.1875-0.6250-4078-false-796-8-0.47-true-false-true-true-false-true-8-42.3128-2299-1094-1.0000-blackman.ark delete mode 100644 test/assets/kaldi/mfcc-0.8432-1.3765-0.9375-1.1875-6004-true-2302-4-0.60-false-false-true-false-true-true-4-74.1116-4129-2898-1.0000-hamming.ark delete mode 100644 test/assets/kaldi/mfcc-0.8549-4.8924-0.3125-1.1250-5643-true-956-4-0.32-true-false-true-false-false-true-2-76.0384-2672-1762-1.0000-rectangular.ark delete mode 100644 test/assets/kaldi/mfcc-0.8596-3.8941-1.0625-1.1250-5952-false-3433-8-0.25-true-false-true-true-false-false-6-49.2912-5518-5442-1.0000-hamming.ark delete mode 100644 test/assets/kaldi/mfcc-0.9502-1.9738-0.7500-0.2500-7773-true-1205-7-0.50-false-false-true-false-false-true-3-62.9038-7460-7174-1.0000-blackman.ark delete mode 100644 test/assets/kaldi/mfcc-1.0759-1.9132-1.1875-0.6250-3529-false-227-8-0.26-true-false-true-true-false-true-4-4.1559-1976-972-1.0000-hanning.ark delete mode 100644 test/assets/kaldi/mfcc-1.1470-4.3972-0.9375-0.7500-6393-true-2451-4-0.06-true-false-true-true-false-true-4-67.4571-5460-3654-1.0000-povey.ark delete mode 100644 test/assets/kaldi/mfcc-1.1602-3.7738-1.0625-0.0625-3652-false-1886-4-0.55-true-true-true-false-true-true-3-73.6328-3496-2890-1.0000-hamming.ark delete mode 100644 test/assets/kaldi/mfcc-1.2069-0.4607-1.1250-0.5625-5864-true-1512-7-0.17-false-true-true-false-false-true-3-33.0194-5438-3920-1.0000-blackman.ark delete mode 100644 test/assets/kaldi/mfcc-1.2303-1.5089-1.0625-0.8125-5882-false-3298-8-0.49-true-false-true-false-false-false-7-81.2017-5809-5654-1.0000-hamming.ark delete mode 100644 test/assets/kaldi/mfcc-1.3369-4.2619-0.6875-0.3750-5307-true-666-6-0.19-false-false-true-true-false-true-4-88.3186-4677-2590-1.0000-hamming.ark delete mode 100644 test/assets/kaldi/mfcc-1.3699-3.0236-1.0625-0.7500-3720-true-1980-4-0.13-true-true-true-false-false-true-3-57.6793-3441-3396-1.0000-blackman.ark delete mode 100644 test/assets/kaldi/mfcc-1.3763-1.6574-1.1250-0.8125-2816-false-1021-4-0.91-true-false-true-true-true-true-2-45.2819-2547-1123-1.0000-rectangular.ark delete mode 100644 test/assets/kaldi/mfcc-1.4097-4.1523-0.8750-0.3750-6164-false-987-4-0.06-false-true-true-true-false-false-3-75.0589-5873-5807-1.0000-hamming.ark delete mode 100644 test/assets/kaldi/mfcc-1.4295-3.7938-1.1250-0.7500-3382-false-471-4-0.42-false-false-false-false-true-true-2-78.5880-3299-2540-1.0000-hanning.ark delete mode 100644 test/assets/kaldi/mfcc-1.4677-4.0728-1.1250-1.0625-7698-true-569-6-0.50-true-true-false-true-true-false-3-76.8484-7453-7251-1.0000-rectangular.ark delete mode 100644 test/assets/kaldi/mfcc-1.4943-1.9921-0.9375-0.3750-7846-false-1602-5-0.93-false-false-true-false-true-true-3-44.8604-5099-4429-1.0000-povey.ark delete mode 100644 test/assets/kaldi/mfcc-1.4979-1.1705-1.1875-0.3750-4474-true-1123-7-0.09-true-false-true-true-false-true-4-38.6407-3043-2934-1.0000-hamming.ark delete mode 100644 test/assets/kaldi/mfcc-1.4988-0.0621-0.8750-0.1875-4881-true-846-4-0.53-false-true-false-false-false-true-2-17.5040-4228-1009-1.0000-rectangular.ark delete mode 100644 test/assets/kaldi/mfcc-1.5514-3.7279-1.0000-0.2500-7958-true-481-5-0.93-true-true-false-true-true-true-4-98.3869-7445-7362-1.0000-hamming.ark delete mode 100644 test/assets/kaldi/mfcc-1.5550-1.8728-0.8750-0.9375-5191-true-2262-4-0.24-true-true-true-false-true-false-2-11.9820-4607-4483-1.0000-povey.ark delete mode 100644 test/assets/kaldi/mfcc-1.5626-3.7117-1.1250-0.1250-3008-true-534-5-0.65-true-false-false-true-true-true-2-75.6661-2592-1621-1.0000-hamming.ark delete mode 100644 test/assets/kaldi/mfcc-1.5707-3.0409-0.7500-0.6250-7441-true-1554-6-0.95-true-false-true-true-true-true-4-80.1563-7152-6151-1.0000-rectangular.ark delete mode 100644 test/assets/kaldi/mfcc-1.5966-2.3442-0.5625-0.5000-7944-true-1616-5-0.49-true-true-true-false-false-true-2-80.8779-5720-4080-1.0000-povey.ark delete mode 100644 test/assets/kaldi/mfcc-1.6229-2.0519-1.1875-0.3125-4871-true-1567-4-0.79-false-true-true-true-false-true-2-42.9569-3483-3287-1.0000-hanning.ark delete mode 100644 test/assets/kaldi/mfcc-1.6399-3.5598-1.0000-0.2500-6102-false-1267-4-0.83-true-false-true-false-false-false-4-31.0832-5457-4742-1.0000-rectangular.ark delete mode 100644 test/assets/kaldi/mfcc-1.7360-0.4063-0.6875-0.0625-6475-true-4439-4-0.23-true-false-true-false-false-false-2-30.0984-5450-4909-1.0000-rectangular.ark delete mode 100644 test/assets/kaldi/mfcc-1.7411-2.0918-1.0625-0.8125-6107-true-2523-4-0.69-true-false-true-true-false-false-3-92.6839-5085-4771-1.0000-povey.ark delete mode 100644 test/assets/kaldi/mfcc-1.7439-2.3782-0.8750-1.1875-7669-false-4499-4-0.81-false-true-false-true-false-false-2-95.7035-7521-7417-1.0000-hamming.ark delete mode 100644 test/assets/kaldi/mfcc-1.7611-4.2965-0.8125-0.6875-6607-false-454-7-0.35-true-true-true-false-true-false-2-17.8265-6387-6105-1.0000-hanning.ark delete mode 100644 test/assets/kaldi/mfcc-1.7893-1.8005-0.6250-0.3750-2791-true-617-4-0.96-true-false-true-true-false-true-4-93.4050-1751-1690-1.0000-povey.ark delete mode 100644 test/assets/kaldi/mfcc-1.8392-4.3711-0.9375-0.7500-6978-true-453-4-0.48-true-true-true-true-true-false-3-42.9768-6315-3995-1.1059-rectangular.ark delete mode 100644 test/assets/kaldi/mfcc-1.8810-1.1207-1.0625-0.1250-7667-true-5118-7-0.58-false-false-true-false-true-false-5-33.6608-6998-6740-1.0000-povey.ark delete mode 100644 test/assets/kaldi/mfcc-1.9561-0.8419-0.8125-1.1250-5308-false-1471-5-0.62-true-false-true-true-false-true-3-51.0514-5221-5071-1.0000-rectangular.ark delete mode 100644 test/assets/kaldi/mfcc-1.9980-1.6949-1.1250-0.8125-4678-true-2340-5-0.44-true-false-false-true-false-true-3-70.1988-4041-2424-1.0000-rectangular.ark delete mode 100644 test/assets/kaldi/mfcc-2.0106-4.5392-0.6875-0.1875-4776-true-1297-5-0.14-false-false-true-false-false-true-2-37.5837-3995-2991-1.0000-hanning.ark delete mode 100644 test/assets/kaldi/mfcc-2.0603-1.7529-0.6875-0.6250-7900-false-5086-4-0.74-false-false-true-false-true-false-4-59.0671-7431-7014-1.0000-hamming.ark delete mode 100644 test/assets/kaldi/mfcc-2.0835-2.8454-0.9375-0.3125-7496-false-1207-6-0.76-true-false-true-true-false-false-6-4.5734-3935-3932-1.0000-blackman.ark delete mode 100644 test/assets/kaldi/mfcc-2.1743-1.8196-1.0625-0.2500-5382-false-1493-6-0.05-true-true-true-false-false-false-6-35.3731-4786-4226-1.0000-hamming.ark delete mode 100644 test/assets/kaldi/mfcc-2.2801-1.7051-1.1875-0.1250-7958-true-561-4-0.90-false-false-true-true-true-true-2-60.4649-7218-5709-1.0000-rectangular.ark delete mode 100644 test/assets/kaldi/mfcc-2.3150-0.4964-0.5000-0.4375-6582-false-1010-4-0.98-false-false-true-true-false-false-3-71.5160-6157-4430-1.0000-rectangular.ark delete mode 100644 test/assets/kaldi/mfcc-2.3236-0.7825-0.8125-0.2500-7488-true-1363-4-0.30-false-true-true-true-true-true-4-68.9678-3555-1851-1.0000-blackman.ark delete mode 100644 test/assets/kaldi/mfcc-2.3318-4.4467-0.7500-0.1250-7229-true-3549-7-0.11-false-false-true-false-true-false-6-91.3952-6769-5907-1.0000-povey.ark delete mode 100644 test/assets/kaldi/mfcc-2.3805-2.9340-0.7500-0.2500-6076-true-80-4-0.85-false-true-true-false-true-true-3-31.0805-2257-1533-1.0000-hamming.ark delete mode 100644 test/assets/kaldi/mfcc-2.4091-2.8812-1.1250-0.9375-6086-false-1210-5-0.59-true-false-false-false-false-true-3-96.1612-4840-1905-1.0000-hamming.ark delete mode 100644 test/assets/kaldi/mfcc-2.4134-2.6379-1.1875-0.3750-3318-false-770-5-0.60-false-true-true-false-false-false-3-73.9427-2044-1481-1.0000-hanning.ark delete mode 100644 test/assets/kaldi/mfcc-2.5228-3.1056-1.1250-1.1875-5422-false-2825-7-0.88-false-false-true-false-false-false-7-4.6719-5337-5243-1.0000-hanning.ark delete mode 100644 test/assets/kaldi/mfcc-2.5421-3.9141-1.0000-0.1250-5126-false-362-5-0.10-false-true-false-true-true-true-4-83.2329-5090-1185-1.0000-hanning.ark delete mode 100644 test/assets/kaldi/mfcc-2.5577-0.7393-0.8125-0.5000-5291-true-1445-5-0.01-false-true-true-false-true-false-2-5.8944-4338-4330-1.0000-hanning.ark delete mode 100644 test/assets/kaldi/mfcc-2.5854-3.2219-0.8750-0.4375-6924-false-4024-4-1.00-false-true-true-false-true-false-2-0.0578-5707-5025-1.0000-rectangular.ark delete mode 100644 test/assets/kaldi/mfcc-2.6294-1.9703-1.1875-0.6250-7569-true-2883-8-0.91-false-true-true-false-true-true-7-31.0763-7031-6291-1.0000-povey.ark delete mode 100644 test/assets/kaldi/mfcc-2.6674-2.7770-1.0625-0.3125-3129-true-1706-4-0.91-false-true-true-false-true-true-3-50.9241-2593-2198-1.0000-hanning.ark delete mode 100644 test/assets/kaldi/mfcc-2.6816-4.0548-1.1875-0.6250-3182-false-157-6-0.04-false-true-true-true-true-false-5-31.3652-1203-1174-1.0000-povey.ark delete mode 100644 test/assets/kaldi/mfcc-2.7879-3.3482-0.6875-0.3750-4262-true-150-4-0.68-true-false-true-true-false-true-2-92.7940-3276-1685-1.0000-rectangular.ark delete mode 100644 test/assets/kaldi/mfcc-2.8683-3.8162-1.1250-0.3750-6620-false-3389-7-0.83-false-true-true-true-true-true-5-82.2365-5365-4579-1.0000-rectangular.ark delete mode 100644 test/assets/kaldi/mfcc-2.8690-3.2618-1.1875-0.9375-5646-true-491-8-0.89-false-false-true-false-false-true-2-59.9812-5397-2639-1.0000-hamming.ark delete mode 100644 test/assets/kaldi/mfcc-2.9211-4.1440-0.7500-0.3750-7210-true-3666-4-0.93-false-false-true-true-false-false-4-94.5907-6682-4979-1.0000-hamming.ark delete mode 100644 test/assets/kaldi/mfcc-2.9464-0.6798-1.1250-0.0625-4445-true-323-6-0.46-false-true-true-false-true-false-6-7.8133-3755-1137-1.0000-hanning.ark delete mode 100644 test/assets/kaldi/mfcc-2.9633-1.9565-0.8750-0.0625-6835-false-649-5-0.77-false-false-false-true-false-false-2-80.8871-6691-6581-1.0000-povey.ark delete mode 100644 test/assets/kaldi/mfcc-2.9643-3.8883-0.7500-0.2500-7373-false-1698-4-0.92-false-false-true-false-true-true-4-63.3036-6650-5500-1.0000-povey.ark delete mode 100644 test/assets/kaldi/mfcc-2.9697-2.0241-1.1250-0.6875-2170-false-180-5-0.28-false-true-true-true-true-true-3-95.8111-1266-521-1.0000-blackman.ark delete mode 100644 test/assets/kaldi/mfcc-3.0358-1.7295-1.1875-1.0000-7222-true-858-4-0.16-false-true-true-false-false-true-4-64.7537-6220-5229-1.0000-povey.ark delete mode 100644 test/assets/kaldi/mfcc-3.0421-3.3343-1.0000-0.9375-6477-false-1402-5-0.99-false-true-true-true-true-true-4-26.1743-6381-5017-1.0000-hamming.ark delete mode 100644 test/assets/kaldi/mfcc-3.0919-4.5103-0.6250-1.0000-5323-true-937-5-0.95-false-false-true-true-true-false-5-82.2405-5130-5086-1.0000-hanning.ark delete mode 100644 test/assets/kaldi/mfcc-3.1463-4.5068-0.6875-0.3125-7587-true-3542-7-0.78-true-false-true-true-true-true-4-28.5808-7478-7326-1.0000-blackman.ark delete mode 100644 test/assets/kaldi/mfcc-3.2007-1.3677-1.1250-0.1875-4726-true-2027-4-0.74-false-true-false-false-true-false-4-3.5732-4583-3742-1.0000-povey.ark delete mode 100644 test/assets/kaldi/mfcc-3.2416-1.0604-0.8750-0.5000-4730-false-968-4-0.11-true-true-true-false-true-true-3-60.5751-3542-1943-1.0000-blackman.ark delete mode 100644 test/assets/kaldi/mfcc-3.2432-2.7787-0.8125-0.9375-4407-false-847-5-0.24-false-false-true-false-false-false-4-90.4067-3617-3615-1.0000-rectangular.ark delete mode 100644 test/assets/kaldi/mfcc-3.2698-3.0361-1.0625-0.7500-4870-true-1281-7-0.64-false-true-true-false-true-true-3-28.5360-4401-3315-1.0000-blackman.ark delete mode 100644 test/assets/kaldi/mfcc-3.3078-4.9217-1.0000-0.3125-6758-true-760-5-0.98-true-true-true-true-false-true-3-97.4694-6022-5650-1.0000-rectangular.ark delete mode 100644 test/assets/kaldi/mfcc-3.3206-0.0230-1.0625-0.5625-5744-true-3901-5-0.94-true-false-true-true-true-false-2-47.6031-5741-5524-1.0000-hanning.ark delete mode 100644 test/assets/kaldi/mfcc-3.4022-1.2172-0.8750-0.3750-7737-false-612-5-0.35-true-true-true-false-false-false-2-65.1166-6852-5820-1.0000-blackman.ark delete mode 100644 test/assets/kaldi/mfcc-3.4130-2.1158-1.1250-0.2500-5107-false-1362-7-0.73-true-true-true-false-true-false-7-7.0295-4988-4931-1.0000-povey.ark delete mode 100644 test/assets/kaldi/mfcc-3.4339-2.6197-1.1250-0.1875-3341-true-1275-7-0.41-true-false-true-false-true-true-2-76.6062-3005-1680-1.0000-rectangular.ark delete mode 100644 test/assets/kaldi/mfcc-3.4369-3.9198-0.9375-0.1250-6218-true-904-5-0.47-true-true-true-true-false-false-5-92.8036-4870-1901-1.0000-blackman.ark delete mode 100644 test/assets/kaldi/mfcc-3.4557-1.5553-0.7500-0.3750-6642-true-1530-4-0.72-false-true-false-false-false-true-2-28.8828-4490-2980-1.0000-hamming.ark delete mode 100644 test/assets/kaldi/mfcc-3.4753-4.7166-0.7500-0.3125-7637-true-4992-4-0.92-true-false-true-true-false-true-3-2.5456-6925-5486-1.0000-hamming.ark delete mode 100644 test/assets/kaldi/mfcc-3.5134-2.0285-0.6250-0.1875-5229-false-595-4-0.65-true-true-true-true-false-false-3-30.6069-5090-3467-1.0000-hamming.ark delete mode 100644 test/assets/kaldi/mfcc-3.5212-3.8251-0.8750-0.3125-4092-true-545-5-0.09-false-true-true-false-true-false-2-2.9422-1634-1000-1.0000-hanning.ark delete mode 100644 test/assets/kaldi/mfcc-3.5261-2.0251-0.8750-0.6250-7926-false-3916-7-0.45-false-false-true-true-true-false-2-48.8818-7889-7527-1.0000-hanning.ark delete mode 100644 test/assets/kaldi/mfcc-3.5390-1.6456-1.1250-0.1875-5425-true-2326-7-0.72-false-false-true-false-true-false-4-39.4555-4290-2715-1.0000-povey.ark delete mode 100644 test/assets/kaldi/mfcc-3.5643-2.2424-1.1875-0.8750-2140-true-59-4-0.98-true-true-true-false-false-false-2-36.7118-1463-1358-1.0000-hanning.ark delete mode 100644 test/assets/kaldi/mfcc-3.5959-4.8866-1.1250-1.0625-5150-false-3697-4-0.46-true-true-true-false-true-true-3-74.0966-4277-3777-1.0000-rectangular.ark delete mode 100644 test/assets/kaldi/mfcc-3.6480-4.7888-0.8750-0.1250-6969-true-1494-7-0.57-true-true-true-false-true-false-7-1.1255-4890-3923-1.0000-blackman.ark delete mode 100644 test/assets/kaldi/mfcc-3.7223-3.4282-1.0000-0.1250-6601-true-1923-6-0.05-false-true-true-false-false-true-4-19.2839-6596-6594-1.0000-hanning.ark delete mode 100644 test/assets/kaldi/mfcc-3.7376-0.2093-1.1875-0.7500-7830-true-4448-5-0.27-true-false-true-false-false-true-5-5.5865-5459-5056-1.0000-blackman.ark delete mode 100644 test/assets/kaldi/mfcc-3.7750-0.8364-0.7500-0.3750-4995-true-1191-4-0.47-false-true-true-true-true-false-2-32.2463-4992-4951-1.0000-hamming.ark delete mode 100644 test/assets/kaldi/mfcc-3.8120-0.4393-0.7500-1.0625-5917-false-1272-4-0.97-false-false-false-false-true-true-3-91.4723-3532-3056-1.0000-povey.ark delete mode 100644 test/assets/kaldi/mfcc-3.8613-4.6574-1.1250-1.0000-3399-true-1576-5-0.71-true-false-true-false-false-true-3-29.1497-2440-1852-1.0000-blackman.ark delete mode 100644 test/assets/kaldi/mfcc-3.8727-2.0972-0.7500-0.5000-7946-true-911-7-0.14-false-true-false-true-true-false-3-17.4711-5295-4742-0.6284-hanning.ark delete mode 100644 test/assets/kaldi/mfcc-3.9117-4.6803-0.5625-0.6250-5009-false-2542-4-0.25-true-true-true-false-false-false-4-65.8362-4734-3050-1.0000-povey.ark delete mode 100644 test/assets/kaldi/mfcc-4.0839-2.1503-0.6875-0.3750-4291-false-790-4-0.07-false-false-true-true-false-true-3-85.2464-3982-3760-1.0000-hamming.ark delete mode 100644 test/assets/kaldi/mfcc-4.0943-2.5765-1.1250-0.3125-1241-true-331-4-0.76-true-true-true-false-true-true-3-84.6108-655-525-1.0000-hamming.ark delete mode 100644 test/assets/kaldi/mfcc-4.1414-4.1878-0.8750-0.2500-7231-false-2925-6-0.36-true-false-true-false-false-false-6-88.1580-5517-3249-1.0000-povey.ark delete mode 100644 test/assets/kaldi/mfcc-4.1851-3.5211-1.1250-0.8750-4768-false-562-4-0.05-true-true-true-true-false-false-2-36.9610-1982-741-1.0000-povey.ark delete mode 100644 test/assets/kaldi/mfcc-4.2197-3.7252-0.9375-0.8125-7453-true-1561-4-0.06-false-false-true-true-true-false-2-44.7800-6612-4074-1.0000-blackman.ark delete mode 100644 test/assets/kaldi/mfcc-4.2736-4.9552-0.7500-1.0000-5145-false-1705-4-0.33-false-false-false-true-false-false-4-70.9332-4857-2223-1.0000-blackman.ark delete mode 100644 test/assets/kaldi/mfcc-4.2787-1.6289-1.0625-0.8750-7792-true-5085-7-0.54-false-true-true-true-false-true-7-86.3861-7554-7506-1.0000-rectangular.ark delete mode 100644 test/assets/kaldi/mfcc-4.3762-4.7209-0.9375-0.0625-5564-true-712-4-0.74-false-false-true-true-true-true-2-39.2887-4353-3521-1.0000-rectangular.ark delete mode 100644 test/assets/kaldi/mfcc-4.4229-0.4222-1.0625-1.1875-7822-true-4837-5-0.04-true-false-true-true-true-false-5-36.9181-7261-5703-1.0000-blackman.ark delete mode 100644 test/assets/kaldi/mfcc-4.4663-3.5767-1.1250-1.1250-5844-false-799-7-0.37-false-false-true-true-true-false-4-34.2098-4554-1148-1.0000-hamming.ark delete mode 100644 test/assets/kaldi/mfcc-4.5300-3.1492-1.0625-0.3750-7706-false-3813-6-0.74-false-false-true-false-true-false-2-71.8337-7672-5265-1.0000-povey.ark delete mode 100644 test/assets/kaldi/mfcc-4.5474-0.7883-0.5625-1.0000-7283-false-2418-4-0.68-true-true-true-false-true-true-4-70.0635-7277-7265-1.0000-hamming.ark delete mode 100644 test/assets/kaldi/mfcc-4.5474-3.1023-0.7500-0.4375-7554-true-2566-6-0.31-false-false-false-false-false-false-5-76.9780-7368-7310-1.0000-hanning.ark delete mode 100644 test/assets/kaldi/mfcc-4.5663-1.1270-1.1250-0.8125-6069-true-167-8-0.68-false-false-true-false-false-true-6-1.6240-2148-461-1.0000-rectangular.ark delete mode 100644 test/assets/kaldi/mfcc-4.5896-2.7617-1.0625-0.8125-3851-true-1115-4-0.03-true-false-true-true-false-false-4-49.7637-2897-2701-1.0000-hanning.ark delete mode 100644 test/assets/kaldi/mfcc-4.6128-0.1203-1.1875-0.9375-6901-false-3577-6-0.25-false-false-true-false-true-false-3-70.5509-5962-4190-1.0000-rectangular.ark delete mode 100644 test/assets/kaldi/mfcc-4.6262-4.1656-1.1875-0.8125-6147-false-1684-6-0.58-true-false-true-true-true-true-5-54.2056-5259-2363-1.0000-rectangular.ark delete mode 100644 test/assets/kaldi/mfcc-4.6741-4.3867-1.1250-1.1250-6273-false-2481-4-0.15-true-false-false-true-false-false-4-75.6122-3701-2992-1.0000-hamming.ark delete mode 100644 test/assets/kaldi/mfcc-4.6765-1.2644-1.1250-0.7500-5204-false-276-4-0.04-true-false-false-true-true-false-3-96.1160-5148-2541-1.0000-hamming.ark delete mode 100644 test/assets/kaldi/mfcc-4.7119-3.1322-1.0625-0.0625-7985-false-4247-5-0.13-false-false-true-false-false-false-5-6.6500-7634-6587-1.0000-hanning.ark delete mode 100644 test/assets/kaldi/mfcc-4.7216-2.4818-0.8125-0.3750-6723-true-2352-6-0.14-false-false-true-false-true-false-3-32.0303-5598-2579-1.0000-hanning.ark delete mode 100644 test/assets/kaldi/mfcc-4.7919-2.6435-0.6250-0.5000-7971-false-1812-4-0.65-false-false-false-false-true-false-4-27.7648-7735-7419-1.0000-povey.ark delete mode 100644 test/assets/kaldi/mfcc-4.8140-0.4680-1.0625-0.6875-5252-true-569-6-0.85-true-false-true-true-false-false-6-56.4490-4397-4332-1.0000-hamming.ark delete mode 100644 test/assets/kaldi/mfcc-4.9500-4.5916-1.1250-1.0625-5044-true-617-8-0.89-false-false-false-false-true-true-8-23.3238-2732-2677-1.0000-hanning.ark delete mode 100644 test/assets/kaldi/mfcc-4.9663-4.7867-1.1875-0.5000-2424-false-350-4-0.39-false-false-true-false-true-true-2-59.4319-1202-1063-1.0000-hamming.ark delete mode 100644 test/assets/kaldi/spec-0.0016-0-4.6680-0.6250-0.2500-0.82-false-false-false-false-false-povey.ark delete mode 100644 test/assets/kaldi/spec-0.0121-0-4.9643-0.8750-0.1875-0.98-false-false-false-true-false-rectangular.ark delete mode 100644 test/assets/kaldi/spec-0.0378-0-3.7770-0.5000-0.6250-0.76-false-true-true-true-false-blackman.ark delete mode 100644 test/assets/kaldi/spec-0.0545-0-0.0732-1.0000-0.7500-0.81-false-true-true-true-true-hanning.ark delete mode 100644 test/assets/kaldi/spec-0.1005-0-0.3739-0.5625-0.6250-0.19-false-false-true-true-false-blackman.ark delete mode 100644 test/assets/kaldi/spec-0.1088-0-0.6933-0.5000-0.7500-0.51-true-true-false-true-false-povey.ark delete mode 100644 test/assets/kaldi/spec-0.1777-0-3.8992-1.0000-0.3125-0.96-true-false-false-true-false-blackman.ark delete mode 100644 test/assets/kaldi/spec-0.2043-0-1.9538-0.5000-0.3750-0.96-true-false-true-false-true-povey.ark delete mode 100644 test/assets/kaldi/spec-0.2384-0-0.3080-0.3750-0.2500-0.98-true-false-false-false-true-povey.ark delete mode 100644 test/assets/kaldi/spec-0.2669-0-2.4329-0.6250-1.1875-0.18-false-true-false-true-false-blackman.ark delete mode 100644 test/assets/kaldi/spec-0.3067-0-2.7461-0.3750-0.1250-0.52-true-false-false-true-true-hamming.ark delete mode 100644 test/assets/kaldi/spec-0.3340-0-0.5962-0.2500-0.5625-0.38-false-false-true-false-true-hamming.ark delete mode 100644 test/assets/kaldi/spec-0.4268-0-2.4431-0.5625-0.0625-0.95-true-true-true-true-false-hamming.ark delete mode 100644 test/assets/kaldi/spec-0.4774-0-0.6982-1.1250-1.1250-0.27-false-true-false-true-true-povey.ark delete mode 100644 test/assets/kaldi/spec-0.4828-0-2.6861-0.6875-0.3750-0.15-true-false-true-false-true-povey.ark delete mode 100644 test/assets/kaldi/spec-0.4992-0-3.7665-0.4375-1.1250-0.42-false-false-true-false-true-rectangular.ark delete mode 100644 test/assets/kaldi/spec-0.5440-0-1.6641-0.9375-0.8750-0.13-true-true-true-true-true-rectangular.ark delete mode 100644 test/assets/kaldi/spec-0.5785-0-2.8162-1.1250-1.0625-0.17-false-false-false-true-false-blackman.ark delete mode 100644 test/assets/kaldi/spec-0.7797-0-2.5119-0.6250-0.5000-0.69-true-false-false-false-true-povey.ark delete mode 100644 test/assets/kaldi/spec-0.8072-0-4.0404-0.5000-1.1875-0.74-false-false-false-true-true-hamming.ark delete mode 100644 test/assets/kaldi/spec-0.8418-0-4.1771-0.3125-0.2500-0.48-false-false-true-true-false-hanning.ark delete mode 100644 test/assets/kaldi/spec-0.8431-0-0.0728-0.7500-0.8125-0.10-true-false-true-false-false-povey.ark delete mode 100644 test/assets/kaldi/spec-0.8850-0-3.9292-0.3750-0.7500-0.27-true-false-false-true-false-blackman.ark delete mode 100644 test/assets/kaldi/spec-0.9625-0-2.5481-0.6875-1.0000-0.06-false-true-true-true-false-blackman.ark delete mode 100644 test/assets/kaldi/spec-0.9826-0-0.7377-0.3750-0.6875-0.70-false-false-true-false-true-rectangular.ark delete mode 100644 test/assets/kaldi/spec-0.9854-0-3.8819-0.2500-1.0000-0.54-true-false-false-false-true-povey.ark delete mode 100644 test/assets/kaldi/spec-0.9864-0-3.6583-1.0625-0.6250-0.23-false-false-true-false-true-hamming.ark delete mode 100644 test/assets/kaldi/spec-1.0303-0-4.4583-0.3750-0.8750-0.39-false-true-false-true-false-blackman.ark delete mode 100644 test/assets/kaldi/spec-1.0743-0-0.4642-1.1250-0.6250-0.39-true-true-true-true-true-hanning.ark delete mode 100644 test/assets/kaldi/spec-1.0788-0-1.4420-0.1875-0.3125-0.53-true-true-true-true-true-hanning.ark delete mode 100644 test/assets/kaldi/spec-1.0802-0-4.5077-0.8750-0.1250-0.54-true-false-false-false-true-povey.ark delete mode 100644 test/assets/kaldi/spec-1.0816-0-0.2050-0.1875-0.6875-0.02-false-false-true-true-false-hamming.ark delete mode 100644 test/assets/kaldi/spec-1.1385-0-4.7380-0.6250-0.3125-0.23-true-false-false-false-false-hanning.ark delete mode 100644 test/assets/kaldi/spec-1.1575-0-3.0941-0.5625-0.1250-1.00-true-true-true-true-true-povey.ark delete mode 100644 test/assets/kaldi/spec-1.3142-0-4.8914-0.8750-0.1875-0.34-true-true-false-false-false-blackman.ark delete mode 100644 test/assets/kaldi/spec-1.3189-0-3.6830-1.1250-1.1250-0.88-false-false-false-false-true-hamming.ark delete mode 100644 test/assets/kaldi/spec-1.3235-0-3.8538-0.2500-1.0625-0.07-false-false-true-false-true-blackman.ark delete mode 100644 test/assets/kaldi/spec-1.3389-0-1.6152-0.3750-0.5000-0.21-false-false-false-true-false-blackman.ark delete mode 100644 test/assets/kaldi/spec-1.3612-0-2.9585-0.8750-0.0625-0.66-false-false-true-true-true-blackman.ark delete mode 100644 test/assets/kaldi/spec-1.3887-0-3.3198-0.3750-0.1250-0.14-false-false-true-false-false-hanning.ark delete mode 100644 test/assets/kaldi/spec-1.4127-0-2.6264-0.8750-0.3750-0.69-false-false-true-false-false-povey.ark delete mode 100644 test/assets/kaldi/spec-1.5178-0-2.8631-1.0000-0.8125-0.95-true-true-true-true-false-blackman.ark delete mode 100644 test/assets/kaldi/spec-1.5403-0-0.0133-1.1875-0.2500-0.59-true-false-true-false-false-blackman.ark delete mode 100644 test/assets/kaldi/spec-1.5551-0-3.0664-0.7500-0.3750-0.18-false-true-false-false-true-rectangular.ark delete mode 100644 test/assets/kaldi/spec-1.5669-0-0.5190-0.8750-0.2500-0.56-true-true-false-false-true-blackman.ark delete mode 100644 test/assets/kaldi/spec-1.5754-0-0.9540-1.0000-0.9375-0.20-false-false-true-true-true-rectangular.ark delete mode 100644 test/assets/kaldi/spec-1.5959-0-0.9033-0.7500-1.0000-0.14-true-true-true-true-false-hanning.ark delete mode 100644 test/assets/kaldi/spec-1.6923-0-3.5626-0.6875-1.0625-0.27-true-false-true-false-false-rectangular.ark delete mode 100644 test/assets/kaldi/spec-1.6972-0-1.0863-1.1875-0.8750-0.86-true-true-true-true-false-rectangular.ark delete mode 100644 test/assets/kaldi/spec-1.7440-0-0.5308-0.5000-0.1250-0.33-true-true-false-false-false-hamming.ark delete mode 100644 test/assets/kaldi/spec-1.7642-0-0.4833-0.2500-0.8125-0.94-false-true-false-true-false-blackman.ark delete mode 100644 test/assets/kaldi/spec-1.8072-0-0.8085-0.5000-0.2500-0.96-false-true-true-false-false-hanning.ark delete mode 100644 test/assets/kaldi/spec-1.8468-0-2.0534-1.0000-0.1875-0.35-false-true-true-false-true-rectangular.ark delete mode 100644 test/assets/kaldi/spec-1.8836-0-4.5145-0.8750-1.0625-0.40-false-false-true-true-true-hanning.ark delete mode 100644 test/assets/kaldi/spec-1.8946-0-4.1442-0.3125-0.8750-0.73-true-true-true-true-true-rectangular.ark delete mode 100644 test/assets/kaldi/spec-1.8988-0-3.0931-1.0625-0.3125-0.35-true-true-true-true-true-hanning.ark delete mode 100644 test/assets/kaldi/spec-1.9093-0-2.4939-0.7500-0.5000-0.47-true-false-true-false-true-blackman.ark delete mode 100644 test/assets/kaldi/spec-1.9501-0-4.3519-0.4375-0.2500-0.61-false-false-true-false-true-hanning.ark delete mode 100644 test/assets/kaldi/spec-2.0137-0-3.1007-0.6250-1.0625-0.67-true-false-true-true-true-rectangular.ark delete mode 100644 test/assets/kaldi/spec-2.0175-0-2.9099-1.0000-0.5625-0.28-true-false-true-false-false-blackman.ark delete mode 100644 test/assets/kaldi/spec-2.1114-0-4.5618-0.2500-0.8750-0.61-true-true-false-false-false-povey.ark delete mode 100644 test/assets/kaldi/spec-2.1472-0-0.2000-1.1250-0.8750-0.58-true-true-false-true-true-hamming.ark delete mode 100644 test/assets/kaldi/spec-2.1947-0-1.8065-0.8750-0.7500-0.45-false-true-false-false-false-povey.ark delete mode 100644 test/assets/kaldi/spec-2.2457-0-1.7040-0.7500-0.5625-0.98-true-false-false-false-true-hamming.ark delete mode 100644 test/assets/kaldi/spec-2.2893-0-1.0286-0.2500-0.5000-0.80-true-false-true-false-false-hanning.ark delete mode 100644 test/assets/kaldi/spec-2.3371-0-4.4192-0.8125-0.6250-0.30-true-false-true-true-true-rectangular.ark delete mode 100644 test/assets/kaldi/spec-2.3789-0-3.0234-0.1875-0.3750-0.54-true-false-true-true-true-hamming.ark delete mode 100644 test/assets/kaldi/spec-2.3831-0-4.8325-0.2500-1.1250-0.34-true-true-true-false-true-povey.ark delete mode 100644 test/assets/kaldi/spec-2.4230-0-0.6363-0.8750-0.3125-0.77-true-true-true-false-false-hanning.ark delete mode 100644 test/assets/kaldi/spec-2.4378-0-1.4617-0.9375-0.3750-0.53-true-false-true-true-false-rectangular.ark delete mode 100644 test/assets/kaldi/spec-2.4454-0-1.9360-1.0000-0.9375-0.66-false-true-false-false-false-rectangular.ark delete mode 100644 test/assets/kaldi/spec-2.4480-0-3.8782-0.5625-1.1250-0.10-false-true-true-false-true-rectangular.ark delete mode 100644 test/assets/kaldi/spec-2.5164-0-2.7455-0.8750-0.9375-0.55-false-true-false-false-false-hanning.ark delete mode 100644 test/assets/kaldi/spec-2.5316-0-2.3286-0.7500-0.7500-0.61-false-false-false-false-true-rectangular.ark delete mode 100644 test/assets/kaldi/spec-2.5487-0-3.8457-1.1875-0.9375-0.63-true-true-true-true-false-hanning.ark delete mode 100644 test/assets/kaldi/spec-2.6121-0-4.3165-0.6875-1.1875-0.19-false-true-true-true-false-rectangular.ark delete mode 100644 test/assets/kaldi/spec-2.6768-0-2.4181-1.1250-0.6875-0.14-true-true-false-false-true-hamming.ark delete mode 100644 test/assets/kaldi/spec-2.6988-0-2.3417-1.0000-0.6875-0.38-false-false-true-false-false-rectangular.ark delete mode 100644 test/assets/kaldi/spec-2.7457-0-1.3662-0.2500-0.8750-0.74-false-true-false-true-true-blackman.ark delete mode 100644 test/assets/kaldi/spec-2.8577-0-4.1431-0.3750-1.0000-1.00-false-true-true-false-false-hamming.ark delete mode 100644 test/assets/kaldi/spec-2.8693-0-4.3801-0.7500-1.0000-0.95-true-true-true-true-true-rectangular.ark delete mode 100644 test/assets/kaldi/spec-2.8888-0-0.4078-0.3125-0.6250-0.25-false-true-true-true-false-hanning.ark delete mode 100644 test/assets/kaldi/spec-2.9074-0-1.6849-1.1250-0.6250-0.79-false-true-true-false-false-blackman.ark delete mode 100644 test/assets/kaldi/spec-2.9303-0-3.5172-0.5000-0.5000-0.04-true-false-true-true-true-rectangular.ark delete mode 100644 test/assets/kaldi/spec-3.0700-0-3.5254-0.7500-0.8750-0.96-false-true-false-true-false-povey.ark delete mode 100644 test/assets/kaldi/spec-3.1297-0-0.3513-0.4375-0.3125-0.20-true-true-true-true-false-povey.ark delete mode 100644 test/assets/kaldi/spec-3.2080-0-1.8656-0.3125-0.4375-0.55-false-false-true-true-true-hanning.ark delete mode 100644 test/assets/kaldi/spec-3.2523-0-3.5376-0.3125-0.2500-0.46-false-false-true-true-true-rectangular.ark delete mode 100644 test/assets/kaldi/spec-3.3896-0-0.4666-1.1250-0.2500-0.05-false-true-false-false-false-rectangular.ark delete mode 100644 test/assets/kaldi/spec-3.5370-0-1.7032-0.3750-0.8750-0.17-false-true-true-false-true-hamming.ark delete mode 100644 test/assets/kaldi/spec-3.5378-0-3.6594-0.2500-0.6250-0.54-true-true-true-true-true-rectangular.ark delete mode 100644 test/assets/kaldi/spec-3.5847-0-3.6357-1.0000-0.3125-0.79-false-false-false-true-false-povey.ark delete mode 100644 test/assets/kaldi/spec-3.6057-0-1.6902-1.0625-0.6875-0.65-false-true-true-true-false-blackman.ark delete mode 100644 test/assets/kaldi/spec-3.6308-0-1.1407-0.3125-0.0625-0.17-false-true-true-true-true-rectangular.ark delete mode 100644 test/assets/kaldi/spec-3.6498-0-0.2005-0.9375-1.1250-0.37-false-true-true-false-true-rectangular.ark delete mode 100644 test/assets/kaldi/spec-3.6648-0-4.6742-0.6250-1.1875-0.88-false-true-false-true-true-blackman.ark delete mode 100644 test/assets/kaldi/spec-3.6701-0-3.7451-0.8125-0.2500-0.19-true-false-true-true-true-blackman.ark delete mode 100644 test/assets/kaldi/spec-3.7232-0-0.4912-0.3750-0.8750-0.34-false-true-false-false-true-rectangular.ark delete mode 100644 test/assets/kaldi/spec-3.7605-0-1.6813-0.2500-0.5625-0.27-true-true-true-false-false-rectangular.ark delete mode 100644 test/assets/kaldi/spec-3.7632-0-3.7271-0.6875-0.3125-0.86-true-true-true-true-true-hamming.ark delete mode 100644 test/assets/kaldi/spec-3.7759-0-1.7002-1.0625-0.6875-0.42-false-false-true-true-true-hamming.ark delete mode 100644 test/assets/kaldi/spec-3.7921-0-3.4087-0.2500-1.0000-0.54-true-true-true-false-false-blackman.ark delete mode 100644 test/assets/kaldi/spec-3.7954-0-3.5651-0.5000-0.8125-0.06-false-true-true-false-true-blackman.ark delete mode 100644 test/assets/kaldi/spec-3.7990-0-3.0026-0.6250-1.0000-0.82-false-true-false-true-true-hamming.ark delete mode 100644 test/assets/kaldi/spec-3.8659-0-1.7487-1.1875-0.3750-1.00-true-true-true-true-false-hanning.ark delete mode 100644 test/assets/kaldi/spec-3.9039-0-3.8315-0.3125-0.7500-0.55-false-true-true-false-true-hamming.ark delete mode 100644 test/assets/kaldi/spec-3.9510-0-0.3903-1.1250-1.0000-0.41-true-false-false-true-true-rectangular.ark delete mode 100644 test/assets/kaldi/spec-3.9659-0-3.8318-0.1875-0.3750-0.58-false-false-true-false-true-rectangular.ark delete mode 100644 test/assets/kaldi/spec-4.0045-0-3.0610-0.6250-1.0625-0.74-false-false-true-false-true-hanning.ark delete mode 100644 test/assets/kaldi/spec-4.0187-0-4.8148-0.3750-0.6875-0.68-true-true-false-false-false-hanning.ark delete mode 100644 test/assets/kaldi/spec-4.0320-0-2.2019-1.1250-0.2500-0.78-true-true-true-true-true-rectangular.ark delete mode 100644 test/assets/kaldi/spec-4.0468-0-0.5053-0.3125-0.1875-0.52-false-true-true-true-true-rectangular.ark delete mode 100644 test/assets/kaldi/spec-4.0627-0-4.1729-0.6250-1.1250-0.89-false-false-false-false-false-povey.ark delete mode 100644 test/assets/kaldi/spec-4.0736-0-0.9155-1.0625-0.5625-0.82-false-true-true-true-true-hamming.ark delete mode 100644 test/assets/kaldi/spec-4.1131-0-3.9204-0.5000-0.1250-0.39-false-true-true-false-false-hanning.ark delete mode 100644 test/assets/kaldi/spec-4.1816-0-1.6650-0.8125-0.3750-0.37-true-false-true-true-false-rectangular.ark delete mode 100644 test/assets/kaldi/spec-4.1897-0-1.2668-0.1875-0.6250-0.74-true-false-true-false-false-hamming.ark delete mode 100644 test/assets/kaldi/spec-4.2217-0-3.6775-0.3125-0.1250-0.01-true-false-true-false-false-hamming.ark delete mode 100644 test/assets/kaldi/spec-4.2785-0-0.7201-0.8125-0.8125-0.30-false-false-true-false-true-hanning.ark delete mode 100644 test/assets/kaldi/spec-4.3304-0-1.0538-0.8750-1.1250-0.92-true-false-true-false-false-povey.ark delete mode 100644 test/assets/kaldi/spec-4.3942-0-3.9813-0.7500-0.6875-0.27-false-true-true-true-true-blackman.ark delete mode 100644 test/assets/kaldi/spec-4.4432-0-2.0441-0.5000-0.6875-0.77-false-false-true-true-false-hanning.ark delete mode 100644 test/assets/kaldi/spec-4.4459-0-0.5135-0.2500-0.1875-0.29-false-false-true-false-true-hanning.ark delete mode 100644 test/assets/kaldi/spec-4.4807-0-3.5660-0.6250-0.1250-0.08-false-true-false-false-false-povey.ark delete mode 100644 test/assets/kaldi/spec-4.5486-0-1.3248-0.1875-1.1250-0.91-false-false-true-false-true-hanning.ark delete mode 100644 test/assets/kaldi/spec-4.5535-0-2.1772-0.4375-0.8750-0.21-true-false-true-true-true-hanning.ark delete mode 100644 test/assets/kaldi/spec-4.5835-0-0.3781-0.8750-0.8750-0.04-true-false-true-true-true-hamming.ark delete mode 100644 test/assets/kaldi/spec-4.5882-0-1.0111-0.3750-0.1875-0.78-false-true-false-false-true-blackman.ark delete mode 100644 test/assets/kaldi/spec-4.6297-0-2.4900-0.5000-0.2500-0.03-false-false-true-true-false-rectangular.ark delete mode 100644 test/assets/kaldi/spec-4.6749-0-4.8853-0.2500-0.2500-0.48-false-true-false-false-false-povey.ark delete mode 100644 test/assets/kaldi/spec-4.6971-0-1.3632-0.8750-0.9375-0.44-false-true-false-true-false-blackman.ark create mode 100644 test/assets/kaldi_test_spectrogram_args.json rename test/{test_functional.py => functional_cpu_test.py} (90%) create mode 100644 test/functional_cuda_test.py create mode 100644 test/functional_impl.py create mode 100644 test/test_backend.py delete mode 100644 torchaudio/_backend.py create mode 100644 torchaudio/_internal/__init__.py create mode 100644 torchaudio/_internal/misc_ops.py create mode 100644 torchaudio/_internal/module_utils.py delete mode 100644 torchaudio/_sox_backend.py create mode 100644 torchaudio/backend/__init__.py create mode 100644 torchaudio/backend/common.py create mode 100644 torchaudio/backend/no_backend.py rename torchaudio/{_soundfile_backend.py => backend/soundfile_backend.py} (67%) create mode 100644 torchaudio/backend/sox_backend.py create mode 100644 torchaudio/backend/utils.py delete mode 100644 torchaudio/common_utils.py create mode 100644 torchaudio/csrc/register.cpp create mode 100644 torchaudio/csrc/typedefs.cpp create mode 100644 torchaudio/csrc/typedefs.h create mode 100644 torchaudio/datasets/cmuarctic.py create mode 100644 torchaudio/extension/__init__.py create mode 100644 torchaudio/extension/extension.py create mode 100644 torchaudio/models/_wavernn.py create mode 100644 torchaudio/sox_effects/__init__.py rename torchaudio/{ => sox_effects}/sox_effects.py (71%) diff --git a/docs/source/datasets.rst b/docs/source/datasets.rst index 8ba05dc670..2f844293f6 100644 --- a/docs/source/datasets.rst +++ b/docs/source/datasets.rst @@ -25,6 +25,14 @@ All the datasets have almost similar API. They all have two common arguments: .. currentmodule:: torchaudio.datasets +CMUARCTIC +~~~~~~~~~ + +.. autoclass:: CMUARCTIC + :members: __getitem__ + :special-members: + + COMMONVOICE ~~~~~~~~~~~ diff --git a/test/README.md b/test/README.md index a6686603af..35a926c120 100644 --- a/test/README.md +++ b/test/README.md @@ -44,6 +44,16 @@ The following test modules are defined for corresponding `torchaudio` module/fun ## Adding test +The following is the current practice of torchaudio test suite. + +1. Unless the tests are related to I/O, use synthetic data. [`common_utils`](./common_utils.py) has some data generator functions. +1. When you add a new test case, use `common_utils.TorchaudioTestCase` as base class unless you are writing tests that are common to CPU / CUDA. + - Set class memeber `dtype`, `device` and `backend` for the desired behavior. + - If you do not set `backend` value in your test suite, then I/O functions will be unassigned and attempt to load/save file will fail. + - For `backend` value, in addition to available backends, you can also provide the value "default" and backend will be picked automatically based on availability. +1. If you are writing tests that should pass on diffrent dtype/devices, write a common class inheriting `common_utils.TestBaseMixin`, then inherit `common_utils.PytorchTestCase` and define class attributes (`dtype` / `device` / `backend`) there. See [Torchscript consistency test implementation](./torchscript_consistency_impl.py) and test definitions for [CPU](./torchscript_consistency_cpu_test.py) and [CUDA](./torchscript_consistency_cuda_test.py) devices. +1. For numerically comparing Tensors, use `assertEqual` method from `common_utils.PytorchTestCase` class. This method has a better support for a wide variety of Tensor types. + When you add a new feature(functional/transform), consider the following 1. When you add a new feature, please make it Torchscript-able and batch-consistent unless it degrades the performance. Please add the tests to see if the new feature meet these requirements. diff --git a/test/assets/ARCTIC/cmu_us_aew_arctic/etc/txt.done.data b/test/assets/ARCTIC/cmu_us_aew_arctic/etc/txt.done.data new file mode 100644 index 0000000000..b6a7aa90ba --- /dev/null +++ b/test/assets/ARCTIC/cmu_us_aew_arctic/etc/txt.done.data @@ -0,0 +1 @@ +( arctic_a0024 "This is the test text." ) diff --git a/test/assets/ARCTIC/cmu_us_aew_arctic/wav/arctic_a0024.wav b/test/assets/ARCTIC/cmu_us_aew_arctic/wav/arctic_a0024.wav new file mode 100644 index 0000000000000000000000000000000000000000..b95ce95776fafd3e3cbaf670153f8d73167dfab3 GIT binary patch literal 441078 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

CSAV+5*9;R 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

Cz3T@ze3!6w*(fHW_fV9=% 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 diff --git a/test/assets/kaldi/fbank-0.2512-0.2607-0.8750-0.8750-7380-true-4471-5-0.76-true-true-true-true-true-true-false-true-7138-5172-1.0000-hamming.ark b/test/assets/kaldi/fbank-0.2512-0.2607-0.8750-0.8750-7380-true-4471-5-0.76-true-true-true-true-true-true-false-true-7138-5172-1.0000-hamming.ark deleted file mode 100644 index 088b2337ddf515f9da058bf9cdb87acf1c445b90..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 45 ccmd0;jL%F_U~qEtRbXLcU|?Wj0}{9Z0E0LKHvj+t diff --git a/test/assets/kaldi/fbank-0.2834-1.7885-1.1875-0.9375-5385-false-2579-6-0.82-false-false-true-false-true-false-true-true-4782-4492-1.0000-povey.ark b/test/assets/kaldi/fbank-0.2834-1.7885-1.1875-0.9375-5385-false-2579-6-0.82-false-false-true-false-true-false-true-true-4782-4492-1.0000-povey.ark deleted file mode 100644 index 088b2337ddf515f9da058bf9cdb87acf1c445b90..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 45 ccmd0;jL%F_U~qEtRbXLcU|?Wj0}{9Z0E0LKHvj+t diff --git a/test/assets/kaldi/fbank-0.3188-1.6288-1.0000-0.5000-6258-true-2043-4-0.57-true-false-false-false-false-false-true-true-5274-3268-1.0000-hamming.ark b/test/assets/kaldi/fbank-0.3188-1.6288-1.0000-0.5000-6258-true-2043-4-0.57-true-false-false-false-false-false-true-true-5274-3268-1.0000-hamming.ark deleted file mode 100644 index 274f73c2a7f5502593a40c6b1697d323b7525e65..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 69 zcmd0;jL%F_U~qEtRbXLeU|?Wj0TQR@O>~sCn(8?DTC?M+&J;(LlF5!b%+noZzc)DM Y-O_cum)qgE(!9sf=WUZ?yj6oE0Mzmq*#H0l diff --git a/test/assets/kaldi/fbank-0.3637-4.7928-1.0000-0.5625-7671-false-2385-5-0.81-true-false-true-true-false-true-false-true-6881-4659-1.0000-rectangular.ark b/test/assets/kaldi/fbank-0.3637-4.7928-1.0000-0.5625-7671-false-2385-5-0.81-true-false-true-true-false-true-false-true-6881-4659-1.0000-rectangular.ark deleted file mode 100644 index 7377dc0360486a2498185de28cd275f2d7a485ed..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 45 zcmd0;jL%F_U~qEtRbXLcU|?Wj0}@6u^Bf-+O88A$w8N)kv9izY!?V0=!z{f41xXFc diff --git a/test/assets/kaldi/fbank-0.4702-2.6680-1.0000-1.0000-7231-true-1515-4-0.92-true-false-false-false-true-false-false-true-6506-2549-1.0000-hamming.ark b/test/assets/kaldi/fbank-0.4702-2.6680-1.0000-1.0000-7231-true-1515-4-0.92-true-false-false-false-true-false-false-true-6506-2549-1.0000-hamming.ark deleted file mode 100644 index 5c90e36332ecd0d82a77f708f326a6498410a9a1..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 37 ccmd0;jL%F_U~qEtRbXLcU|?Wj0TSo{0BKkQH2?qr diff --git a/test/assets/kaldi/fbank-0.5177-2.3803-0.8750-0.3750-5535-true-194-5-0.22-false-true-true-false-true-false-true-true-3979-1023-1.0000-hanning.ark b/test/assets/kaldi/fbank-0.5177-2.3803-0.8750-0.3750-5535-true-194-5-0.22-false-true-true-false-true-false-true-true-3979-1023-1.0000-hanning.ark deleted file mode 100644 index 50a38e47f3f7626d0c0abcf1f9d990f019ac2b75..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 81 zcmd0;jL%F_U~qEtRbXLeU|?Wj1riAdHrP1;F@xxNTLy(wdm6-;_bD*2><3|n-%Iu~ fEcj~85IfEGK)s$_0}wN0tk}b_p~r?{LA)&hw|N>0 diff --git a/test/assets/kaldi/fbank-0.5988-0.8014-1.1250-0.8750-3663-true-1941-6-0.59-false-false-true-false-true-false-false-false-3373-3354-1.0000-blackman.ark b/test/assets/kaldi/fbank-0.5988-0.8014-1.1250-0.8750-3663-true-1941-6-0.59-false-false-true-false-true-false-false-false-3373-3354-1.0000-blackman.ark deleted file mode 100644 index 088b2337ddf515f9da058bf9cdb87acf1c445b90..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 45 ccmd0;jL%F_U~qEtRbXLcU|?Wj0}{9Z0E0LKHvj+t diff --git a/test/assets/kaldi/fbank-0.6342-1.2603-1.0625-0.0625-6044-false-77-5-0.85-true-true-true-false-true-true-true-false-5918-4804-1.0000-blackman.ark b/test/assets/kaldi/fbank-0.6342-1.2603-1.0625-0.0625-6044-false-77-5-0.85-true-true-true-false-true-true-true-false-5918-4804-1.0000-blackman.ark deleted file mode 100644 index b104a28c7687c7d48247e6fde5e6bb9675691da8..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 501 zcmWNNUr19?9LK-Tu}r0HG$ktPLMy6=k{}t|{hfQMF=9}N!CJ6rfj$`ZAW2Y^yU-qN z3|z3lBE}+vNd;zPx}9_G@x|;PL_rxVT7}qCf5gh3YA>Is&%=k$>2t^XdNk~d9MqgX z08UpO2zo{0m$GxIRfc&az|1>diMMA2qMOKC{wCFHw_y%#WtL+}ptOZ!>b8!|chVmG zWmaj4EXOqgEm*<4OUIirt_H#kcY6qt>$t+#z7iR4{o($D^!(C&GUu z|1q@n3p|Ypv?U0?CpZpui@Bi&!?bTmbWaOwqCj}L7(#AFug$J!T~9XHR&-gweV+inCJ2Z!2n%I5|Z~@8=lK2~-y-@Xl|WW~0Q> zx?kJOk@XSwuB8#tZo_Vp*1d;>Kqtq%U+>tMVe!N^Tcuhh&QB8(QI0{MC@x%Qo}W@$ zkuL)2dQUAL!uT~BKIl7w3<9^19 z>)tc0&JrAoqqbPaSud#cVbAed=WD^A3puf!!q{{gto#RmWY diff --git a/test/assets/kaldi/fbank-0.6421-2.1404-0.7500-1.0625-6031-false-57-4-0.03-true-true-true-false-false-true-false-true-5417-1170-1.0000-povey.ark b/test/assets/kaldi/fbank-0.6421-2.1404-0.7500-1.0625-6031-false-57-4-0.03-true-true-true-false-false-true-false-true-5417-1170-1.0000-povey.ark deleted file mode 100644 index 279d7e5b94d50c8bde5360ceacc40811f59a01fc..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 41 vcmd0;jL%F_U~qEtRbXLcU|?Wj1rqt8GaNTa-1Is!E#AlSL%DCkB`se7*TxKK diff --git a/test/assets/kaldi/fbank-0.6740-1.3778-1.0000-0.8750-6623-true-2402-7-0.50-true-false-true-false-true-false-false-true-6491-6262-1.0000-hamming.ark b/test/assets/kaldi/fbank-0.6740-1.3778-1.0000-0.8750-6623-true-2402-7-0.50-true-false-true-false-true-false-false-true-6491-6262-1.0000-hamming.ark deleted file mode 100644 index 40397585c94eae6c4ef3d969c40c6b275d30aca2..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 49 ccmd0;jL%F_U~qEtRbXLcU|?Wj2NL)I0FX2TH~;_u diff --git a/test/assets/kaldi/fbank-0.7979-1.4223-1.1250-0.3125-2534-false-810-4-0.77-true-true-true-true-true-true-false-true-2494-2015-1.0000-hamming.ark b/test/assets/kaldi/fbank-0.7979-1.4223-1.1250-0.3125-2534-false-810-4-0.77-true-true-true-true-true-true-false-true-2494-2015-1.0000-hamming.ark deleted file mode 100644 index 2d2a4a0a3ac06ec14f9d4f1f4e834ab3c900878a..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 41 ccmd0;jL%F_U~qEtRbXLcU|?Wj1rpc*0Cq$JHUIzs diff --git a/test/assets/kaldi/fbank-0.8161-1.2937-0.9375-0.1250-5030-false-966-6-0.03-false-false-true-false-false-true-true-true-4652-2559-1.0000-hanning.ark b/test/assets/kaldi/fbank-0.8161-1.2937-0.9375-0.1250-5030-false-966-6-0.03-false-false-true-false-false-true-true-true-4652-2559-1.0000-hanning.ark deleted file mode 100644 index a1292e64d6b88466badc4dd00d891d1c5a906b31..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 301 zcmWN>KT85}0Dxf!NeUu|q(KX5iJ~QFsTSXYKrpDu0zn5MG^Gqf4U{1Kb69zL{?0Qa zl7gg$$l6>=u%U)p!h)!=4^T8T)iXT7nA_*I>ZWJstokmUPNz5g=ebZB`^^$}Dx|U% zmTLtXs|s7q1maX7dK1RblrjEjoD2z^29@_*8c{7$52fh)l(Cx2cpn5)S1Oa65Mkm8d!tVvPvtr5y5ZiM%Cn2qZK$ diff --git a/test/assets/kaldi/fbank-0.8997-2.8795-0.8750-0.5000-3383-false-259-4-0.08-true-true-true-true-false-true-true-false-1175-1038-1.0000-povey.ark b/test/assets/kaldi/fbank-0.8997-2.8795-0.8750-0.5000-3383-false-259-4-0.08-true-true-true-true-false-true-true-false-1175-1038-1.0000-povey.ark deleted file mode 100644 index b0a365fa3e779a023b79cc8756f7a502c0236954..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 41 vcmd0;jL%F_U~qEtRbXLcU|?Wj1rjH>%yc}c*6GkS>AyqL1s=y+-ja?0<7^C; diff --git a/test/assets/kaldi/fbank-0.9113-0.9909-0.6875-0.3750-7562-true-3978-4-0.03-false-true-true-false-false-false-true-true-6483-5671-1.0000-hamming.ark b/test/assets/kaldi/fbank-0.9113-0.9909-0.6875-0.3750-7562-true-3978-4-0.03-false-true-true-false-false-false-true-true-6483-5671-1.0000-hamming.ark deleted file mode 100644 index 9e937a29e720ed416382cabab7ca809ba46427f5..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 69 zcmd0;jL%F_U~qEtRbXLeU|?Wj0TLDLxsC_CG9B04Fn3%pq2l->A;&R6GRaY5BfF!l Yy{seO=N!jhT^WvdYt0-#@j5sH0E!(ISO5S3 diff --git a/test/assets/kaldi/fbank-0.9312-3.3768-0.8125-1.1250-5824-false-1366-6-0.28-true-true-true-false-false-false-true-true-3917-1620-1.0000-hanning.ark b/test/assets/kaldi/fbank-0.9312-3.3768-0.8125-1.1250-5824-false-1366-6-0.28-true-true-true-false-false-false-true-true-3917-1620-1.0000-hanning.ark deleted file mode 100644 index 89e1ba093c72c938bef6f68360ad295dd75fefbf..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 45 zcmd0;jL%F_U~qEtRbXLcU|?Wj0}|WX`W?d$O?LddcA}%T@nlDa)7_5U=^EV6Q diff --git a/test/assets/kaldi/fbank-0.9631-3.3222-1.0000-0.5000-7662-true-1833-6-0.71-false-true-false-true-true-false-true-true-6204-5887-1.0000-rectangular.ark b/test/assets/kaldi/fbank-0.9631-3.3222-1.0000-0.5000-7662-true-1833-6-0.71-false-true-false-true-true-false-true-true-6204-5887-1.0000-rectangular.ark deleted file mode 100644 index 088b2337ddf515f9da058bf9cdb87acf1c445b90..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 45 ccmd0;jL%F_U~qEtRbXLcU|?Wj0}{9Z0E0LKHvj+t diff --git a/test/assets/kaldi/fbank-0.9820-1.6680-0.7500-0.1875-6788-false-1968-4-0.14-false-true-true-false-false-true-true-false-2114-2024-1.0000-blackman.ark b/test/assets/kaldi/fbank-0.9820-1.6680-0.7500-0.1875-6788-false-1968-4-0.14-false-true-true-false-false-true-true-false-2114-2024-1.0000-blackman.ark deleted file mode 100644 index a0c7aec2f4ec64aeb1890ed335b18baf2b05c744..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 161 zcmd0;jL%F_U~qEtRbXLfU|?Wj1rnYUXE-XD3pqM8i8@YgXLo!M$L}b3d72~ZE)mD3 zqmqu=+qfNHOyzRqsh#e4YLlqr{*O|QJ7)1ZKJVgj^sJli=&(i9aoc+-$Jh>DN3#wd z$E)?z9p7vfb=(RR`&bVYYv*yCb9S0zZM=x1fuW?MaU7SUqz;#(i`ooFKM?`P3Hl}N80QMEbz+_!SP>f+j1%V`h diff --git a/test/assets/kaldi/fbank-1.0269-0.3681-1.1250-0.5625-4897-true-543-4-0.57-false-true-true-true-true-false-false-false-1226-960-1.0000-blackman.ark b/test/assets/kaldi/fbank-1.0269-0.3681-1.1250-0.5625-4897-true-543-4-0.57-false-true-true-true-true-false-false-false-1226-960-1.0000-blackman.ark deleted file mode 100644 index 5c90e36332ecd0d82a77f708f326a6498410a9a1..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 37 ccmd0;jL%F_U~qEtRbXLcU|?Wj0TSo{0BKkQH2?qr diff --git a/test/assets/kaldi/fbank-1.0298-2.2490-1.1250-0.2500-2031-true-257-5-0.65-false-true-true-false-true-false-false-true-1731-1582-1.0000-blackman.ark b/test/assets/kaldi/fbank-1.0298-2.2490-1.1250-0.2500-2031-true-257-5-0.65-false-true-true-false-true-false-false-true-1731-1582-1.0000-blackman.ark deleted file mode 100644 index 2ebef62a85b7268f5bdf3d4466a9f9d4618e4a76..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 121 zcmV-<0EYi{aO?z3B{?ZgIA$}7 diff --git a/test/assets/kaldi/fbank-1.2222-0.0582-1.1875-0.8125-6633-false-1117-8-0.96-false-true-true-true-false-false-true-false-4191-3264-1.0000-blackman.ark b/test/assets/kaldi/fbank-1.2222-0.0582-1.1875-0.8125-6633-false-1117-8-0.96-false-true-true-true-false-false-true-false-4191-3264-1.0000-blackman.ark deleted file mode 100644 index b344a5ca56f99a2e78dc95fcf06cb51a2e2f5a80..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 53 zcmd0;jL%F_U~qEtRbXLcU|?Y301{1KZ#rx$ H6@w!HVz3Sb diff --git a/test/assets/kaldi/fbank-1.2251-0.4403-0.5625-0.6875-3192-false-599-4-0.75-true-false-true-false-false-false-false-true-3183-2975-1.0000-povey.ark b/test/assets/kaldi/fbank-1.2251-0.4403-0.5625-0.6875-3192-false-599-4-0.75-true-false-true-false-false-false-false-true-3183-2975-1.0000-povey.ark deleted file mode 100644 index 32b8b4016ba701ecfef0cfcd6ab32f9eb061c157..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 53 zcmd0;jL%F_U~qEtRbXLaU|?Wj0TLDmQhXSzTD^tYdVSW_r21^m-s5fm__o*cq$r=D H9kxCIasCkG diff --git a/test/assets/kaldi/fbank-1.2278-1.4848-0.6875-0.6250-5785-true-289-4-0.58-true-true-true-false-true-false-false-true-4062-3715-1.0000-hanning.ark b/test/assets/kaldi/fbank-1.2278-1.4848-0.6875-0.6250-5785-true-289-4-0.58-true-true-true-false-true-false-false-true-4062-3715-1.0000-hanning.ark deleted file mode 100644 index 9e29a09c096f1a854f06eda324d13ca7be86265e..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 53 zcmd0;jL%F_U~qEtRbXLaU|?Wj0TKyaey19QD^D?`2b^MHnsFkd%g+nQ_X6_0fP4=C DZqyF6 diff --git a/test/assets/kaldi/fbank-1.3199-1.1137-1.1250-0.6875-6702-true-390-6-0.54-true-false-false-true-true-false-true-false-4426-2811-1.0000-povey.ark b/test/assets/kaldi/fbank-1.3199-1.1137-1.1250-0.6875-6702-true-390-6-0.54-true-false-false-true-true-false-true-false-4426-2811-1.0000-povey.ark deleted file mode 100644 index 088b2337ddf515f9da058bf9cdb87acf1c445b90..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 45 ccmd0;jL%F_U~qEtRbXLcU|?Wj0}{9Z0E0LKHvj+t diff --git a/test/assets/kaldi/fbank-1.3325-2.6552-1.0000-1.0625-6444-true-759-4-0.67-false-true-true-false-true-false-false-false-6065-4599-1.0000-hamming.ark b/test/assets/kaldi/fbank-1.3325-2.6552-1.0000-1.0625-6444-true-759-4-0.67-false-true-true-false-true-false-false-false-6065-4599-1.0000-hamming.ark deleted file mode 100644 index 5c90e36332ecd0d82a77f708f326a6498410a9a1..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 37 ccmd0;jL%F_U~qEtRbXLcU|?Wj0TSo{0BKkQH2?qr diff --git a/test/assets/kaldi/fbank-1.3426-1.5712-1.1875-1.0000-7444-false-1986-6-0.46-true-false-true-true-true-false-true-true-4787-3163-1.0000-hanning.ark b/test/assets/kaldi/fbank-1.3426-1.5712-1.1875-1.0000-7444-false-1986-6-0.46-true-false-true-true-true-false-true-true-4787-3163-1.0000-hanning.ark deleted file mode 100644 index 088b2337ddf515f9da058bf9cdb87acf1c445b90..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 45 ccmd0;jL%F_U~qEtRbXLcU|?Wj0}{9Z0E0LKHvj+t diff --git a/test/assets/kaldi/fbank-1.4359-1.2709-1.0000-0.5625-7657-true-1017-5-0.93-true-false-true-true-false-false-false-true-4228-2903-1.0000-hanning.ark b/test/assets/kaldi/fbank-1.4359-1.2709-1.0000-0.5625-7657-true-1017-5-0.93-true-false-true-true-false-false-false-true-4228-2903-1.0000-hanning.ark deleted file mode 100644 index 81fb130b6b3a1e2145c0ff78cbce4837c8b8e668..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 41 vcmd0;jL%F_U~qEtRbXLcU|?Wj1rp1RyL{qTx%sY(srJ3Fw97krwSWfz)W!@1 diff --git a/test/assets/kaldi/fbank-1.4621-1.2891-0.8750-1.0625-6324-true-408-7-0.09-false-true-true-true-false-false-false-false-6163-5973-1.0000-povey.ark b/test/assets/kaldi/fbank-1.4621-1.2891-0.8750-1.0625-6324-true-408-7-0.09-false-true-true-true-false-false-false-false-6163-5973-1.0000-povey.ark deleted file mode 100644 index 7cc96c9bcd2fc1d44c2a796652c6c5a923b77a5d..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 49 zcmd0;jL%F_U~qEtRbXLcU|?Wj2NHsZZae!bDZ0MA%HcXQ+}}-ZshgWg*$>wOhW9Q2 DF=`HH diff --git a/test/assets/kaldi/fbank-1.4751-2.3567-1.1875-1.0000-7115-false-4236-5-0.65-true-false-true-true-true-true-true-false-6523-5708-1.0000-rectangular.ark b/test/assets/kaldi/fbank-1.4751-2.3567-1.1875-1.0000-7115-false-4236-5-0.65-true-false-true-true-true-true-true-false-6523-5708-1.0000-rectangular.ark deleted file mode 100644 index 088b2337ddf515f9da058bf9cdb87acf1c445b90..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 45 ccmd0;jL%F_U~qEtRbXLcU|?Wj0}{9Z0E0LKHvj+t diff --git a/test/assets/kaldi/fbank-1.4883-4.1237-0.7500-0.2500-5670-true-766-6-0.29-true-true-true-false-true-false-false-false-5479-4173-1.0000-povey.ark b/test/assets/kaldi/fbank-1.4883-4.1237-0.7500-0.2500-5670-true-766-6-0.29-true-true-true-false-true-false-false-false-5479-4173-1.0000-povey.ark deleted file mode 100644 index df600f0f07aa8467d62831b7f88c3f2751dbaecd..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 141 zcmV;80CN9rd0%N{AOJ!}O&|mX000041^@s6&{BCs0P9>rV5AE~xD*4#aP3RP@Y;97 zs61Z8z=PqzAdHT~AVBs*I2|WMFcbtsuu?+AfW(=>Kx9J0P`L6#7^x&gkTnEDh(|ue v!0K4S;2a6WfT8?DSe!3J(Aoq;5W=!VK%+TA;I8UJP`GczoVu69@JSWJ?xj3> diff --git a/test/assets/kaldi/fbank-1.4930-1.4719-1.1250-0.2500-7805-true-5052-4-0.90-true-true-false-true-false-true-false-false-7300-5299-1.0000-blackman.ark b/test/assets/kaldi/fbank-1.4930-1.4719-1.1250-0.2500-7805-true-5052-4-0.90-true-true-false-true-false-true-false-false-7300-5299-1.0000-blackman.ark deleted file mode 100644 index 34ebb0a68731af5e69295133eb7c44b7f334cc2f..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 41 vcmd0;jL%F_U~qEtRbXLcU|?Wj1ri_j&vw3PAMCs>p2IoPjMq6PX0{^$*xn07 diff --git a/test/assets/kaldi/fbank-1.5718-3.5447-0.6250-0.1875-6777-true-938-4-0.69-true-false-false-false-false-true-true-false-4540-3168-1.0000-blackman.ark b/test/assets/kaldi/fbank-1.5718-3.5447-0.6250-0.1875-6777-true-938-4-0.69-true-false-false-false-false-true-true-false-4540-3168-1.0000-blackman.ark deleted file mode 100644 index 3602cf8bcfd2733b8791dc948f862a691ced905f..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 161 zcmV;S0ABxXd0%N{AOJ!}O&|mZ000041poj5?~x`!AmI%`-Siqkn3Who#2uPJI$|P0 zIH?XnT7Mxy9l!=bWLKO)`q&{s9*Ye@^Wq;tq&y2j_w<%QyCNS!!8{H@q#q+eK->pG z>uQ@pGuR(NXLJlfn3W$v=gA8})7h3m>0cW`lSU0eRj(sK2WkgFnTec1ww@kAL=FW( Pce)Tk>6sZpR&bg@8_+pz diff --git a/test/assets/kaldi/fbank-1.5786-1.9016-1.1875-0.7500-5812-true-3000-4-0.14-false-false-true-false-false-true-true-false-4930-4316-1.0000-rectangular.ark b/test/assets/kaldi/fbank-1.5786-1.9016-1.1875-0.7500-5812-true-3000-4-0.14-false-false-true-false-false-true-true-false-4930-4316-1.0000-rectangular.ark deleted file mode 100644 index f40c7b38ac8f70b371f52403263bdeb14567cad8..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 61 zcmd0;jL%F_U~qEtRbXLaU|?Wj1rilUxf~zW|8=Oi$L(0Nj@dECYo24RfwW_VHm~Em QPaKYgb2uEIb-BGRd!{i^<>d+XP=h^Z7mi DETs+k diff --git a/test/assets/kaldi/fbank-1.6312-2.6556-0.6250-0.4375-5589-false-1049-5-0.80-false-false-false-true-false-false-false-false-3816-1550-1.0000-rectangular.ark b/test/assets/kaldi/fbank-1.6312-2.6556-0.6250-0.4375-5589-false-1049-5-0.80-false-false-false-true-false-false-false-false-3816-1550-1.0000-rectangular.ark deleted file mode 100644 index d9737a90c94e611a8b67e18bb6e6d2aa20d410cc..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 61 zcmd0;jL%F_U~qEtRbXLaU|?Wj1rp~e( DPOlGn diff --git a/test/assets/kaldi/fbank-2.0479-1.4296-1.0625-0.6875-7818-true-1628-8-0.27-true-true-true-true-false-true-false-true-7749-7478-1.0000-blackman.ark b/test/assets/kaldi/fbank-2.0479-1.4296-1.0625-0.6875-7818-true-1628-8-0.27-true-true-true-true-false-true-false-true-7749-7478-1.0000-blackman.ark deleted file mode 100644 index b39ca69f14a5bbf5d68fcee07884ac8084188489..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 57 zcmd0;jL%F_U~qEtRbXLcU|?Y31QN-vn*Q3J*DfM%U4EOU`tMB*WVw}&6 LIA5=r0OX*&bf{j*)#jATHiihyaEnmPP-yMTg!6_>0C4C$ti+v3iUZS2C~h50{DxFa L;B=!)d{~Xlt?e%6 diff --git a/test/assets/kaldi/fbank-2.1098-2.1356-1.0625-0.9375-7825-true-408-4-0.37-true-true-true-true-true-true-false-false-5297-2747-1.0000-hamming.ark b/test/assets/kaldi/fbank-2.1098-2.1356-1.0625-0.9375-7825-true-408-4-0.37-true-true-true-true-true-true-false-false-5297-2747-1.0000-hamming.ark deleted file mode 100644 index 2d2a4a0a3ac06ec14f9d4f1f4e834ab3c900878a..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 41 ccmd0;jL%F_U~qEtRbXLcU|?Wj1rpc*0Cq$JHUIzs diff --git a/test/assets/kaldi/fbank-2.1463-0.3422-0.8125-0.5000-6892-true-65-4-0.47-false-false-true-true-true-true-false-true-4178-2891-1.0000-rectangular.ark b/test/assets/kaldi/fbank-2.1463-0.3422-0.8125-0.5000-6892-true-65-4-0.47-false-false-true-true-true-true-false-true-4178-2891-1.0000-rectangular.ark deleted file mode 100644 index 2d2a4a0a3ac06ec14f9d4f1f4e834ab3c900878a..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 41 ccmd0;jL%F_U~qEtRbXLcU|?Wj1rpc*0Cq$JHUIzs diff --git a/test/assets/kaldi/fbank-2.1768-3.7820-0.7500-0.8125-7063-false-2703-4-0.99-true-false-false-false-true-false-false-true-6819-3764-1.0000-hanning.ark b/test/assets/kaldi/fbank-2.1768-3.7820-0.7500-0.8125-7063-false-2703-4-0.99-true-false-false-false-true-false-false-true-6819-3764-1.0000-hanning.ark deleted file mode 100644 index a4463cd778c952f86047f97381d734b3b798acd3..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 53 zcmd0;jL%F_U~qEtRbXLaU|?Wj0TMS_G(Eje=X;CJW;|uHn&H&77R{4D{%IiJ3&{5Z E0EaRV#sB~S diff --git a/test/assets/kaldi/fbank-2.1792-4.7065-0.6250-0.1875-6808-true-742-4-0.36-false-true-true-false-true-false-true-true-5081-4539-1.0000-hamming.ark b/test/assets/kaldi/fbank-2.1792-4.7065-0.6250-0.1875-6808-true-742-4-0.36-false-true-true-false-true-false-true-true-5081-4539-1.0000-hamming.ark deleted file mode 100644 index e575d185e41dac08b8c0948ce41450c7ff2933fc..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 133 zcmV;00DAvzd0%N{AOJ!}O&|mZ000041ONa403g7<002q7Kopt2pbb600C?`a0C0Ca z0Hz&2fQ*nn09L%c0Kk;H0RA*SKp~et08n4O0ARa2fFLzKK+c&y06q-809Zsk0MRr) nKn|NefEWZm0E)Oh01zBLK=YJ7fYdTR0P>B!;GYS<;ITWur6MhJ diff --git a/test/assets/kaldi/fbank-2.1902-4.9973-1.1250-0.5000-7066-false-1699-4-0.95-true-false-true-true-false-false-false-false-5452-5271-1.0000-rectangular.ark b/test/assets/kaldi/fbank-2.1902-4.9973-1.1250-0.5000-7066-false-1699-4-0.95-true-false-true-true-false-false-false-false-5452-5271-1.0000-rectangular.ark deleted file mode 100644 index a69fbcf6a0b83164abc5cf0ef799838cfc62f730..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 37 rcmd0;jL%F_U~qEtRbXLcU|?Wj0TNli?cDdjS;&3dS$LqL%k*;H(?lTAX8T^hZBEpX0 Hw(}eTcqRJL{&Fx6*a>X%9SsKnJk^ diff --git a/test/assets/kaldi/fbank-2.7704-4.5251-1.1250-0.8750-3819-true-787-5-0.23-false-false-true-true-true-true-false-false-3368-3286-1.0000-hamming.ark b/test/assets/kaldi/fbank-2.7704-4.5251-1.1250-0.8750-3819-true-787-5-0.23-false-false-true-true-true-true-false-false-3368-3286-1.0000-hamming.ark deleted file mode 100644 index 088b2337ddf515f9da058bf9cdb87acf1c445b90..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 45 ccmd0;jL%F_U~qEtRbXLcU|?Wj0}{9Z0E0LKHvj+t diff --git a/test/assets/kaldi/fbank-2.9255-3.4363-1.1250-1.0000-7660-false-5020-5-0.09-true-false-true-true-true-true-false-false-7470-6783-1.0000-hamming.ark b/test/assets/kaldi/fbank-2.9255-3.4363-1.1250-1.0000-7660-false-5020-5-0.09-true-false-true-true-true-true-false-false-7470-6783-1.0000-hamming.ark deleted file mode 100644 index 088b2337ddf515f9da058bf9cdb87acf1c445b90..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 45 ccmd0;jL%F_U~qEtRbXLcU|?Wj0}{9Z0E0LKHvj+t diff --git a/test/assets/kaldi/fbank-3.0009-1.8450-1.0625-0.7500-5812-true-1287-6-0.22-false-false-true-true-true-true-false-false-5573-4642-1.0000-hanning.ark b/test/assets/kaldi/fbank-3.0009-1.8450-1.0625-0.7500-5812-true-1287-6-0.22-false-false-true-true-true-true-false-false-5573-4642-1.0000-hanning.ark deleted file mode 100644 index 40397585c94eae6c4ef3d969c40c6b275d30aca2..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 49 ccmd0;jL%F_U~qEtRbXLcU|?Wj2NL)I0FX2TH~;_u diff --git a/test/assets/kaldi/fbank-3.0442-4.0677-1.0625-1.1250-5086-true-1013-4-0.99-false-false-true-true-false-true-true-false-4997-4836-1.9525-hamming.ark b/test/assets/kaldi/fbank-3.0442-4.0677-1.0625-1.1250-5086-true-1013-4-0.99-false-false-true-true-false-true-true-false-4997-4836-1.9525-hamming.ark deleted file mode 100644 index 5fe9007902e1602bea06bf70e23f88f94fc03f4f..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 41 vcmd0;jL%F_U~qEtRbXLcU|?Wj1rlP1c^uST1s$dPL><)^$T?2bo8$-ptbhp6 diff --git a/test/assets/kaldi/fbank-3.1610-1.5305-0.8750-0.1875-6634-false-1213-6-0.37-false-true-true-false-true-true-true-false-3273-3199-1.0000-povey.ark b/test/assets/kaldi/fbank-3.1610-1.5305-0.8750-0.1875-6634-false-1213-6-0.37-false-true-true-false-true-true-true-false-3273-3199-1.0000-povey.ark deleted file mode 100644 index c381f22d6b39515079a5244fe56ad6854d410ada..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 217 zcmd0;jL%F_U~qEtRbXLfU|;|f3^_aYFx;)RWw=*sd!R{a--APq`xx{e?~AcnXwP6U z*_vTh`yPfBKzya!w&C^(TL#%5wh8)j`xqE@SvE+z?PUPr%YSSc)(hG-6#li%c(DA_ci;kp-Gr4uIS0wz3{kFo86ttW`j>4(lAxW#GA6qPe}Qr{ zl5H6}m~0t3fq1Q&ZNvP9whiIzb`FeR_A<2b>}}}ivIS$u#rqzpZQiF~X}|A+&<=Y5 D&;L@p diff --git a/test/assets/kaldi/fbank-3.2195-2.9858-1.0625-0.0625-6899-true-4117-6-0.85-true-true-true-true-false-false-true-true-5077-4977-0.8739-rectangular.ark b/test/assets/kaldi/fbank-3.2195-2.9858-1.0625-0.0625-6899-true-4117-6-0.85-true-true-true-true-false-false-true-true-5077-4977-0.8739-rectangular.ark deleted file mode 100644 index c502d19e3da3bf7dd0cb156489ab8ad7e0ca2fa1..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 117 zcmd0;jL%F_U~qEtRbXLZU|?Wj0}>@WsvHllEO+cmv2~0~%65!e5%2iFT;FjoW2fVm z8|{wI7TP=Nu4#ANd$7?_zuVA}GpfT;(4*avML@>!_ue+gGZz~i)%G(us-LQKY`j$F VD41jA_|!kc(Q9gq<0MfXM*uMZDsBJ( diff --git a/test/assets/kaldi/fbank-3.3208-1.5569-1.0000-0.3125-4556-false-334-5-0.02-false-true-true-true-true-false-true-false-2831-696-1.0000-hanning.ark b/test/assets/kaldi/fbank-3.3208-1.5569-1.0000-0.3125-4556-false-334-5-0.02-false-true-true-true-true-false-true-false-2831-696-1.0000-hanning.ark deleted file mode 100644 index 2d2a4a0a3ac06ec14f9d4f1f4e834ab3c900878a..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 41 ccmd0;jL%F_U~qEtRbXLcU|?Wj1rpc*0Cq$JHUIzs diff --git a/test/assets/kaldi/fbank-3.3976-3.9462-1.1875-0.5625-6513-false-3398-8-0.38-true-true-true-false-false-false-true-false-5827-5388-1.0000-blackman.ark b/test/assets/kaldi/fbank-3.3976-3.9462-1.1875-0.5625-6513-false-3398-8-0.38-true-true-true-false-false-false-true-false-5827-5388-1.0000-blackman.ark deleted file mode 100644 index bf8ab510c2641a244c0bc4216643a4b4b52c30f2..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 85 zcmd0;jL%F_U~qEtRbXLaU|?Y301`8-MIH57wH=>Km2%`yRB$w|6?aq)6LgfX<#%je o%j@{^Ba362v$o?VQ#r@z2o1;H3F3|qcXK;VzrpM{OOwkH0Cg4@nE(I) diff --git a/test/assets/kaldi/fbank-3.5842-1.2264-0.9375-1.0000-7744-false-195-5-0.62-false-false-true-false-false-true-true-false-7667-2993-1.0000-hamming.ark b/test/assets/kaldi/fbank-3.5842-1.2264-0.9375-1.0000-7744-false-195-5-0.62-false-false-true-false-false-true-true-false-7667-2993-1.0000-hamming.ark deleted file mode 100644 index b68c0a6597ae76041d9051b0d01d7761293444ca..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 45 zcmd0;jL%F_U~qEtRbXLcU|?Wj0}`n-`W?5nTz4pa^Vi{BpR{9anxvzh+!qG`9WD-c diff --git a/test/assets/kaldi/fbank-3.5889-3.3559-1.0000-1.1875-7354-true-997-5-0.98-false-true-true-true-true-false-false-false-7088-6494-1.0000-povey.ark b/test/assets/kaldi/fbank-3.5889-3.3559-1.0000-1.1875-7354-true-997-5-0.98-false-true-true-true-true-false-false-false-7088-6494-1.0000-povey.ark deleted file mode 100644 index 2d2a4a0a3ac06ec14f9d4f1f4e834ab3c900878a..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 41 ccmd0;jL%F_U~qEtRbXLcU|?Wj1rpc*0Cq$JHUIzs diff --git a/test/assets/kaldi/fbank-3.5936-2.1701-1.0625-1.0625-7407-true-3649-5-0.65-false-true-true-true-false-true-true-true-6878-6036-1.0000-povey.ark b/test/assets/kaldi/fbank-3.5936-2.1701-1.0625-1.0625-7407-true-3649-5-0.65-false-true-true-true-false-true-true-true-6878-6036-1.0000-povey.ark deleted file mode 100644 index c228297339aa0d6afe828d047706f977fcb31b26..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 45 zcmd0;jL%F_U~qEtRbXLcU|?Wj0}>ghsvN7XIXen9I65Xx({TJ)F5%dmIl&PC0TT@C diff --git a/test/assets/kaldi/fbank-3.7002-3.5670-1.1875-0.6250-4479-true-2240-6-0.73-false-false-true-false-false-true-false-true-4084-3955-1.0000-hamming.ark b/test/assets/kaldi/fbank-3.7002-3.5670-1.1875-0.6250-4479-true-2240-6-0.73-false-false-true-false-false-true-false-true-4084-3955-1.0000-hamming.ark deleted file mode 100644 index b8e1de6d4c2129ab887855a17291a45916a8097f..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 77 zcmd0;jL%F_U~qEtRbXLaU|?Wj2NIS?Zu&AWZ1BnNNcL5nF7Kn0^~&4u*?F(bB@-Q! g3{LxI=cW2Qk#X}a;!*ZtnEK7T?wgYLjVlu!0gn_LSpWb4 diff --git a/test/assets/kaldi/fbank-3.7078-0.3892-0.8125-0.3125-7876-true-2830-7-0.46-false-false-true-true-true-false-false-true-4726-2918-1.0000-rectangular.ark b/test/assets/kaldi/fbank-3.7078-0.3892-0.8125-0.3125-7876-true-2830-7-0.46-false-false-true-true-true-false-false-true-4726-2918-1.0000-rectangular.ark deleted file mode 100644 index b29214083baf95e34d9e8f08088db853767695e2..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 77 zcmd0;jL%F_U~qEtRbXLaU|?Wj2ND(s#e5D$J@!g_C*xh`Cv?h3`s+!tXI7_rZk+Kl cIVg7KNYvv~K)KUEIWM4`r^GWWFQD8h0PH#+1poj5 diff --git a/test/assets/kaldi/fbank-3.7585-2.9425-1.1875-1.0000-3277-true-2244-4-0.76-false-false-true-false-true-false-false-false-3158-2865-1.0000-rectangular.ark b/test/assets/kaldi/fbank-3.7585-2.9425-1.1875-1.0000-3277-true-2244-4-0.76-false-false-true-false-true-false-false-false-3158-2865-1.0000-rectangular.ark deleted file mode 100644 index 5c90e36332ecd0d82a77f708f326a6498410a9a1..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 37 ccmd0;jL%F_U~qEtRbXLcU|?Wj0TSo{0BKkQH2?qr diff --git a/test/assets/kaldi/fbank-3.7772-2.8211-1.0000-0.1875-3747-false-1244-4-0.64-false-true-true-false-true-false-false-true-3640-2770-1.0000-hanning.ark b/test/assets/kaldi/fbank-3.7772-2.8211-1.0000-0.1875-3747-false-1244-4-0.64-false-true-true-false-true-false-false-true-3640-2770-1.0000-hanning.ark deleted file mode 100644 index 235d9645c6f69e1df62c5049ac130eb7769fc9dd..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 133 zcmV;00DAvzd0%N{AOJ!}O&|mZ000041ONa4FbJ7`VkyVtm!ut^HOV?U?T~a--aWq2hFJ8vZ%yAR1a+H^=ct_l}-yz-aR J@j~KsM*wmCBftOv diff --git a/test/assets/kaldi/fbank-3.8677-2.5418-1.0625-0.0625-3496-true-309-4-0.47-false-false-true-false-false-false-true-false-1490-645-1.0000-rectangular.ark b/test/assets/kaldi/fbank-3.8677-2.5418-1.0625-0.0625-3496-true-309-4-0.47-false-false-true-false-false-false-true-false-1490-645-1.0000-rectangular.ark deleted file mode 100644 index 7dc2921baad5a03a889b999f776f20f117fbd3b6..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 341 zcmWO0O(;VF0KoCB4Pi^{y|;zDz17s@y(f_q^_SF$gJ?U@d@S0+w2KxsX^{gC6emin zaZp^8i-_XtpdD!QQOZ{oIXKzncm7Sp0->PO(AwVRGz$iU!EDa4euQCZ`w#?Glppe0Ws99DVll(=pzgFz>eh)VUj$Wx)nf?Hkguyx!<%vPje~3%L=rtj`|_8Hf-mjyNc+Q&d{|)kI#X*O~#nfxJXGX z^$ASQ%ETKq9tZ6tA|k(Og+T6q|7XWICb56z;vrZ|>{wzuYsFQskU6PkCnYjv$>+%H U#IvPx@*>hdXJK_wA>Xg^4@)R*&;S4c diff --git a/test/assets/kaldi/fbank-3.8988-3.9608-1.1250-0.1250-6973-false-1703-5-0.68-true-false-true-false-true-true-true-true-6446-6419-1.0000-povey.ark b/test/assets/kaldi/fbank-3.8988-3.9608-1.1250-0.1250-6973-false-1703-5-0.68-true-false-true-false-true-true-true-true-6446-6419-1.0000-povey.ark deleted file mode 100644 index 02a67809e97863c63ca77ea1483cab6dc9b67902..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 261 zcmV+g0s8)Jd0%N{AOJ!}O&|mc000041^@s60Dhr80GJy*!0xBMpv7pvSZ|m=@O{%i z081Rc0JOn80AAz00E$b#&<8C)P+hw}0MUs(0C)ks021RpK=p$@zz0#jK=s)^0Fn8BWQg~qV3s8LYgR9F7(&WdB~OFqS3%m z?KJAA3{)huk!#A=LUg89qv%)B%(|Jm>KR^@+?A!|{A@;L&i`ZZtq0%-dfVnafIR-CW>Yl^p>YA?`~9D3$cB^lR#O31M=s4yHFVC@W{; zlgXV17YZo@5rlu$Bj!ghhgVCi-tr0&lz&JI2TFvfm|{@cr>RB+tv5P$&L;E3QUz1u zepKGppgHyg?WctL{y?4@Y9qMOFS{yGAC95ZrlCJEKmlpR{V2jr89{a(Szlsk-|0sG Ri9yOyqbKD~`AM;d{|6b3{U`tc diff --git a/test/assets/kaldi/fbank-3.9033-2.6770-1.1250-0.8750-5699-false-2960-7-0.52-true-true-true-true-true-true-false-false-5458-5400-1.0000-rectangular.ark b/test/assets/kaldi/fbank-3.9033-2.6770-1.1250-0.8750-5699-false-2960-7-0.52-true-true-true-true-true-true-false-false-5458-5400-1.0000-rectangular.ark deleted file mode 100644 index ba991d473cae9aa4c61a1dd1696d9399779675f7..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 53 ccmd0;jL%F_U~qEtRbXLcU|?Y301|`%0G&7kIRF3v diff --git a/test/assets/kaldi/fbank-3.9687-0.6295-1.1250-0.0625-5774-false-3495-4-0.48-true-true-true-true-true-true-true-false-5769-5699-1.0000-povey.ark b/test/assets/kaldi/fbank-3.9687-0.6295-1.1250-0.0625-5774-false-3495-4-0.48-true-true-true-true-true-true-true-false-5769-5699-1.0000-povey.ark deleted file mode 100644 index a1119f033d7183b263fd87800433fd914458a0f8..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 81 zcmd0;jL%F_U~qEtRbXLeU|?Wj1riJj6KxniEVgE7NZ84sv%s1m>aq>PEzi9Sb6SC7 juPqr0YONV0XW1~gG1@X56WPPiP_~nyh<{JRF0;J=U?vzQ diff --git a/test/assets/kaldi/fbank-4.0371-3.7559-1.0625-0.8125-4280-false-1207-4-0.12-true-false-true-true-true-true-false-true-3686-2010-1.0000-hamming.ark b/test/assets/kaldi/fbank-4.0371-3.7559-1.0625-0.8125-4280-false-1207-4-0.12-true-false-true-true-true-true-false-true-3686-2010-1.0000-hamming.ark deleted file mode 100644 index 2d2a4a0a3ac06ec14f9d4f1f4e834ab3c900878a..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 41 ccmd0;jL%F_U~qEtRbXLcU|?Wj1rpc*0Cq$JHUIzs diff --git a/test/assets/kaldi/fbank-4.0757-4.7442-0.8750-1.1250-6363-true-1524-4-0.32-true-false-false-true-false-true-true-false-5178-4628-1.0000-blackman.ark b/test/assets/kaldi/fbank-4.0757-4.7442-0.8750-1.1250-6363-true-1524-4-0.32-true-false-false-true-false-true-true-false-5178-4628-1.0000-blackman.ark deleted file mode 100644 index e30a24c1ab9ac27bc97719c8f49813ebb3715feb..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 41 vcmd0;jL%F_U~qEtRbXLcU|?Wj1rk%g>N}b})^MDdqvOcKqwAP(ey$?`$-oM) diff --git a/test/assets/kaldi/fbank-4.1248-2.5255-0.6875-0.6875-3527-true-1701-4-0.43-true-true-true-true-true-true-false-true-2884-1773-1.0000-blackman.ark b/test/assets/kaldi/fbank-4.1248-2.5255-0.6875-0.6875-3527-true-1701-4-0.43-true-true-true-true-true-true-false-true-2884-1773-1.0000-blackman.ark deleted file mode 100644 index 2d2a4a0a3ac06ec14f9d4f1f4e834ab3c900878a..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 41 ccmd0;jL%F_U~qEtRbXLcU|?Wj1rpc*0Cq$JHUIzs diff --git a/test/assets/kaldi/fbank-4.1800-4.6907-1.1875-0.5625-7316-true-3483-8-0.61-false-true-true-false-true-true-true-true-5820-4635-1.0000-rectangular.ark b/test/assets/kaldi/fbank-4.1800-4.6907-1.1875-0.5625-7316-true-3483-8-0.61-false-true-true-false-true-true-true-true-5820-4635-1.0000-rectangular.ark deleted file mode 100644 index 862c43a30fdfd855e7340df2e93bc42448eae6a6..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 93 zcmd0;jL%F_U~qEtRbXLaU|?Y31QHH^qU;oE&e$>B+qReCQ-rOCL)5YR-BSnAvfT~< DEddUD diff --git a/test/assets/kaldi/fbank-4.3252-0.7732-0.6250-0.6875-7389-false-2071-4-0.08-true-false-true-false-false-true-false-false-6900-2344-1.0000-blackman.ark b/test/assets/kaldi/fbank-4.3252-0.7732-0.6250-0.6875-7389-false-2071-4-0.08-true-false-true-false-false-true-false-false-6900-2344-1.0000-blackman.ark deleted file mode 100644 index d9ede2c7a011bb1c626a472a08630e78e7db9f0c..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 61 zcmd0;jL%F_U~qEtRbXLaU|?Wj1rki1vm68Wb-H_KmAV%nRCnJjmf}9MbB?3$m(A|W Q0++ZidSK^1sVCDN01D|8u>b%7 diff --git a/test/assets/kaldi/fbank-4.3693-3.9073-0.8750-0.9375-6107-true-3905-4-0.86-true-false-true-false-true-true-false-true-5001-4046-1.0000-rectangular.ark b/test/assets/kaldi/fbank-4.3693-3.9073-0.8750-0.9375-6107-true-3905-4-0.86-true-false-true-false-true-true-false-true-5001-4046-1.0000-rectangular.ark deleted file mode 100644 index 2d2a4a0a3ac06ec14f9d4f1f4e834ab3c900878a..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 41 ccmd0;jL%F_U~qEtRbXLcU|?Wj1rpc*0Cq$JHUIzs diff --git a/test/assets/kaldi/fbank-4.3926-2.0617-0.5625-0.0625-4253-true-1367-5-0.84-false-true-true-true-false-true-true-false-2112-1445-1.0000-hamming.ark b/test/assets/kaldi/fbank-4.3926-2.0617-0.5625-0.0625-4253-true-1367-5-0.84-false-true-true-true-false-true-true-false-2112-1445-1.0000-hamming.ark deleted file mode 100644 index 6254849c9637484741fecfcc5442629e18490945..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 309 zcmWN}&nv@W0LSsk!olIu6HQI_2OtzpD?T4-aqv8;t;l?pq~u4_)|e?FG|$SxNy)Di zyO1QJ6giM`c5zfL&%yEgJ=x`bdiR>kj!#d9e7(`ZkiXjJ^Z6@E+3K_SSrNQw)tJAL zT+h3hjT@f!SfrK(UmG-TFC~X^Eg^!fvL&C#-u)y?yMPgO(tx6+P zluTW@ICc!zA{G-%f(jbLcal!RMa{cmV9cT=FBpv|)MX@Fw1>M&z*&TS#ZpYAZY!3sswH+8wySj$~h#N$B_BlM- Kv6tbk diff --git a/test/assets/kaldi/fbank-4.9640-3.4931-1.1875-1.0000-4235-true-1036-4-0.43-false-true-true-false-true-true-false-false-3706-2840-1.0000-hamming.ark b/test/assets/kaldi/fbank-4.9640-3.4931-1.1875-1.0000-4235-true-1036-4-0.43-false-true-true-false-true-true-false-false-3706-2840-1.0000-hamming.ark deleted file mode 100644 index 2d2a4a0a3ac06ec14f9d4f1f4e834ab3c900878a..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 41 ccmd0;jL%F_U~qEtRbXLcU|?Wj1rpc*0Cq$JHUIzs diff --git a/test/assets/kaldi/mfcc-0.0063-3.0323-0.6250-0.0625-5842-false-3240-4-0.29-true-false-true-true-true-true-2-73.5792-5749-4449-1.0000-blackman.ark b/test/assets/kaldi/mfcc-0.0063-3.0323-0.6250-0.0625-5842-false-3240-4-0.29-true-false-true-true-true-true-2-73.5792-5749-4449-1.0000-blackman.ark deleted file mode 100644 index 6851377b73719226a9768bd340a8fa3ae51e1b7e..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 109 zcmV-z0FwW0d0%N{AOJ!}O&|md000040ssI202dKH0L?8wfD^ZRS@pK1Ifquu1&ROYL1U8xg2Z!r#qAw^g99onlT9h diff --git a/test/assets/kaldi/mfcc-0.1447-4.7142-1.0625-0.4375-7629-true-3498-7-0.39-true-true-true-true-true-false-3-19.4145-7169-6751-1.0000-hanning.ark b/test/assets/kaldi/mfcc-0.1447-4.7142-1.0625-0.4375-7629-true-3498-7-0.39-true-true-true-true-true-false-3-19.4145-7169-6751-1.0000-hanning.ark deleted file mode 100644 index 1d1e54f1345975676060adce6e6a164f12918eeb..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 33 ccmd0;jL%F_U~qEtRbXLcU|?Wj1`@~s09XU+VZc{p$e$zkmz= diff --git a/test/assets/kaldi/mfcc-0.2107-3.4750-1.1250-0.8125-5701-true-1629-4-0.09-true-false-true-false-true-true-2-77.7066-5622-5544-1.0000-blackman.ark b/test/assets/kaldi/mfcc-0.2107-3.4750-1.1250-0.8125-5701-true-1629-4-0.09-true-false-true-false-true-true-2-77.7066-5622-5544-1.0000-blackman.ark deleted file mode 100644 index 00a02adf9d093ed097f21f8b93fbb11159b03f5c..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 37 pcmd0;jL%F_U~qEtRbXLaU|;|fw|i&oXAlV7bEkKPJp)Ie4FIe$3FQC) diff --git a/test/assets/kaldi/mfcc-0.2523-0.1480-1.0000-1.1250-5833-false-556-4-0.66-true-true-true-true-true-false-4-57.0398-4519-3600-1.0000-rectangular.ark b/test/assets/kaldi/mfcc-0.2523-0.1480-1.0000-1.1250-5833-false-556-4-0.66-true-true-true-true-true-false-4-57.0398-4519-3600-1.0000-rectangular.ark deleted file mode 100644 index 5c90e36332ecd0d82a77f708f326a6498410a9a1..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 37 ccmd0;jL%F_U~qEtRbXLcU|?Wj0TSo{0BKkQH2?qr diff --git a/test/assets/kaldi/mfcc-0.2648-0.5702-1.1875-0.1250-5559-false-932-8-0.92-false-false-true-false-true-false-3-96.3721-4277-2466-1.0000-rectangular.ark b/test/assets/kaldi/mfcc-0.2648-0.5702-1.1875-0.1250-5559-false-932-8-0.92-false-false-true-false-true-false-3-96.3721-4277-2466-1.0000-rectangular.ark deleted file mode 100644 index fb2b88a9cb76be92b39cd2fe7b03262d81178a0e..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 141 zcmV;80CN9rd0%N{AOJ!}O&|mc000040{{R301Tr&Xz4OOz<!0NAEJQU2q<&@Z(= zfE}(rmY|J42r1`3z-5=e&~g?)_{NXG0N7H#7^K*~0J|-~0DP6c$Yc^efaZI@0AzPP vfH@04z+}BX0N$QH6c1lNXeCrY0J0cA(XX4opwiJl01N}Y8-3!xpl6xCp0_!Q diff --git a/test/assets/kaldi/mfcc-0.2959-2.3729-0.6250-0.5000-6757-false-1744-6-0.20-true-false-true-true-true-false-2-99.8710-4957-3549-1.0000-povey.ark b/test/assets/kaldi/mfcc-0.2959-2.3729-0.6250-0.5000-6757-false-1744-6-0.20-true-false-true-true-true-false-2-99.8710-4957-3549-1.0000-povey.ark deleted file mode 100644 index 3f1f943cf95355f19f71d870f50c56a5cffedfcb..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 37 pcmd0;jL%F_U~qEtRbXLaU|;|f4Cngyo_N5&pW#fu?S%*Y_5iVO3t9jG diff --git a/test/assets/kaldi/mfcc-0.3642-3.5246-0.4375-0.9375-7942-false-3282-4-0.52-false-false-true-true-false-false-3-74.4735-5601-4966-1.0000-blackman.ark b/test/assets/kaldi/mfcc-0.3642-3.5246-0.4375-0.9375-7942-false-3282-4-0.52-false-false-true-true-false-false-3-74.4735-5601-4966-1.0000-blackman.ark deleted file mode 100644 index 0e8da8bc4d6f28b0c8eb694db30a0ff9860d0f03..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 33 ncmd0;jL%F_U~qEtRbXLcU|?Wj1`@xvy>r}G!QjBYv&8`biJA!w diff --git a/test/assets/kaldi/mfcc-0.4261-0.8487-0.3750-0.1250-6730-false-1273-5-0.71-true-true-true-false-true-false-3-57.1750-3578-2101-1.0000-hanning.ark b/test/assets/kaldi/mfcc-0.4261-0.8487-0.3750-0.1250-6730-false-1273-5-0.71-true-true-true-false-true-false-3-57.1750-3578-2101-1.0000-hanning.ark deleted file mode 100644 index 43f269ccfce642a553997798b437165ac4d72e9c..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 141 zcmV;80CN9rd0%N{AOJ!}O&|mc000040{{R3;Nt$jh-8L70c88XKvN(;h({+s@Ig2~ z0AEi&_+kCNfZ8j*0D~(&VgU-jFn|)i0AV6OXv!!*99lI$0048k6-R@=5R3%BfWp5% v0CYP%n3RA%K<*DekR|FqAPosW02s6fa~(U&eEknL|vahd2Ka^ diff --git a/test/assets/kaldi/mfcc-0.4891-1.9890-1.1250-0.8750-3219-true-973-5-0.91-false-false-true-true-true-true-4-85.3570-3181-3129-1.0000-hamming.ark b/test/assets/kaldi/mfcc-0.4891-1.9890-1.1250-0.8750-3219-true-973-5-0.91-false-false-true-true-true-true-4-85.3570-3181-3129-1.0000-hamming.ark deleted file mode 100644 index 5c90e36332ecd0d82a77f708f326a6498410a9a1..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 37 ccmd0;jL%F_U~qEtRbXLcU|?Wj0TSo{0BKkQH2?qr diff --git a/test/assets/kaldi/mfcc-0.5428-1.2368-0.5625-1.0000-6700-false-749-4-0.86-false-false-true-true-true-true-2-16.2782-5573-4988-1.0000-rectangular.ark b/test/assets/kaldi/mfcc-0.5428-1.2368-0.5625-1.0000-6700-false-749-4-0.86-false-false-true-true-true-true-2-16.2782-5573-4988-1.0000-rectangular.ark deleted file mode 100644 index 9d86c0893b4873332f278aaa8762ee0b17d2aecb..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 29 ccmd0;jL%F_U~qEtRbXLcU|?Wj0unF)08f|$GXMYp diff --git a/test/assets/kaldi/mfcc-0.5495-2.9502-1.1875-1.1875-3873-true-1564-5-0.05-false-true-true-false-true-false-5-59.0075-3870-3750-1.0000-hanning.ark b/test/assets/kaldi/mfcc-0.5495-2.9502-1.1875-1.1875-3873-true-1564-5-0.05-false-true-true-false-true-false-5-59.0075-3870-3750-1.0000-hanning.ark deleted file mode 100644 index 2d2a4a0a3ac06ec14f9d4f1f4e834ab3c900878a..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 41 ccmd0;jL%F_U~qEtRbXLcU|?Wj1rpc*0Cq$JHUIzs diff --git a/test/assets/kaldi/mfcc-0.6055-3.9496-1.0000-0.1250-7949-true-1517-8-0.88-false-true-false-false-true-false-6-55.7891-4641-2879-1.0000-hanning.ark b/test/assets/kaldi/mfcc-0.6055-3.9496-1.0000-0.1250-7949-true-1517-8-0.88-false-true-false-false-true-false-6-55.7891-4641-2879-1.0000-hanning.ark deleted file mode 100644 index 4e2bb9a8113694d3d01ea220a7cf841985b0de3d..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 261 zcmV+g0s8)Jd0%N{AOJ!}O&|mc000041^@s6hGE;lX4MHn8lyZwa_t|%VIQ49;LZ#{ zP>H9&WM-5=tQF=y3(yY0U=UkAASe|;0KC{es56v5?}f0y7p>GlGs#E50Ju6m+?k?4 zGz_S~NKQ?@(5&P?Kw#WH0PFj|{L{=pQYzHIcqr^XY<8GG7;?8i0Bk0}oB+x|KxEFq z{OG+t*deVyz?zyrAf6(?6oJe@AW+i4^jzsaC{CY0*et9+U`QpvV7;b45c592B))RM zxAw0<4ia9#0D7#xaH^od?-+tWa+p59xEnJ+^j7P?U^y5-I<^PFK$7J^v^cUrDk;Xm L*dva=0J}s$+IMsT diff --git a/test/assets/kaldi/mfcc-0.6457-2.0199-0.8750-0.8125-6510-false-1482-4-0.26-false-true-false-true-false-true-2-49.7663-5461-4039-1.0000-blackman.ark b/test/assets/kaldi/mfcc-0.6457-2.0199-0.8750-0.8125-6510-false-1482-4-0.26-false-true-false-true-false-true-2-49.7663-5461-4039-1.0000-blackman.ark deleted file mode 100644 index d9730160ff01175edcc9a37b27246b20a607567f..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 29 jcmd0;jL%F_U~qEtRbXLcU|?Wj0urD7COJAuh&uuRU&00X diff --git a/test/assets/kaldi/mfcc-0.7031-4.0380-1.1250-0.6875-6433-true-2336-8-0.70-false-true-false-true-true-false-3-18.0061-5902-3191-1.0000-rectangular.ark b/test/assets/kaldi/mfcc-0.7031-4.0380-1.1250-0.6875-6433-true-2336-8-0.70-false-true-false-true-true-false-3-18.0061-5902-3191-1.0000-rectangular.ark deleted file mode 100644 index 1d1e54f1345975676060adce6e6a164f12918eeb..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 33 ccmd0;jL%F_U~qEtRbXLcU|?Wj1`@~s09GnA&R3FoDg+VF6J5z-JqVx?g)4Y_j*w@0oP~ E0JfzjeE7dbegR^}j=nXhB)WKl}E+8w8LIXK?CGULDl+a~+px}o*}0^bfR diff --git a/test/assets/kaldi/mfcc-0.9502-1.9738-0.7500-0.2500-7773-true-1205-7-0.50-false-false-true-false-false-true-3-62.9038-7460-7174-1.0000-blackman.ark b/test/assets/kaldi/mfcc-0.9502-1.9738-0.7500-0.2500-7773-true-1205-7-0.50-false-false-true-false-false-true-3-62.9038-7460-7174-1.0000-blackman.ark deleted file mode 100644 index 2cf95fab1ea26f9055a0452f31b785376f626c77..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 81 zcmV-X0IvUSd0%N{AOJ!}O&|mX000040{{R3)E^2#(IM=>gWi`xg#*DrU=_x|_@k6T n5+BMyl)eSQqj;D>V$r`qPq6X8wRx67r#=ZmSnJBb{`rh@1ek#S5HoaYDtpb-g9 diff --git a/test/assets/kaldi/mfcc-1.1602-3.7738-1.0625-0.0625-3652-false-1886-4-0.55-true-true-true-false-true-true-3-73.6328-3496-2890-1.0000-hamming.ark b/test/assets/kaldi/mfcc-1.1602-3.7738-1.0625-0.0625-3652-false-1886-4-0.55-true-true-true-false-true-true-3-73.6328-3496-2890-1.0000-hamming.ark deleted file mode 100644 index 8f2056f00efb7698578d19993ed7417533fad619..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 261 zcmV+g0s8)Jd0%N{AOJ!}O&|mm000040{{R306G!9f*{X75atO!07@P`+M}jF(1jX4 z0Jx<*hgvj05Y=8j0N4gR;7jd1@ID4U0CX}vG6TZC0G>>}01!sJ_Yx?-U>^&<08Uc9 zdFO1u@N#{=0Fc2vX32cN0K~(-04fMQ*VT5v@C3WQ08_fXV-beGcvHB(0FRKpn^cFt zNc+{k0E`qp!a{ey$nC$r0N5lvLhEb4U<8o90Dcs`M)z935PT)R0I*%WNl_KQfc_c1 z0O$Zc#5pv+5Xf*o08k1&dftjYXshx*0Co{Qo34I8c$Eo107SbyG_vA#`bq diff --git a/test/assets/kaldi/mfcc-1.2069-0.4607-1.1250-0.5625-5864-true-1512-7-0.17-false-true-true-false-false-true-3-33.0194-5438-3920-1.0000-blackman.ark b/test/assets/kaldi/mfcc-1.2069-0.4607-1.1250-0.5625-5864-true-1512-7-0.17-false-true-true-false-false-true-3-33.0194-5438-3920-1.0000-blackman.ark deleted file mode 100644 index 470acf3382333d8b9d5b33b902e7191cca80e969..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 45 zcmd0;jL%F_U~qEtRbXLaU|?Wj1`_>yxEzaZdJcH=%y;B_a?9bzv;G54x$_+X3nmW5 diff --git a/test/assets/kaldi/mfcc-1.2303-1.5089-1.0625-0.8125-5882-false-3298-8-0.49-true-false-true-false-false-false-7-81.2017-5809-5654-1.0000-hamming.ark b/test/assets/kaldi/mfcc-1.2303-1.5089-1.0625-0.8125-5882-false-3298-8-0.49-true-false-true-false-false-false-7-81.2017-5809-5654-1.0000-hamming.ark deleted file mode 100644 index ce88edb222a6fa3834c8da4460a6424f423d93cd..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 77 zcmd0;jL%F_U~qEtRbXLaU|?Wj2NExih&pNK_&G*y(0BY}pXxBZQciK;4={+!K!7Rsg^-_=#T|!RQ*AyN2Qa&6202zS} A)Bpeg diff --git a/test/assets/kaldi/mfcc-1.4295-3.7938-1.1250-0.7500-3382-false-471-4-0.42-false-false-false-false-true-true-2-78.5880-3299-2540-1.0000-hanning.ark b/test/assets/kaldi/mfcc-1.4295-3.7938-1.1250-0.7500-3382-false-471-4-0.42-false-false-false-false-true-true-2-78.5880-3299-2540-1.0000-hanning.ark deleted file mode 100644 index 1ea457d702e932a9af4a26cf6e0f57f4eab9f304..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 37 ocmd0;jL%F_U~qEtRbXLaU|;|f40osO4T+hsA4uDV#Z0gV0IH`7kN^Mx diff --git a/test/assets/kaldi/mfcc-1.4677-4.0728-1.1250-1.0625-7698-true-569-6-0.50-true-true-false-true-true-false-3-76.8484-7453-7251-1.0000-rectangular.ark b/test/assets/kaldi/mfcc-1.4677-4.0728-1.1250-1.0625-7698-true-569-6-0.50-true-true-false-true-true-false-3-76.8484-7453-7251-1.0000-rectangular.ark deleted file mode 100644 index 1d1e54f1345975676060adce6e6a164f12918eeb..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 33 ccmd0;jL%F_U~qEtRbXLcU|?Wj1`@~s09+6MrFY!EX5 diff --git a/test/assets/kaldi/mfcc-1.4979-1.1705-1.1875-0.3750-4474-true-1123-7-0.09-true-false-true-true-false-true-4-38.6407-3043-2934-1.0000-hamming.ark b/test/assets/kaldi/mfcc-1.4979-1.1705-1.1875-0.3750-4474-true-1123-7-0.09-true-false-true-true-false-true-4-38.6407-3043-2934-1.0000-hamming.ark deleted file mode 100644 index d776bd55b9deafd91c612de25c73c2f36e5c7309..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 37 rcmd0;jL%F_U~qEtRbXLcU|?Wj0TRg{GY)Xx@;UfTF36#VcfKP4ujUG{ diff --git a/test/assets/kaldi/mfcc-1.4988-0.0621-0.8750-0.1875-4881-true-846-4-0.53-false-true-false-false-false-true-2-17.5040-4228-1009-1.0000-rectangular.ark b/test/assets/kaldi/mfcc-1.4988-0.0621-0.8750-0.1875-4881-true-846-4-0.53-false-true-false-false-false-true-2-17.5040-4228-1009-1.0000-rectangular.ark deleted file mode 100644 index 28f94712923ac0f59f9fc7fd62a7e59a6baf522d..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 77 zcmV-T0J8sWd0%N{AOJ!}O&|mZ000040ssI2`Qh5X$=8)ZW53zI+X|LJAiE&I0R5Fg j>$VcW;0KmLEHDeea}$<953mQoUp|#VDv3S3fIyW&O(z}} diff --git a/test/assets/kaldi/mfcc-1.5514-3.7279-1.0000-0.2500-7958-true-481-5-0.93-true-true-false-true-true-true-4-98.3869-7445-7362-1.0000-hamming.ark b/test/assets/kaldi/mfcc-1.5514-3.7279-1.0000-0.2500-7958-true-481-5-0.93-true-true-false-true-true-true-4-98.3869-7445-7362-1.0000-hamming.ark deleted file mode 100644 index 7f99d35a70e1e11957e88494f7a94497fbc632d0..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 53 zcmd0;jL%F_U~qEtRbXLaU|?Wj0TK->zt}MF?zUz4xYvf^Lyt9(zX!lt diff --git a/test/assets/kaldi/mfcc-1.5707-3.0409-0.7500-0.6250-7441-true-1554-6-0.95-true-false-true-true-true-true-4-80.1563-7152-6151-1.0000-rectangular.ark b/test/assets/kaldi/mfcc-1.5707-3.0409-0.7500-0.6250-7441-true-1554-6-0.95-true-false-true-true-true-true-4-80.1563-7152-6151-1.0000-rectangular.ark deleted file mode 100644 index 5c90e36332ecd0d82a77f708f326a6498410a9a1..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 37 ccmd0;jL%F_U~qEtRbXLcU|?Wj0TSo{0BKkQH2?qr diff --git a/test/assets/kaldi/mfcc-1.5966-2.3442-0.5625-0.5000-7944-true-1616-5-0.49-true-true-true-false-false-true-2-80.8779-5720-4080-1.0000-povey.ark b/test/assets/kaldi/mfcc-1.5966-2.3442-0.5625-0.5000-7944-true-1616-5-0.49-true-true-true-false-false-true-2-80.8779-5720-4080-1.0000-povey.ark deleted file mode 100644 index 1d9faca58a2e8ee9e2950b0ab0b76c0e0fb8a054..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 45 zcmd0;jL%F_U~qEtRbXLeU|?Wj0ut+{{&AS*J=IYxfyL3mf2w2l&9e?GHK#iQ00^)R Ah5!Hn diff --git a/test/assets/kaldi/mfcc-1.6229-2.0519-1.1875-0.3125-4871-true-1567-4-0.79-false-true-true-true-false-true-2-42.9569-3483-3287-1.0000-hanning.ark b/test/assets/kaldi/mfcc-1.6229-2.0519-1.1875-0.3125-4871-true-1567-4-0.79-false-true-true-true-false-true-2-42.9569-3483-3287-1.0000-hanning.ark deleted file mode 100644 index f9c63dbd2fb6f0557520e2b623d3623082b9d665..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 29 jcmd0;jL%F_U~qEtRbXLcU|?Wj0ur;AXE_`Wndk@rVkid) diff --git a/test/assets/kaldi/mfcc-1.6399-3.5598-1.0000-0.2500-6102-false-1267-4-0.83-true-false-true-false-false-false-4-31.0832-5457-4742-1.0000-rectangular.ark b/test/assets/kaldi/mfcc-1.6399-3.5598-1.0000-0.2500-6102-false-1267-4-0.83-true-false-true-false-false-false-4-31.0832-5457-4742-1.0000-rectangular.ark deleted file mode 100644 index 76d3ae2e1691d357ab94e2cbfa8650a684bd0d21..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 101 zcmV-r0Gj`8d0%N{AOJ!}O&|mX000041ONa4h~FAQwLfG)o%mBe_>rqVYNQuJq{6#E zHdMgCgaCj*_p2I0Z51>?G}frVG*ux$Qi2vj6e89@@>JTu5xbK>CYu^U1oBcq2#%*e H29}q;-hm~X diff --git a/test/assets/kaldi/mfcc-1.7360-0.4063-0.6875-0.0625-6475-true-4439-4-0.23-true-false-true-false-false-false-2-30.0984-5450-4909-1.0000-rectangular.ark b/test/assets/kaldi/mfcc-1.7360-0.4063-0.6875-0.0625-6475-true-4439-4-0.23-true-false-true-false-false-false-2-30.0984-5450-4909-1.0000-rectangular.ark deleted file mode 100644 index 4b427a041dc74e62016396d945b0d1e5ffdff8ff..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 181 zcmV;m080ODd0%N{AOJ!}O&|mm000040ssI28mxdoLCP{hFr!+)2;?k6G4R5`tTG%z z6{GCH?P?W5Wh`C5^Cu=kf-)IEZ1pfgw?>gbYCASUUZ-9_%zrgPzVbpoG;=CKSjI3w z;XfuqZymY%7;QyH_tla$`q_ diff --git a/test/assets/kaldi/mfcc-1.7411-2.0918-1.0625-0.8125-6107-true-2523-4-0.69-true-false-true-true-false-false-3-92.6839-5085-4771-1.0000-povey.ark b/test/assets/kaldi/mfcc-1.7411-2.0918-1.0625-0.8125-6107-true-2523-4-0.69-true-false-true-true-false-false-3-92.6839-5085-4771-1.0000-povey.ark deleted file mode 100644 index 57c6959a3d627f1efd0fd50682d67b0830160cbd..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 33 ncmd0;jL%F_U~qEtRbXLcU|?Wj1`meg=F1 diff --git a/test/assets/kaldi/mfcc-1.7611-4.2965-0.8125-0.6875-6607-false-454-7-0.35-true-true-true-false-true-false-2-17.8265-6387-6105-1.0000-hanning.ark b/test/assets/kaldi/mfcc-1.7611-4.2965-0.8125-0.6875-6607-false-454-7-0.35-true-true-true-false-true-false-2-17.8265-6387-6105-1.0000-hanning.ark deleted file mode 100644 index 283ac67bcaf19e42b7e8a3218c8452fae657c5b2..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 37 mcmd0;jL%F_U~qEtRbXLaU|;|f4F1RW9l6xKA4uB)X?p;#u?w64 diff --git a/test/assets/kaldi/mfcc-1.7893-1.8005-0.6250-0.3750-2791-true-617-4-0.96-true-false-true-true-false-true-4-93.4050-1751-1690-1.0000-povey.ark b/test/assets/kaldi/mfcc-1.7893-1.8005-0.6250-0.3750-2791-true-617-4-0.96-true-false-true-true-false-true-4-93.4050-1751-1690-1.0000-povey.ark deleted file mode 100644 index 0388a86a955d562ed828e39fd21f851f8e56ca28..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 53 zcmd0;jL%F_U~qEtRbXLaU|?Wj0TP0d0tcS<`8#;E@i;Jb&T?!E;Ro}tP2+aZcst7x E0BN5PMgRZ+ diff --git a/test/assets/kaldi/mfcc-1.8392-4.3711-0.9375-0.7500-6978-true-453-4-0.48-true-true-true-true-true-false-3-42.9768-6315-3995-1.1059-rectangular.ark b/test/assets/kaldi/mfcc-1.8392-4.3711-0.9375-0.7500-6978-true-453-4-0.48-true-true-true-true-true-false-3-42.9768-6315-3995-1.1059-rectangular.ark deleted file mode 100644 index 1d1e54f1345975676060adce6e6a164f12918eeb..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 33 ccmd0;jL%F_U~qEtRbXLcU|?Wj1`@~s099sOtEjj zaDVT>$m|-xSbb5xt-l_@^okBYGPy6o(D1%Ky3Y*1BH8r6Kmv)r@QxS3@|(E8;@~X6 zv|WL~#;)Z*c*nxPAgql($hUSsayOGe$as=IXhe!YQSnMZ;X!skVgnLDpf4J~z`pT7 XBQOC#l6+FXh97r8{4F8BkTM8C>fvb_ diff --git a/test/assets/kaldi/mfcc-1.9561-0.8419-0.8125-1.1250-5308-false-1471-5-0.62-true-false-true-true-false-true-3-51.0514-5221-5071-1.0000-rectangular.ark b/test/assets/kaldi/mfcc-1.9561-0.8419-0.8125-1.1250-5308-false-1471-5-0.62-true-false-true-true-false-true-3-51.0514-5221-5071-1.0000-rectangular.ark deleted file mode 100644 index b05a8f453786a3e20c89f261c82fba9202756d26..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 33 ncmd0;jL%F_U~qEtRbXLcU|?Wj1`>Q(a~wDDRXO;2UOE5(czg&c diff --git a/test/assets/kaldi/mfcc-1.9980-1.6949-1.1250-0.8125-4678-true-2340-5-0.44-true-false-false-true-false-true-3-70.1988-4041-2424-1.0000-rectangular.ark b/test/assets/kaldi/mfcc-1.9980-1.6949-1.1250-0.8125-4678-true-2340-5-0.44-true-false-false-true-false-true-3-70.1988-4041-2424-1.0000-rectangular.ark deleted file mode 100644 index 51fea416e511821910c5c9642728380d569ec027..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 33 ncmd0;jL%F_U~qEtRbXLcU|?Wj1`>Af^BnVj&v3AFo#zMuf|m%h diff --git a/test/assets/kaldi/mfcc-2.0106-4.5392-0.6875-0.1875-4776-true-1297-5-0.14-false-false-true-false-false-true-2-37.5837-3995-2991-1.0000-hanning.ark b/test/assets/kaldi/mfcc-2.0106-4.5392-0.6875-0.1875-4776-true-1297-5-0.14-false-false-true-false-false-true-2-37.5837-3995-2991-1.0000-hanning.ark deleted file mode 100644 index 24bb8a996b243ce502dfcdd6c9372ca802333c99..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 77 zcmd0;jL%F_U~qEtRbXLfU|?Wj0um8xAKM3PnB*Abzj=RyL7(H4)_ZpRHIp0@7{Bj- huF&gf&M9j@fH4G`+y7a$v`j1P37h00V==)^nUH F4gi6$5HbJ& diff --git a/test/assets/kaldi/mfcc-2.0835-2.8454-0.9375-0.3125-7496-false-1207-6-0.76-true-false-true-true-false-false-6-4.5734-3935-3932-1.0000-blackman.ark b/test/assets/kaldi/mfcc-2.0835-2.8454-0.9375-0.3125-7496-false-1207-6-0.76-true-false-true-true-false-false-6-4.5734-3935-3932-1.0000-blackman.ark deleted file mode 100644 index 6486e374e977461728fe94e759b7362b3bdf9d5a..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 69 zcmd0;jL%F_U~qEtRbXLaU|?Wj0}?4Z9!}r=`y8eo>p38Ot$TmfCxQLkA&PcM_uQPW YX=gedEShlOpVY+tzA}vaT|^x00QJ`xod5s; diff --git a/test/assets/kaldi/mfcc-2.1743-1.8196-1.0625-0.2500-5382-false-1493-6-0.05-true-true-true-false-false-false-6-35.3731-4786-4226-1.0000-hamming.ark b/test/assets/kaldi/mfcc-2.1743-1.8196-1.0625-0.2500-5382-false-1493-6-0.05-true-true-true-false-false-false-6-35.3731-4786-4226-1.0000-hamming.ark deleted file mode 100644 index 75204cd4bf5db6c61a10e9a233d93d3ef995099c..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 141 zcmV;80CN9rd0%N{AOJ!}O&|mX000041^@s6+?X{&O_l&bv5MWm{lMbAZ^tA)4UP}L zNK7?CoUZ{vCb=-dMPQ0ROu=-(2k6f~J+3rDv400apHM%+AX%M21+|92!^Go1UgR}G vFa!5M=cFCMUldG04+J^Da*UBb6yP*MlI8qB9SMlQt6wL;Un0Xltp88HnbA3T diff --git a/test/assets/kaldi/mfcc-2.2801-1.7051-1.1875-0.1250-7958-true-561-4-0.90-false-false-true-true-true-true-2-60.4649-7218-5709-1.0000-rectangular.ark b/test/assets/kaldi/mfcc-2.2801-1.7051-1.1875-0.1250-7958-true-561-4-0.90-false-false-true-true-true-true-2-60.4649-7218-5709-1.0000-rectangular.ark deleted file mode 100644 index 9d86c0893b4873332f278aaa8762ee0b17d2aecb..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 29 ccmd0;jL%F_U~qEtRbXLcU|?Wj0unF)08f|$GXMYp diff --git a/test/assets/kaldi/mfcc-2.3150-0.4964-0.5000-0.4375-6582-false-1010-4-0.98-false-false-true-true-false-false-3-71.5160-6157-4430-1.0000-rectangular.ark b/test/assets/kaldi/mfcc-2.3150-0.4964-0.5000-0.4375-6582-false-1010-4-0.98-false-false-true-true-false-false-3-71.5160-6157-4430-1.0000-rectangular.ark deleted file mode 100644 index 6006ef583384ddce02c055c36f29ba216dc254da..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 45 zcmd0;jL%F_U~qEtRbXLaU|?Wj1`?Z2@HR);`9?Aa;7OnWRrOLs-U07xD^oDgR~u*WAqegwimyamO;kQ6Mx;Hd4tFvS!< z0O8v|SR@}nK${`Jzl7nx0Koe_jO!>s{)SCJ?0AAeBYuRyILuPOKxON{>_lNeG{NaV z)P$!%=NziQvcK=Y0F(#7;3C{U@R{8|yw(*!s3;h~cSz&E06c0wwCzDTyvPy3Oi6{no>_-L LxP=u#urf_R*k5&x diff --git a/test/assets/kaldi/mfcc-2.3805-2.9340-0.7500-0.2500-6076-true-80-4-0.85-false-true-true-false-true-true-3-31.0805-2257-1533-1.0000-hamming.ark b/test/assets/kaldi/mfcc-2.3805-2.9340-0.7500-0.2500-6076-true-80-4-0.85-false-true-true-false-true-true-3-31.0805-2257-1533-1.0000-hamming.ark deleted file mode 100644 index f9146a0606ca0adbc31d00bcfb76a69ad64f4929..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 81 zcmd0;jL%F_U~qEtRbXLdU|?Wj1`>NhciStxTC$J9_U>MZt2O%>d|PZ8mSouq^i=I{ k@VB*P$g8mZAQ86Tp;N|=AtK(^CVjO%gLA$u!=L88000*oGynhq diff --git a/test/assets/kaldi/mfcc-2.4091-2.8812-1.1250-0.9375-6086-false-1210-5-0.59-true-false-false-false-false-true-3-96.1612-4840-1905-1.0000-hamming.ark b/test/assets/kaldi/mfcc-2.4091-2.8812-1.1250-0.9375-6086-false-1210-5-0.59-true-false-false-false-false-true-3-96.1612-4840-1905-1.0000-hamming.ark deleted file mode 100644 index dedcb03ce6e952c5810449f64c5018e27a535cdc..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 33 ncmd0;jL%F_U~qEtRbXLcU|?Wj1`<=h%y+!xuIX5{EAJoxhS~{( diff --git a/test/assets/kaldi/mfcc-2.4134-2.6379-1.1875-0.3750-3318-false-770-5-0.60-false-true-true-false-false-false-3-73.9427-2044-1481-1.0000-hanning.ark b/test/assets/kaldi/mfcc-2.4134-2.6379-1.1875-0.3750-3318-false-770-5-0.60-false-true-true-false-false-false-3-73.9427-2044-1481-1.0000-hanning.ark deleted file mode 100644 index 43ced6f3bfd905221e25c14a0ef6db503966c6ef..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 57 zcmd0;jL%F_U~qEtRbXLeU|;|f-%C}To-({W@V}w|z=DMePUjYA9=ta9;DHUYs!nDd L4-V{qm~j9AA*dIz diff --git a/test/assets/kaldi/mfcc-2.5228-3.1056-1.1250-1.1875-5422-false-2825-7-0.88-false-false-true-false-false-false-7-4.6719-5337-5243-1.0000-hanning.ark b/test/assets/kaldi/mfcc-2.5228-3.1056-1.1250-1.1875-5422-false-2825-7-0.88-false-false-true-false-false-false-7-4.6719-5337-5243-1.0000-hanning.ark deleted file mode 100644 index 3c4e7b018cecaa6abcafdf3afcb9e4173fd134bd..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 49 zcmd0;jL%F_U~qEtRbXLcU|?Wj2NFKZl$>UMn&P;1n(6_Om8bXrC~|eMY?-l-UAcQd E09P&$+W-In diff --git a/test/assets/kaldi/mfcc-2.5421-3.9141-1.0000-0.1250-5126-false-362-5-0.10-false-true-false-true-true-true-4-83.2329-5090-1185-1.0000-hanning.ark b/test/assets/kaldi/mfcc-2.5421-3.9141-1.0000-0.1250-5126-false-362-5-0.10-false-true-false-true-true-true-4-83.2329-5090-1185-1.0000-hanning.ark deleted file mode 100644 index 2d7479bb0fa048efa80bba1d9040b98d99a35f04..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 69 zcmd0;jL%F_U~qEtRbXLeU|?Wj0TK)io>mw3T(+063b9`i6TP2-VTomilhJ{ITbuW{ Z{NG{EaG-aWz=;X=1y#cK6^q370|3F47()O6 diff --git a/test/assets/kaldi/mfcc-2.5577-0.7393-0.8125-0.5000-5291-true-1445-5-0.01-false-true-true-false-true-false-2-5.8944-4338-4330-1.0000-hanning.ark b/test/assets/kaldi/mfcc-2.5577-0.7393-0.8125-0.5000-5291-true-1445-5-0.01-false-true-true-false-true-false-2-5.8944-4338-4330-1.0000-hanning.ark deleted file mode 100644 index 66eecec655978a31261a2c029da94e318bbbd488..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 45 zcmd0;jL%F_U~qEtRbXLeU|?Wj0unrRyZ0YZ)v;e@cx(RwMtS>N*S#DbOkTPl01lH6 ADgXcg diff --git a/test/assets/kaldi/mfcc-2.5854-3.2219-0.8750-0.4375-6924-false-4024-4-1.00-false-true-true-false-true-false-2-0.0578-5707-5025-1.0000-rectangular.ark b/test/assets/kaldi/mfcc-2.5854-3.2219-0.8750-0.4375-6924-false-4024-4-1.00-false-true-true-false-true-false-2-0.0578-5707-5025-1.0000-rectangular.ark deleted file mode 100644 index 762fae800a36ad63470d7cfd7868c7fbf1f83b8c..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 45 zcmd0;jL%F_U~qEtRbXLeU|?Wj0ul^|;`VL1a@9USdFlSk%Zv{s{61j+sbZo%04CWG Ah5!Hn diff --git a/test/assets/kaldi/mfcc-2.6294-1.9703-1.1875-0.6250-7569-true-2883-8-0.91-false-true-true-false-true-true-7-31.0763-7031-6291-1.0000-povey.ark b/test/assets/kaldi/mfcc-2.6294-1.9703-1.1875-0.6250-7569-true-2883-8-0.91-false-true-true-false-true-true-7-31.0763-7031-6291-1.0000-povey.ark deleted file mode 100644 index e67a1d723d58738a30d76f5ecd88e882b83da5b6..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 77 zcmd0;jL%F_U~qEtRbXLaU|?Wj2NDWNJoYkg7ugGJx@otdf^~laQ^EcPXDe(O9Ez=h ca{GaD`+;)%mQ=9XXD}7mH=M253zXXp0CBz=zW@LL diff --git a/test/assets/kaldi/mfcc-2.6674-2.7770-1.0625-0.3125-3129-true-1706-4-0.91-false-true-true-false-true-true-3-50.9241-2593-2198-1.0000-hanning.ark b/test/assets/kaldi/mfcc-2.6674-2.7770-1.0625-0.3125-3129-true-1706-4-0.91-false-true-true-false-true-true-3-50.9241-2593-2198-1.0000-hanning.ark deleted file mode 100644 index e945306c639376893a9fd78788eece11d981c8a7..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 69 zcmd0;jL%F_U~qEtRbXLZU|?Wj1`;dxYuRs@x^f>w#LT_+{WANfD0JE}XqDS`?=jf_ ZFJ+<~gG+&}Qje1T(ff(}7!H{11pwT^7(W02 diff --git a/test/assets/kaldi/mfcc-2.6816-4.0548-1.1875-0.6250-3182-false-157-6-0.04-false-true-true-true-true-false-5-31.3652-1203-1174-1.0000-povey.ark b/test/assets/kaldi/mfcc-2.6816-4.0548-1.1875-0.6250-3182-false-157-6-0.04-false-true-true-true-true-false-5-31.3652-1203-1174-1.0000-povey.ark deleted file mode 100644 index 2d2a4a0a3ac06ec14f9d4f1f4e834ab3c900878a..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 41 ccmd0;jL%F_U~qEtRbXLcU|?Wj1rpc*0Cq$JHUIzs diff --git a/test/assets/kaldi/mfcc-2.7879-3.3482-0.6875-0.3750-4262-true-150-4-0.68-true-false-true-true-false-true-2-92.7940-3276-1685-1.0000-rectangular.ark b/test/assets/kaldi/mfcc-2.7879-3.3482-0.6875-0.3750-4262-true-150-4-0.68-true-false-true-true-false-true-2-92.7940-3276-1685-1.0000-rectangular.ark deleted file mode 100644 index 9aa42cb5a66495e3b019187647b176d909e01954..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 37 pcmd0;jL%F_U~qEtRbXLaU|;|fyS?=eRxO?7*p;Jy&`)l*BLJ!Q3Q+(6 diff --git a/test/assets/kaldi/mfcc-2.8683-3.8162-1.1250-0.3750-6620-false-3389-7-0.83-false-true-true-true-true-true-5-82.2365-5365-4579-1.0000-rectangular.ark b/test/assets/kaldi/mfcc-2.8683-3.8162-1.1250-0.3750-6620-false-3389-7-0.83-false-true-true-true-true-true-5-82.2365-5365-4579-1.0000-rectangular.ark deleted file mode 100644 index 2d2a4a0a3ac06ec14f9d4f1f4e834ab3c900878a..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 41 ccmd0;jL%F_U~qEtRbXLcU|?Wj1rpc*0Cq$JHUIzs diff --git a/test/assets/kaldi/mfcc-2.8690-3.2618-1.1875-0.9375-5646-true-491-8-0.89-false-false-true-false-false-true-2-59.9812-5397-2639-1.0000-hamming.ark b/test/assets/kaldi/mfcc-2.8690-3.2618-1.1875-0.9375-5646-true-491-8-0.89-false-false-true-false-false-true-2-59.9812-5397-2639-1.0000-hamming.ark deleted file mode 100644 index 2cd02945e66cee76f2ca4d4e1557c026bea44006..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 29 jcmd0;jL%F_U~qEtRbXLcU|?Wj0ul#jeLldLG071CW$6cf diff --git a/test/assets/kaldi/mfcc-2.9211-4.1440-0.7500-0.3750-7210-true-3666-4-0.93-false-false-true-true-false-false-4-94.5907-6682-4979-1.0000-hamming.ark b/test/assets/kaldi/mfcc-2.9211-4.1440-0.7500-0.3750-7210-true-3666-4-0.93-false-false-true-true-false-false-4-94.5907-6682-4979-1.0000-hamming.ark deleted file mode 100644 index 310e73e07bef502b16870a6b3224d5d803c5ec63..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 53 zcmd0;jL%F_U~qEtRbXLaU|?Wj0TLw_0v+RzIXl#!dG7G?o{-a>|Dlf8Uq?8c7W&}8 I`by9V0I=2*TL1t6 diff --git a/test/assets/kaldi/mfcc-2.9464-0.6798-1.1250-0.0625-4445-true-323-6-0.46-false-true-true-false-true-false-6-7.8133-3755-1137-1.0000-hanning.ark b/test/assets/kaldi/mfcc-2.9464-0.6798-1.1250-0.0625-4445-true-323-6-0.46-false-true-true-false-true-false-6-7.8133-3755-1137-1.0000-hanning.ark deleted file mode 100644 index 72747bae3cb4081c75182bee9f0db778f374b01d..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 501 zcmVpGCYo<0A+z>p6=utqRI82ER;NeR)vy;3B=fw-o>U=4~tkYv(7 zAaczh@ntG#JHM3 zzMrc=XqPxZKs_11giT4nm={^UiTI_zZaVzFgdCv0K+cfA7>s(r%)P6>5?rLesm`0e zpdJ&xpbf&mXn01zK=pt-No%6N#Q7z^ zKyJ*xP&_ukNOl81>|csM)Su=*x{Y{0Ks%7XfO_=5Sx|XEi|6J*#?}Er=WdZeK*fK* zz`%k(UvXtXynG!%-NM&DtZnE%fDJ1@P!1bEK+%rV zP;Y`ir1nX_ZLWF01Ib#y;1!iWu3L#f9C)=q`2O0ykztp=G+lMSKnVUn3mBq60ApLe rNvNj3C1V}HlLfKA0Kxh{&NP8Q;%{5PM}IcJ5q5FkaAKjpX~7aj)W5%bDo3O9Z4t2 g<2?>}q0&ySyEZt?dm-&q(|p9CZmYCY+15P{07IP_p#T5? diff --git a/test/assets/kaldi/mfcc-2.9643-3.8883-0.7500-0.2500-7373-false-1698-4-0.92-false-false-true-false-true-true-4-63.3036-6650-5500-1.0000-povey.ark b/test/assets/kaldi/mfcc-2.9643-3.8883-0.7500-0.2500-7373-false-1698-4-0.92-false-false-true-false-true-true-4-63.3036-6650-5500-1.0000-povey.ark deleted file mode 100644 index 67bf964d4d9e1303fcea47e2eb1602711928a7ab..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 101 zcmV-r0Gj`8d0%N{AOJ!}O&|mX000041ONa4faXNLDy1dBrgWV^Hj`n%0588iIE=$T z<{=Wmk`1{(0BSNlNa^uErkFy&s`=Zbt%JjzZIc`UvB3+= diff --git a/test/assets/kaldi/mfcc-3.0421-3.3343-1.0000-0.9375-6477-false-1402-5-0.99-false-true-true-true-true-true-4-26.1743-6381-5017-1.0000-hamming.ark b/test/assets/kaldi/mfcc-3.0421-3.3343-1.0000-0.9375-6477-false-1402-5-0.99-false-true-true-true-true-true-4-26.1743-6381-5017-1.0000-hamming.ark deleted file mode 100644 index 5c90e36332ecd0d82a77f708f326a6498410a9a1..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 37 ccmd0;jL%F_U~qEtRbXLcU|?Wj0TSo{0BKkQH2?qr diff --git a/test/assets/kaldi/mfcc-3.0919-4.5103-0.6250-1.0000-5323-true-937-5-0.95-false-false-true-true-true-false-5-82.2405-5130-5086-1.0000-hanning.ark b/test/assets/kaldi/mfcc-3.0919-4.5103-0.6250-1.0000-5323-true-937-5-0.95-false-false-true-true-true-false-5-82.2405-5130-5086-1.0000-hanning.ark deleted file mode 100644 index 2d2a4a0a3ac06ec14f9d4f1f4e834ab3c900878a..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 41 ccmd0;jL%F_U~qEtRbXLcU|?Wj1rpc*0Cq$JHUIzs diff --git a/test/assets/kaldi/mfcc-3.1463-4.5068-0.6875-0.3125-7587-true-3542-7-0.78-true-false-true-true-true-true-4-28.5808-7478-7326-1.0000-blackman.ark b/test/assets/kaldi/mfcc-3.1463-4.5068-0.6875-0.3125-7587-true-3542-7-0.78-true-false-true-true-true-true-4-28.5808-7478-7326-1.0000-blackman.ark deleted file mode 100644 index cb33b8ea0eb3639527a7c8885ec8abf7330c3d4f..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 53 zcmd0;jL%F_U~qEtRbXLaU|?Wj0TL~G1^YK#)!iRa$+VxLEMzZ`Z-3ybu6;r!lRc1c F3jm1}5F`Kq diff --git a/test/assets/kaldi/mfcc-3.2007-1.3677-1.1250-0.1875-4726-true-2027-4-0.74-false-true-false-false-true-false-4-3.5732-4583-3742-1.0000-povey.ark b/test/assets/kaldi/mfcc-3.2007-1.3677-1.1250-0.1875-4726-true-2027-4-0.74-false-true-false-false-true-false-4-3.5732-4583-3742-1.0000-povey.ark deleted file mode 100644 index 677343eb761979f1357df6c4f2702600f0b90e8c..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 133 zcmd0;jL%F_U~qEtRbXLfU|?Wj0TK#ZKiaEI5^;F*P56Lk!bj J|AgJS{Qzy85C8xG diff --git a/test/assets/kaldi/mfcc-3.2432-2.7787-0.8125-0.9375-4407-false-847-5-0.24-false-false-true-false-false-false-4-90.4067-3617-3615-1.0000-rectangular.ark b/test/assets/kaldi/mfcc-3.2432-2.7787-0.8125-0.9375-4407-false-847-5-0.24-false-false-true-false-false-false-4-90.4067-3617-3615-1.0000-rectangular.ark deleted file mode 100644 index a067e3d831111fd3a1370f61e242ff45111acd6f..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 37 rcmd0;jL%F_U~qEtRbXLcU|?Wj0TPKt8cycZ4;<(S-F!eMqIe$wq>>7? diff --git a/test/assets/kaldi/mfcc-3.2698-3.0361-1.0625-0.7500-4870-true-1281-7-0.64-false-true-true-false-true-true-3-28.5360-4401-3315-1.0000-blackman.ark b/test/assets/kaldi/mfcc-3.2698-3.0361-1.0625-0.7500-4870-true-1281-7-0.64-false-true-true-false-true-true-3-28.5360-4401-3315-1.0000-blackman.ark deleted file mode 100644 index 31304d163c71a0669d293ef0e8360e95e67fc074..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 45 xcmd0;jL%F_U~qEtRbXLaU|?Wj1`<8R+xN%DuRp+W&BhkUwg<8u7;f0?1ppVW4wV1^ diff --git a/test/assets/kaldi/mfcc-3.3078-4.9217-1.0000-0.3125-6758-true-760-5-0.98-true-true-true-true-false-true-3-97.4694-6022-5650-1.0000-rectangular.ark b/test/assets/kaldi/mfcc-3.3078-4.9217-1.0000-0.3125-6758-true-760-5-0.98-true-true-true-true-false-true-3-97.4694-6022-5650-1.0000-rectangular.ark deleted file mode 100644 index 07ec443f4d116d80d1352e849b6ad9e4022622d1..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 33 ncmd0;jL%F_U~qEtRbXLcU|?Wj1`-#hF0!AoMdsk@>{*Tgh@lCT diff --git a/test/assets/kaldi/mfcc-3.3206-0.0230-1.0625-0.5625-5744-true-3901-5-0.94-true-false-true-true-true-false-2-47.6031-5741-5524-1.0000-hanning.ark b/test/assets/kaldi/mfcc-3.3206-0.0230-1.0625-0.5625-5744-true-3901-5-0.94-true-false-true-true-true-false-2-47.6031-5741-5524-1.0000-hanning.ark deleted file mode 100644 index 9d86c0893b4873332f278aaa8762ee0b17d2aecb..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 29 ccmd0;jL%F_U~qEtRbXLcU|?Wj0unF)08f|$GXMYp diff --git a/test/assets/kaldi/mfcc-3.4022-1.2172-0.8750-0.3750-7737-false-612-5-0.35-true-true-true-false-false-false-2-65.1166-6852-5820-1.0000-blackman.ark b/test/assets/kaldi/mfcc-3.4022-1.2172-0.8750-0.3750-7737-false-612-5-0.35-true-true-true-false-false-false-2-65.1166-6852-5820-1.0000-blackman.ark deleted file mode 100644 index cc98d95c7571dca90309bc679df2060288a99bbd..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 45 zcmd0;jL%F_U~qEtRbXLeU|?Wj0unXO_D(b7ukBm3+|g;K{nY*cj@Ua*Vtlb502E>m Ab^rhX diff --git a/test/assets/kaldi/mfcc-3.4130-2.1158-1.1250-0.2500-5107-false-1362-7-0.73-true-true-true-false-true-false-7-7.0295-4988-4931-1.0000-povey.ark b/test/assets/kaldi/mfcc-3.4130-2.1158-1.1250-0.2500-5107-false-1362-7-0.73-true-true-true-false-true-false-7-7.0295-4988-4931-1.0000-povey.ark deleted file mode 100644 index 116242304908b821f325ddcf47ecaa0262e02f85..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 161 zcmV;S0ABxXd0%N{AOJ!}O&|mX000042LJ#707&*cU}H``Oq5wbu>Ci{VXHkrw`#4w zK!@)>05mzhAO#7&&~6jJ^=!01v;e_gc3Kt0AF;zfHtK*z+G*?FTxE#`k@QJ zBV0*8@`ixE0GN-wz$At}B;FOkd<@|~EDp`TY>6B{%%?%Vfa!`p&~E9zJ&T?|IDsI* PqyZN|28s*6%()sqMPouT diff --git a/test/assets/kaldi/mfcc-3.4339-2.6197-1.1250-0.1875-3341-true-1275-7-0.41-true-false-true-false-true-true-2-76.6062-3005-1680-1.0000-rectangular.ark b/test/assets/kaldi/mfcc-3.4339-2.6197-1.1250-0.1875-3341-true-1275-7-0.41-true-false-true-false-true-true-2-76.6062-3005-1680-1.0000-rectangular.ark deleted file mode 100644 index b6ceb2118d7dbf98523e493bf7814e765442f111..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 77 zcmd0;jL%F_U~qEtRbXLfU|?Wj0uoN^91buX>bHF`Wwt%TzsY+Q)TZuZxG}|6I&a;9 ghN7^28xGyJW4LEOnSUwb${n_Mp<2 ZBrT2uetdiftiJI(9r9y2u)2`r008bm7>xh` diff --git a/test/assets/kaldi/mfcc-3.5212-3.8251-0.8750-0.3125-4092-true-545-5-0.09-false-true-true-false-true-false-2-2.9422-1634-1000-1.0000-hanning.ark b/test/assets/kaldi/mfcc-3.5212-3.8251-0.8750-0.3125-4092-true-545-5-0.09-false-true-true-false-true-false-2-2.9422-1634-1000-1.0000-hanning.ark deleted file mode 100644 index 55f5420ac2c2a6d5ab9a4e1a65fa69bc94850ac3..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 53 zcmd0;jL%F_U~qEtRbXLZU|?Wj0uq8p866b%^w|G$)H?8B`~LkVr#kjCxC!q6clf5g IgKfDz0F>bpl>h($ diff --git a/test/assets/kaldi/mfcc-3.5261-2.0251-0.8750-0.6250-7926-false-3916-7-0.45-false-false-true-true-true-false-2-48.8818-7889-7527-1.0000-hanning.ark b/test/assets/kaldi/mfcc-3.5261-2.0251-0.8750-0.6250-7926-false-3916-7-0.45-false-false-true-true-true-false-2-48.8818-7889-7527-1.0000-hanning.ark deleted file mode 100644 index 9d86c0893b4873332f278aaa8762ee0b17d2aecb..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 29 ccmd0;jL%F_U~qEtRbXLcU|?Wj0unF)08f|$GXMYp diff --git a/test/assets/kaldi/mfcc-3.5390-1.6456-1.1250-0.1875-5425-true-2326-7-0.72-false-false-true-false-true-false-4-39.4555-4290-2715-1.0000-povey.ark b/test/assets/kaldi/mfcc-3.5390-1.6456-1.1250-0.1875-5425-true-2326-7-0.72-false-false-true-false-true-false-4-39.4555-4290-2715-1.0000-povey.ark deleted file mode 100644 index 0e96b90a8bf2a5f9fcdbd3cc4cadda2365eb5f0b..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 133 zcmV;00DAvzd0%N{AOJ!}O&|mZ000041ONa4(^I>^M|lcCA#4Ib0LT13U>TSz{`a{qy{&f diff --git a/test/assets/kaldi/mfcc-3.5643-2.2424-1.1875-0.8750-2140-true-59-4-0.98-true-true-true-false-false-false-2-36.7118-1463-1358-1.0000-hanning.ark b/test/assets/kaldi/mfcc-3.5643-2.2424-1.1875-0.8750-2140-true-59-4-0.98-true-true-true-false-false-false-2-36.7118-1463-1358-1.0000-hanning.ark deleted file mode 100644 index eb471febd9994d58b58da1dfa00ed32d2c6d664b..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 29 jcmd0;jL%F_U~qEtRbXLcU|?Wj0ur-lY8OVt2*ku#Etip}Igieh<0D3RJfUE>PGALp_eo~UZ!S}{JCK7%> zIu~NT08@*;z|ECCJSmR7kG5vNdrU1op=FOhR^ws50NnIFklX-15Gkd+j>&4jq?Z*v zF-VX<&Q*850Q9^)AUV;!H+=!V=Im*|8Wu`DJ%*G&-kM3i0O$+7u;UFrsH7deoM30a zb$uQ^(`Al7rjBpE01O>I0KoIS1)YUG+Z%bmNFszin$~SU2$xU3031KQa3={qD*J{# zW-lZ^V`#rU<_zAyT9(E>03YzaC=klNQEys4kn0^lwgW}J1vwPJNVl{;06a`StI2=u diff --git a/test/assets/kaldi/mfcc-3.7223-3.4282-1.0000-0.1250-6601-true-1923-6-0.05-false-true-true-false-false-true-4-19.2839-6596-6594-1.0000-hanning.ark b/test/assets/kaldi/mfcc-3.7223-3.4282-1.0000-0.1250-6601-true-1923-6-0.05-false-true-true-false-false-true-4-19.2839-6596-6594-1.0000-hanning.ark deleted file mode 100644 index ac728acd63ee07195d489b08c63ac3c5719fbb2e..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 181 zcmV;m080ODd0%N{AOJ!}O&|mc000041ONa4l650NI`SI78|co!RuGaw`Mps=Lf_@U zSiZ5qpAeEkOnH|T7rl`|YwL(XKg~_StJwHJIN7o(Ro} QkFYrqb++7|*=&I$075+#%K!iX diff --git a/test/assets/kaldi/mfcc-3.7750-0.8364-0.7500-0.3750-4995-true-1191-4-0.47-false-true-true-true-true-false-2-32.2463-4992-4951-1.0000-hamming.ark b/test/assets/kaldi/mfcc-3.7750-0.8364-0.7500-0.3750-4995-true-1191-4-0.47-false-true-true-true-true-false-2-32.2463-4992-4951-1.0000-hamming.ark deleted file mode 100644 index 8022fcc330a290b221a8ea63b8e31a847ed79136..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 37 pcmd0;jL%F_U~qEtRbXLaU|;|f4c{xQ85mYsGJLPt&A_l`Cjg;83D5ul diff --git a/test/assets/kaldi/mfcc-3.8120-0.4393-0.7500-1.0625-5917-false-1272-4-0.97-false-false-false-false-true-true-3-91.4723-3532-3056-1.0000-povey.ark b/test/assets/kaldi/mfcc-3.8120-0.4393-0.7500-1.0625-5917-false-1272-4-0.97-false-false-false-false-true-true-3-91.4723-3532-3056-1.0000-povey.ark deleted file mode 100644 index 1d1e54f1345975676060adce6e6a164f12918eeb..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 33 ccmd0;jL%F_U~qEtRbXLcU|?Wj1`@~s09D>m5+ IOI2Qy#2shI`8G|}NT>g1L_!w5e z)jb443~j4HL287+SlPzFUu2X(;z&|Jo@M_*uPnkrhfu4)d8(nn3%74T!{@L-FqQ&B vn1rxFk2_1i&XVWAk4dFKTxyFzQUn!3BK+q-S3L>8Nle^7BWN!``!8+4gWfkq diff --git a/test/assets/kaldi/mfcc-4.1851-3.5211-1.1250-0.8750-4768-false-562-4-0.05-true-true-true-true-false-false-2-36.9610-1982-741-1.0000-povey.ark b/test/assets/kaldi/mfcc-4.1851-3.5211-1.1250-0.8750-4768-false-562-4-0.05-true-true-true-true-false-false-2-36.9610-1982-741-1.0000-povey.ark deleted file mode 100644 index 657f1030526f601db30cdffd8a9002524cb814ef..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 29 jcmd0;jL%F_U~qEtRbXLcU|?Wj0umB4#hv^Pzdrx~TzUrm diff --git a/test/assets/kaldi/mfcc-4.2197-3.7252-0.9375-0.8125-7453-true-1561-4-0.06-false-false-true-true-true-false-2-44.7800-6612-4074-1.0000-blackman.ark b/test/assets/kaldi/mfcc-4.2197-3.7252-0.9375-0.8125-7453-true-1561-4-0.06-false-false-true-true-true-false-2-44.7800-6612-4074-1.0000-blackman.ark deleted file mode 100644 index 9d86c0893b4873332f278aaa8762ee0b17d2aecb..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 29 ccmd0;jL%F_U~qEtRbXLcU|?Wj0unF)08f|$GXMYp diff --git a/test/assets/kaldi/mfcc-4.2736-4.9552-0.7500-1.0000-5145-false-1705-4-0.33-false-false-false-true-false-false-4-70.9332-4857-2223-1.0000-blackman.ark b/test/assets/kaldi/mfcc-4.2736-4.9552-0.7500-1.0000-5145-false-1705-4-0.33-false-false-false-true-false-false-4-70.9332-4857-2223-1.0000-blackman.ark deleted file mode 100644 index bc5041f76f95a4fe7b00fd461195cd97957430a3..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 37 rcmd0;jL%F_U~qEtRbXLcU|?Wj0TLh6M4T?lSvoQt`LKV&-sJ}Yr>YBc diff --git a/test/assets/kaldi/mfcc-4.2787-1.6289-1.0625-0.8750-7792-true-5085-7-0.54-false-true-true-true-false-true-7-86.3861-7554-7506-1.0000-rectangular.ark b/test/assets/kaldi/mfcc-4.2787-1.6289-1.0625-0.8750-7792-true-5085-7-0.54-false-true-true-true-false-true-7-86.3861-7554-7506-1.0000-rectangular.ark deleted file mode 100644 index f6ddd229343a0a9403808ddb614273e8789c3a7a..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 49 zcmd0;jL%F_U~qEtRbXLcU|?Wj2NF9>x~)&PPT2pbD&@ez*|Y2&Kl?hYnElEjeCu>a E0B^byP5=M^ diff --git a/test/assets/kaldi/mfcc-4.3762-4.7209-0.9375-0.0625-5564-true-712-4-0.74-false-false-true-true-true-true-2-39.2887-4353-3521-1.0000-rectangular.ark b/test/assets/kaldi/mfcc-4.3762-4.7209-0.9375-0.0625-5564-true-712-4-0.74-false-false-true-true-true-true-2-39.2887-4353-3521-1.0000-rectangular.ark deleted file mode 100644 index e3fde9679db0ce25bf07dd2cfef727650362e590..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 69 zcmd0;jL%F_U~qEtRbXLbU|?Wj0upy_uyI}TITZTAGTL2$j8Xo`v diff --git a/test/assets/kaldi/mfcc-4.4229-0.4222-1.0625-1.1875-7822-true-4837-5-0.04-true-false-true-true-true-false-5-36.9181-7261-5703-1.0000-blackman.ark b/test/assets/kaldi/mfcc-4.4229-0.4222-1.0625-1.1875-7822-true-4837-5-0.04-true-false-true-true-true-false-5-36.9181-7261-5703-1.0000-blackman.ark deleted file mode 100644 index 2d2a4a0a3ac06ec14f9d4f1f4e834ab3c900878a..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 41 ccmd0;jL%F_U~qEtRbXLcU|?Wj1rpc*0Cq$JHUIzs diff --git a/test/assets/kaldi/mfcc-4.4663-3.5767-1.1250-1.1250-5844-false-799-7-0.37-false-false-true-true-true-false-4-34.2098-4554-1148-1.0000-hamming.ark b/test/assets/kaldi/mfcc-4.4663-3.5767-1.1250-1.1250-5844-false-799-7-0.37-false-false-true-true-true-false-4-34.2098-4554-1148-1.0000-hamming.ark deleted file mode 100644 index 5c90e36332ecd0d82a77f708f326a6498410a9a1..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 37 ccmd0;jL%F_U~qEtRbXLcU|?Wj0TSo{0BKkQH2?qr diff --git a/test/assets/kaldi/mfcc-4.5300-3.1492-1.0625-0.3750-7706-false-3813-6-0.74-false-false-true-false-true-false-2-71.8337-7672-5265-1.0000-povey.ark b/test/assets/kaldi/mfcc-4.5300-3.1492-1.0625-0.3750-7706-false-3813-6-0.74-false-false-true-false-true-false-2-71.8337-7672-5265-1.0000-povey.ark deleted file mode 100644 index a92a3692d24314aee0a986530c9e32cb475aacab..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 45 zcmd0;jL%F_U~qEtRbXLeU|?Wj0ul-@%^a>Q-?snB_s# AhyVZp diff --git a/test/assets/kaldi/mfcc-4.5474-0.7883-0.5625-1.0000-7283-false-2418-4-0.68-true-true-true-false-true-true-4-70.0635-7277-7265-1.0000-hamming.ark b/test/assets/kaldi/mfcc-4.5474-0.7883-0.5625-1.0000-7283-false-2418-4-0.68-true-true-true-false-true-true-4-70.0635-7277-7265-1.0000-hamming.ark deleted file mode 100644 index 5c90e36332ecd0d82a77f708f326a6498410a9a1..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 37 ccmd0;jL%F_U~qEtRbXLcU|?Wj0TSo{0BKkQH2?qr diff --git a/test/assets/kaldi/mfcc-4.5474-3.1023-0.7500-0.4375-7554-true-2566-6-0.31-false-false-false-false-false-false-5-76.9780-7368-7310-1.0000-hanning.ark b/test/assets/kaldi/mfcc-4.5474-3.1023-0.7500-0.4375-7554-true-2566-6-0.31-false-false-false-false-false-false-5-76.9780-7368-7310-1.0000-hanning.ark deleted file mode 100644 index d2cc315616154e0d3cf8e77f0a665507fc9cecb3..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 81 zcmd0;jL%F_U~qEtRbXLeU|?Wj1ri@j9Uc90n)Vt=Zawhw3XeniY#%3%X*(R33SHd) lYo7PPm%TFfyX#GymVYpIJi$H5uJ6|30~hm^9hg}CoB&;u9`^tM diff --git a/test/assets/kaldi/mfcc-4.5663-1.1270-1.1250-0.8125-6069-true-167-8-0.68-false-false-true-false-false-true-6-1.6240-2148-461-1.0000-rectangular.ark b/test/assets/kaldi/mfcc-4.5663-1.1270-1.1250-0.8125-6069-true-167-8-0.68-false-false-true-false-false-true-6-1.6240-2148-461-1.0000-rectangular.ark deleted file mode 100644 index e22cf6d939a10a3b1b0a3090c1ba84d78150749e..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 69 zcmV-L0J{Hed0%N{AOJ!}O&|mU000041^@s6FuzH_)x}%C$VIL{m%_lm1L!)xeh!&I bnfW%r>JDVT2hqMiNUgHIut zKZor=w@kIaQ0o3aN}UnE38L~rA7!-Hz=* P*#VBe{4EJURa2Y4CN9f@ diff --git a/test/assets/kaldi/mfcc-4.7216-2.4818-0.8125-0.3750-6723-true-2352-6-0.14-false-false-true-false-true-false-3-32.0303-5598-2579-1.0000-hanning.ark b/test/assets/kaldi/mfcc-4.7216-2.4818-0.8125-0.3750-6723-true-2352-6-0.14-false-false-true-false-true-false-3-32.0303-5598-2579-1.0000-hanning.ark deleted file mode 100644 index 1ae516620076270af00585ab155c0f7935912ce0..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 57 zcmd0;jL%F_U~qEtRbXLeU|;|f5$9*_KTvLD&%poCj=^!aeZc?L{Rb39_cI)C-FJX@ KvmHZ*kR1Tl91@NI diff --git a/test/assets/kaldi/mfcc-4.7919-2.6435-0.6250-0.5000-7971-false-1812-4-0.65-false-false-false-false-true-false-4-27.7648-7735-7419-1.0000-povey.ark b/test/assets/kaldi/mfcc-4.7919-2.6435-0.6250-0.5000-7971-false-1812-4-0.65-false-false-false-false-true-false-4-27.7648-7735-7419-1.0000-povey.ark deleted file mode 100644 index ce9606ef485ec65e58e53d31b84ea5056e111e8f..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 69 zcmd0;jL%F_U~qEtRbXLeU|?Wj0TK=`S?n(?Qn7zx)V7~tPPsjU{t-J3yPftnbNcpw Z=vZy%z?i=O)N$4WQ_{H{EH*6L4*NJ? diff --git a/test/assets/kaldi/mfcc-4.8140-0.4680-1.0625-0.6875-5252-true-569-6-0.85-true-false-true-true-false-false-6-56.4490-4397-4332-1.0000-hamming.ark b/test/assets/kaldi/mfcc-4.8140-0.4680-1.0625-0.6875-5252-true-569-6-0.85-true-false-true-true-false-false-6-56.4490-4397-4332-1.0000-hamming.ark deleted file mode 100644 index 2a5e0f31df8636dd4aa2bc759e4242b50fa9e110..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 45 zcmd0;jL%F_U~qEtRbXLcU|?Wj0}@L_gbp?)w;W7sJhlIgG1I{dQ&#VvAXDK402(z9 AaR2}S diff --git a/test/assets/kaldi/mfcc-4.9500-4.5916-1.1250-1.0625-5044-true-617-8-0.89-false-false-false-false-true-true-8-23.3238-2732-2677-1.0000-hanning.ark b/test/assets/kaldi/mfcc-4.9500-4.5916-1.1250-1.0625-5044-true-617-8-0.89-false-false-false-false-true-true-8-23.3238-2732-2677-1.0000-hanning.ark deleted file mode 100644 index ba991d473cae9aa4c61a1dd1696d9399779675f7..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 53 ccmd0;jL%F_U~qEtRbXLcU|?Y301|`%0G&7kIRF3v diff --git a/test/assets/kaldi/mfcc-4.9663-4.7867-1.1875-0.5000-2424-false-350-4-0.39-false-false-true-false-true-true-2-59.4319-1202-1063-1.0000-hamming.ark b/test/assets/kaldi/mfcc-4.9663-4.7867-1.1875-0.5000-2424-false-350-4-0.39-false-false-true-false-true-true-2-59.4319-1202-1063-1.0000-hamming.ark deleted file mode 100644 index 2504686c1e26a1155240e8bf63557726df3b681b..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 45 zcmd0;jL%F_U~qEtRbXLeU|?Wj0ul_@lJ=emm)_5?!eFn0=?Pngy(ew80-5Xq1E&m; diff --git a/test/assets/kaldi/spec-0.0016-0-4.6680-0.6250-0.2500-0.82-false-false-false-false-false-povey.ark b/test/assets/kaldi/spec-0.0016-0-4.6680-0.6250-0.2500-0.82-false-false-false-false-false-povey.ark deleted file mode 100644 index f25f4f58e2317a241080f9be0b704b5cbfe64ce5..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 141 zcmV;80CN9rd0%N{AOJ!}O&|mX000041^@s6S&@lB3MP<2sdA7(-h+EV&D2{#S*1ro z`MZrl``?p6ZDy1~1E_yN;MqDsYz59hzy6Cs3Yn2X)De_HpKpLcdTl~MzR4*;bZd-3 v#-EZwLiv+HPLzN_v06kyvR5uaUy6-EbnTQuHC>TGerSO~J|R&-hpSsb*dsXV diff --git a/test/assets/kaldi/spec-0.0121-0-4.9643-0.8750-0.1875-0.98-false-false-false-true-false-rectangular.ark b/test/assets/kaldi/spec-0.0121-0-4.9643-0.8750-0.1875-0.98-false-false-false-true-false-rectangular.ark deleted file mode 100644 index 64419a73280795c78960314100bf14a9718e2d13..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 117 zcmd0;jL%F_U~qEtRbXLeU|?Y301~F%(;ao0S{*$;Ep-%ho8stqsm-zaQ?+A!bB<$` zaf;)`*6EJf!mW;Tel2ypEiuJWQ?t#{QnSL*w<*EV@T`;LiMHvE+KR1?dwwrF&5kdg7CRn0UFdjOy2a5Tv&C_NYlq|c1s#r- wdJT?Oiv1l~AGA7l3syOPTF~kku&cvyOG>AspHG)#=k5+it=I-frzyW20IGN*;Q#;t diff --git a/test/assets/kaldi/spec-0.1088-0-0.6933-0.5000-0.7500-0.51-true-true-false-true-false-povey.ark b/test/assets/kaldi/spec-0.1088-0-0.6933-0.5000-0.7500-0.51-true-true-false-true-false-povey.ark deleted file mode 100644 index 81513e4276a9af80e0930ad084140a007702e520..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 61 zcmd0;jL%F_U~qEtRbXLaU|?Wj1rj|nQyqglCpxaw>v5bI6YIG5l&zz?-BibG$0s`8 QjOuax>mB8I*i+FF02zN2vH$=8 diff --git a/test/assets/kaldi/spec-0.1777-0-3.8992-1.0000-0.3125-0.96-true-false-false-true-false-blackman.ark b/test/assets/kaldi/spec-0.1777-0-3.8992-1.0000-0.3125-0.96-true-false-false-true-false-blackman.ark deleted file mode 100644 index 3cfeaaaccef109f49a29f163ae11869ac6a5984f..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 57 zcmd0;jL%F_U~qEtRbXLcU|?Y31QJFv^BjHbCpj{>_d6cp?{^ftGs!XNQL|%Vg{@0M3^^NS}v40NAU%0BGdC07m+~sH&;I03Z;%02r-20L+g) zxZl4&0IC-~AUY~P07kt%fEDUK06b6i@Z;ImgT*Qe-x zC5TTBaMpX8ze@*sy4-~3a60!$mh%?TeTp5LWOTntr5xdMU6}s2HN12B<{90A9U4px6w*0D3pQ01z6y0HQ3t09zhD zxT&wd>^(R@!1gG<0DShn02h?K0Net-0H72+01&V|fDx;`5Y;U|OxvHo!0&%P0C?m) jKwBR_04tq6006H!05GXMfTfYWKz=blsG!il0Q0TA=iV?n diff --git a/test/assets/kaldi/spec-0.4992-0-3.7665-0.4375-1.1250-0.42-false-false-true-false-true-rectangular.ark b/test/assets/kaldi/spec-0.4992-0-3.7665-0.4375-1.1250-0.42-false-false-true-false-true-rectangular.ark deleted file mode 100644 index 2d2a4a0a3ac06ec14f9d4f1f4e834ab3c900878a..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 41 ccmd0;jL%F_U~qEtRbXLcU|?Wj1rpc*0Cq$JHUIzs diff --git a/test/assets/kaldi/spec-0.5440-0-1.6641-0.9375-0.8750-0.13-true-true-true-true-true-rectangular.ark b/test/assets/kaldi/spec-0.5440-0-1.6641-0.9375-0.8750-0.13-true-true-true-true-true-rectangular.ark deleted file mode 100644 index 0fd91bbea354553f70525c939e33bd1954dd4c1f..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 57 ccmd0;jL%F_U~qEtRbXLcU|?Y31QNsm0IEa-IsgCw diff --git a/test/assets/kaldi/spec-0.5785-0-2.8162-1.1250-1.0625-0.17-false-false-false-true-false-blackman.ark b/test/assets/kaldi/spec-0.5785-0-2.8162-1.1250-1.0625-0.17-false-false-false-true-false-blackman.ark deleted file mode 100644 index e843eb3165fcf85330d2a6e01caa889cc5137af9..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 61 zcmd0;jL%F_U~qEtRbXLcU|?Y30unKq(;Ro4nBwT6Kg)6BiG_{_?@e@+G|6=onIq;H QA;{~P@ams~(fn@?03((Zk^lez diff --git a/test/assets/kaldi/spec-0.7797-0-2.5119-0.6250-0.5000-0.69-true-false-false-false-true-povey.ark b/test/assets/kaldi/spec-0.7797-0-2.5119-0.6250-0.5000-0.69-true-false-false-false-true-povey.ark deleted file mode 100644 index b2547d0eb969f8ac82605f99a8eb50d357bd587a..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 93 zcmV-j0HXhGd0%N{AOJ!}O&|mV000041^@s6fEsc>fHa!E01&f2;1Jb5z*;W9fGpcR zfF?!006g|R0PN>J0QpBgfHJ1P0K8Q`0MIkN082SOAbw51z=j;Z&|m#O0I8wAVB;by diff --git a/test/assets/kaldi/spec-0.8072-0-4.0404-0.5000-1.1875-0.74-false-false-false-true-true-hamming.ark b/test/assets/kaldi/spec-0.8072-0-4.0404-0.5000-1.1875-0.74-false-false-false-true-true-hamming.ark deleted file mode 100644 index 2d2a4a0a3ac06ec14f9d4f1f4e834ab3c900878a..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 41 ccmd0;jL%F_U~qEtRbXLcU|?Wj1rpc*0Cq$JHUIzs diff --git a/test/assets/kaldi/spec-0.8418-0-4.1771-0.3125-0.2500-0.48-false-false-true-true-false-hanning.ark b/test/assets/kaldi/spec-0.8418-0-4.1771-0.3125-0.2500-0.48-false-false-true-true-false-hanning.ark deleted file mode 100644 index cc250e187155e796b3ed9914001e1fba00a69b56..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 101 zcmd0;jL%F_U~qEtRbXLZU|?Wj1rmQE>Krw$G&nwuYjjN3u5xVslI!?#a*yLW!HJF@ zO5Kh(k{TV;14|tHuU9!H8CE$i?rCy#D6e*0;T`K}xUkyM#;)4&twyus1;!f3zt@5t E0oN%d?f?J) diff --git a/test/assets/kaldi/spec-0.8431-0-0.0728-0.7500-0.8125-0.10-true-false-true-false-false-povey.ark b/test/assets/kaldi/spec-0.8431-0-0.0728-0.7500-0.8125-0.10-true-false-true-false-false-povey.ark deleted file mode 100644 index c0a1b67666c333391bed64b666d9ff1c1d3395fc..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 93 zcmd0;jL%F_U~qEtRbXLaU|?Y31QPs@XE~+`&2mh*JIgV+eTL)VieAU<++mK*+dUlv xAE`TDNjT@AYCFd<^vHZi?n`qV*^W+j+^10O__)5tG08a9aq~hi$BX_(jsTT7A|L<& diff --git a/test/assets/kaldi/spec-0.8850-0-3.9292-0.3750-0.7500-0.27-true-false-false-true-false-blackman.ark b/test/assets/kaldi/spec-0.8850-0-3.9292-0.3750-0.7500-0.27-true-false-false-true-false-blackman.ark deleted file mode 100644 index c23452aee6f6df8f2bf70e7021e03ef49e9a139c..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 53 zcmd0;jL%F_U~qEtRbXLaU|?Wj0TTMgQypFAbvu^ZcRPBg diff --git a/test/assets/kaldi/spec-0.9625-0-2.5481-0.6875-1.0000-0.06-false-true-true-true-false-blackman.ark b/test/assets/kaldi/spec-0.9625-0-2.5481-0.6875-1.0000-0.06-false-true-true-true-false-blackman.ark deleted file mode 100644 index fc9ff74f1ac600e0ef0a123164ca0e74ffcae542..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 57 zcmd0;jL%F_U~qEtRbXLcU|?Y31QO>^@@yPt&Db~La@zh4&yLvx#cY9Mdw^ng N4VTmGcRV|`9{>-76~_Po diff --git a/test/assets/kaldi/spec-0.9854-0-3.8819-0.2500-1.0000-0.54-true-false-false-false-true-povey.ark b/test/assets/kaldi/spec-0.9854-0-3.8819-0.2500-1.0000-0.54-true-false-false-false-true-povey.ark deleted file mode 100644 index 1d1e54f1345975676060adce6e6a164f12918eeb..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 33 ccmd0;jL%F_U~qEtRbXLcU|?Wj1`@~s09YLkFMTjg^!3H|%V-Z&-VA-wVCA{STV9*)uTI?*f`(o4~@g zpW*M#y+AW;864*90h+NFXvSWk8MX`;{@4M{us_hjw-0EBJV&x E02U)ZpF diff --git a/test/assets/kaldi/spec-1.0743-0-0.4642-1.1250-0.6250-0.39-true-true-true-true-true-hanning.ark b/test/assets/kaldi/spec-1.0743-0-0.4642-1.1250-0.6250-0.39-true-true-true-true-true-hanning.ark deleted file mode 100644 index 1b3f06a3f31b14a95c28a5a86fee15928c05f011..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 89 ccmd0;jL%F_U~qEtRbXLcU|?Vo1QOH$029*#LI3~& diff --git a/test/assets/kaldi/spec-1.0788-0-1.4420-0.1875-0.3125-0.53-true-true-true-true-true-hanning.ark b/test/assets/kaldi/spec-1.0788-0-1.4420-0.1875-0.3125-0.53-true-true-true-true-true-hanning.ark deleted file mode 100644 index b81a55b5e9c8681d2d64507d9e492fd82e96bcc1..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 69 zcmd0;jL%F_U~qEtRbXLZU|?Wj1`-RdtJyPX&D#&c4>$w&C)AYMgYbjfCH5PB*n{zb Nm0tS~IDXm(!T|8M8^{0v diff --git a/test/assets/kaldi/spec-1.0802-0-4.5077-0.8750-0.1250-0.54-true-false-false-false-true-povey.ark b/test/assets/kaldi/spec-1.0802-0-4.5077-0.8750-0.1250-0.54-true-false-false-false-true-povey.ark deleted file mode 100644 index 487a223ba19cd0fe6155e3a7a7f7d62ab1f9937f..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 341 zcmWN>O(=tL90&04O3dUf#T?YUMFp#)KftK#x89B`6x>gmesv+^_fbxK zT(Wx}>T|P3!Rocp9FdqS6?)W`s%3`V)%%=kT43Y#&cw@x2u=+VnsOQzZJBGE;fy22 z`RFBAbYC&PLIOQm#z}`zp+o7u}I~{L+>U69>-tK50-REc@*yngZsmBoj8)Oci diff --git a/test/assets/kaldi/spec-1.1385-0-4.7380-0.6250-0.3125-0.23-true-false-false-false-false-hanning.ark b/test/assets/kaldi/spec-1.1385-0-4.7380-0.6250-0.3125-0.23-true-false-false-false-false-hanning.ark deleted file mode 100644 index 6f8447f8537b3af0e7c7b7729e5880b494418e30..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 117 zcmV-*0E+)@d0%N{AOJ!}O&|mW000041^@s6rrMi9l0uY0p7W7G(8Yd13P?{uKC(tZ z_w<%QX3&^HVltFLtapJy{w*aze@@3h;^>$`!uXd#()N=7C;_BYiv0|If*WK diff --git a/test/assets/kaldi/spec-1.1575-0-3.0941-0.5625-0.1250-1.00-true-true-true-true-true-povey.ark b/test/assets/kaldi/spec-1.1575-0-3.0941-0.5625-0.1250-1.00-true-true-true-true-true-povey.ark deleted file mode 100644 index a84b7b63519194f280771f2b6701d12859042ec6..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 237 zcmd0;jL%F_U~qEtRbXLbU|?Y31QHAk4m%l4r1vs}gxfMS2wF3k?AyceWP!~AMn<~> zYS-)pF8$xf@W8>Ef#H=E1B1ve28J~|7#ga8Y@VGAGJ-Y?zP`2^cVg`s8XR^r7^&GZ zEXmo+z#zMu;lODdhMp~Z7<6U!Ii$1hS6Ox#sOAVzU%*}lmmZ*9X4VWl{_bJWxn{%Q zr)Bry2%~*ubIF4Z^JZTFPeH0|2LuP;&qP diff --git a/test/assets/kaldi/spec-1.3142-0-4.8914-0.8750-0.1875-0.34-true-true-false-false-false-blackman.ark b/test/assets/kaldi/spec-1.3142-0-4.8914-0.8750-0.1875-0.34-true-true-false-false-false-blackman.ark deleted file mode 100644 index 51d04e5f11fdc4da54ef0575be4ecfa56179744f..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 245 zcmV23VA-{(~swiMVK;}e2X26+2CHzo9Rj8>!gE^l;b~2Vh&9#R?2I^ixn*2LK zxxkr0Y`;T6S+uD^vp1hXyf2nPOt6PRy477l``a!-V8oe0(9@7XC;_QK#)X0F_u0@c;k- diff --git a/test/assets/kaldi/spec-1.3612-0-2.9585-0.8750-0.0625-0.66-false-false-true-true-true-blackman.ark b/test/assets/kaldi/spec-1.3612-0-2.9585-0.8750-0.0625-0.66-false-false-true-true-true-blackman.ark deleted file mode 100644 index 76772f786df7b026088f5ec4e5a5fdbb184fc3ff..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 273 zcmV+s0q*{7d0%N{AOJ!}O&|mZ000042><{9fUrxxAjJy50E{iZ0JWLD0A7*206<(j z0DS^Iz#|Gi07xW10JZ`?fDtu60Du0E&*i0C3+sz!POY0Du#_07i~HfCPm;0C9*v zK)#5+811^hfQE3s05&YXP!R#Y0Js}G00b31z@j3)fYyhxx6waAy0U*k z^!R{5qveD_U=@8qYc)ebN4W@&>#|8s^xBSwfpmg9UuhUZm5&hmjlEntK}E=Y$#?c{tx&4*G! X9GH<{9<;#shrId9+X0n(;gWQ%u>G_61E$L}N zoe5w;_}fWA%S`$m~T{Sb*kWXd-|IEFSsLFhC=DB&wX4G}kT diff --git a/test/assets/kaldi/spec-1.5178-0-2.8631-1.0000-0.8125-0.95-true-true-true-true-false-blackman.ark b/test/assets/kaldi/spec-1.5178-0-2.8631-1.0000-0.8125-0.95-true-true-true-true-false-blackman.ark deleted file mode 100644 index 4c228ddfad8b4bb357ff3f5502337eddc7238a5f..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 57 zcmd0;jL%F_U~qEtRbXLcU|?Y31QM&WXF1-=p6R$NX_ey)jx~-hg;N~Yo|xg-Rh{QJ Mf!p2Da-yyy0OX1i#Q*>R diff --git a/test/assets/kaldi/spec-1.5403-0-0.0133-1.1875-0.2500-0.59-true-false-true-false-false-blackman.ark b/test/assets/kaldi/spec-1.5403-0-0.0133-1.1875-0.2500-0.59-true-false-true-false-false-blackman.ark deleted file mode 100644 index 32d13281b5de43df8ea682ed17247d330a54883a..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 361 zcmV-v0ha!4d0%N{AOJ!}O&|mX000045dZ)H;!vMKi~gxW9>|+P@(H6s3uLfC%MY+Y zTU(()rh=P6#k8V9q}`Q47^H(ieRPXKJqUS0^fGHfTYhLkt`b>6rWIvDc=ew_)S{F@ z6hNOr2AGpUEXbxopdhe87zC?9an6iEK4+Xk5pJ77T-=O7Bd=;f@5g*WS9)ndk05VB zfs|)KM!9D}tO%b$x+bMTp=zK(6XB9UGL@=9a}2RTg2k&r`R9m1yceHA1jC#`hS-Eb z&g6AL6eUSPD#BPnS`P?8kLX1~iN_5=aZI2=%uuO8lyag$M#P*!b>^%=ko&Jeet4)s zl&+CMS|yo5`dFDk=OU3oI@NwbR_%mAzXy6j#I$xnU`B31(=}v412&*RyR@7^Aa#&I z5W$>5hB2){GL@}Ch?kl{%ATP?h#jRtls5qU!aMtO+0Hxc%DCnEN0HEAGfMp}T0I>o-pg0OYNLH3V Lm~;InzYnsF$D diff --git a/test/assets/kaldi/spec-1.5669-0-0.5190-0.8750-0.2500-0.56-true-true-false-false-true-blackman.ark b/test/assets/kaldi/spec-1.5669-0-0.5190-0.8750-0.2500-0.56-true-true-false-false-true-blackman.ark deleted file mode 100644 index 70c3a9c35cc4506d191a81a80197bfb7793ad1bf..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 181 zcmV;m080ODd0%N{AOJ!}O&|mX000042mk;80F0`0JwZS;76FhfO>a67)p}B z04E_oz{FcW08E5DWbi@20MU#+z|crP0C6n7fauIWK%;=ZfKL;@0DvqyfCLS|07z*) zVChXi0O_>7uu8E%u)|TmfIyhP01);&knP~V0N5qGAW2R?04l7#une?6;7|U(K%i5; j0Dxt?9FcH904N5&&^emF0RGB707N%FKo)R6*m;gWOe#p} diff --git a/test/assets/kaldi/spec-1.5754-0-0.9540-1.0000-0.9375-0.20-false-false-true-true-true-rectangular.ark b/test/assets/kaldi/spec-1.5754-0-0.9540-1.0000-0.9375-0.20-false-false-true-true-true-rectangular.ark deleted file mode 100644 index 0fd91bbea354553f70525c939e33bd1954dd4c1f..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 57 ccmd0;jL%F_U~qEtRbXLcU|?Y31QNsm0IEa-IsgCw diff --git a/test/assets/kaldi/spec-1.5959-0-0.9033-0.7500-1.0000-0.14-true-true-true-true-false-hanning.ark b/test/assets/kaldi/spec-1.5959-0-0.9033-0.7500-1.0000-0.14-true-true-true-true-false-hanning.ark deleted file mode 100644 index ed3633614377615f972728b4da5168f6449e57c8..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 57 zcmd0;jL%F_U~qEtRbXLcU|?Y31QI3;GaUV-dL08Br#t%Xo$hG2u-EbFkt9bhD_h6& L5)6*!zt|lCpH~oO diff --git a/test/assets/kaldi/spec-1.6923-0-3.5626-0.6875-1.0625-0.27-true-false-true-false-false-rectangular.ark b/test/assets/kaldi/spec-1.6923-0-3.5626-0.6875-1.0625-0.27-true-false-true-false-false-rectangular.ark deleted file mode 100644 index bbf924d34ed925be53666a4b141004e5bfa90d45..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 57 zcmd0;jL%F_U~qEtRbXLcU|?Y31QOETvmHYwPH=prw9ql4Z-FB>Z@y!uRHNh8olTCr MpO!kt$EG?00I;SJ)c^nh diff --git a/test/assets/kaldi/spec-1.6972-0-1.0863-1.1875-0.8750-0.86-true-true-true-true-false-rectangular.ark b/test/assets/kaldi/spec-1.6972-0-1.0863-1.1875-0.8750-0.86-true-true-true-true-false-rectangular.ark deleted file mode 100644 index 1170a149fba6eaa50b6aadee5c9dc79532134d8f..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 89 zcmd0;jL%F_U~qEtRbXLcU|?Vo1QLS#XFKW}^f^uy>vWv@z29+P=6px>*{dC!s}?)P s#k4s(8}>PJo^N-Y?OW?;JEzq#)Fs!k<3ocZ^VAAQo`_P%t6a5?0O2DZv;Y7A diff --git a/test/assets/kaldi/spec-1.7440-0-0.5308-0.5000-0.1250-0.33-true-true-false-false-false-hamming.ark b/test/assets/kaldi/spec-1.7440-0-0.5308-0.5000-0.1250-0.33-true-true-false-false-false-hamming.ark deleted file mode 100644 index 50f7ac538d131a97c5f2b694fbb10f1fba89b9a4..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 221 zcmV<303!cwd0%N{AOJ!}O&|mc000041poj5saKUj!3mK;Hm-(2FY{eN<5@*P3c8g+ zWTTToxZaCF68>aCWGO5`iI|f?p{0;P-lvQ~I{j8bfp*?NqCAyB>pYV|b~%he!KGe7 zgbWiwPBoN4ibRq@wQr0;#U@)p+>;nVf%B6=fCiC4rI(CBf^=9xz_?C8A5N7)wTqKM z4lRs9*+E}HcCZ*h>A{mh)pC(RHjs=#V#`=TXc!Vf+Mks{exH&-*zSu#XhmW{$JI4K XKyH;mz7df@d@zJT@DFD}dk9ZKTv=KU diff --git a/test/assets/kaldi/spec-1.7642-0-0.4833-0.2500-0.8125-0.94-false-true-false-true-false-blackman.ark b/test/assets/kaldi/spec-1.7642-0-0.4833-0.2500-0.8125-0.94-false-true-false-true-false-blackman.ark deleted file mode 100644 index d5d04e7545a03d2e17b018bab40c7c1ca3e51efb..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 45 tcmd0;jL%F_U~qEtRbXLaU|?Wj1`@Y2W;%lKlDB=1_S&<-c&cHQBLEkw4cY(z diff --git a/test/assets/kaldi/spec-1.8072-0-0.8085-0.5000-0.2500-0.96-false-true-true-false-false-hanning.ark b/test/assets/kaldi/spec-1.8072-0-0.8085-0.5000-0.2500-0.96-false-true-true-false-false-hanning.ark deleted file mode 100644 index ea6febeffeeb8db48d853a9ceca3c14bb92dc3f3..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 121 zcmd0;jL%F_U~qEtRbXLdU|;|f8(X>@FBwm8)Cuo&3=hq5ykQmMxOj25<4u!^j`;z- zj@}zH9M?ODItEvCIZl$F=xATm>!@6x>G=P>t)sJRm!l)oL`UhuUPsOzpqRG3Bfn?2 W<{90LXK^P$K)kfPxG@0NI5 z06_4*U}ven2!s;A_(z4n092Da&@;Y20HCD30O0XH;7N?X@Xd_Bz+4@_07KzDKxo-M z07Pd!P{Ef!0Plr9K(EiffI%a^Af|Ia0NTJlfDmy$VCpnK0F0eHa2Q3vfcLgOkT|Qq Xpyh8r0Gv?1p!PODfPN}JK>lh!+YE3{ diff --git a/test/assets/kaldi/spec-1.8836-0-4.5145-0.8750-1.0625-0.40-false-false-true-true-true-hanning.ark b/test/assets/kaldi/spec-1.8836-0-4.5145-0.8750-1.0625-0.40-false-false-true-true-true-hanning.ark deleted file mode 100644 index 0fd91bbea354553f70525c939e33bd1954dd4c1f..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 57 ccmd0;jL%F_U~qEtRbXLcU|?Y31QNsm0IEa-IsgCw diff --git a/test/assets/kaldi/spec-1.8946-0-4.1442-0.3125-0.8750-0.73-true-true-true-true-true-rectangular.ark b/test/assets/kaldi/spec-1.8946-0-4.1442-0.3125-0.8750-0.73-true-true-true-true-true-rectangular.ark deleted file mode 100644 index 8705ca0daa9cc976db070866a00033cd75c66e6a..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 61 zcmd0;jL%F_U~qEtRbXLaU|?Wj1riL&<#r6;Blk6YJ-jcVfz$p&a_D}b*gl|`9Z<{; LD7ODWa;QB3F!vSR diff --git a/test/assets/kaldi/spec-1.8988-0-3.0931-1.0625-0.3125-0.35-true-true-true-true-true-hanning.ark b/test/assets/kaldi/spec-1.8988-0-3.0931-1.0625-0.3125-0.35-true-true-true-true-true-hanning.ark deleted file mode 100644 index 1b3f06a3f31b14a95c28a5a86fee15928c05f011..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 89 ccmd0;jL%F_U~qEtRbXLcU|?Vo1QOH$029*#LI3~& diff --git a/test/assets/kaldi/spec-1.9093-0-2.4939-0.7500-0.5000-0.47-true-false-true-false-true-blackman.ark b/test/assets/kaldi/spec-1.9093-0-2.4939-0.7500-0.5000-0.47-true-false-true-false-true-blackman.ark deleted file mode 100644 index 57c8a94e3ed06e05f1b2e6a602cc4e56529ab664..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 129 zcmV-{0Dk{%d0%N{AOJ!}O&|mV000042><{9fM7m8061elfERT>&;f=&0IngvK#`)p z06j`RFeC{-Adpu-0E(Nvz~76%0Mc!~z~0V2&>OP9fY%tlKtSa_D5%)Kz&t3w05{>i jVDVl*0MO{Wkh!_PU{S_D0R8ShfG;J#5Ehg_Ku$frI^8pg diff --git a/test/assets/kaldi/spec-1.9501-0-4.3519-0.4375-0.2500-0.61-false-false-true-false-true-hanning.ark b/test/assets/kaldi/spec-1.9501-0-4.3519-0.4375-0.2500-0.61-false-false-true-false-true-hanning.ark deleted file mode 100644 index b617e9162dfe422ccfbd9ef35a492b9775b6fc7b..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 121 zcmd0;jL%F_U~qEtRbXLdU|;|f4W=mwv*(a=(w`T~9 zvulufxOan=_kISKmHQg*OxnlruF94n!ocPbx88vRVrTX_+&;38fn}Zz151WY91G)t Z1Cy2Q8&dV{86L#%Ww`xuZ%1630|0)gFFpVO diff --git a/test/assets/kaldi/spec-2.0137-0-3.1007-0.6250-1.0625-0.67-true-false-true-true-true-rectangular.ark b/test/assets/kaldi/spec-2.0137-0-3.1007-0.6250-1.0625-0.67-true-false-true-true-true-rectangular.ark deleted file mode 100644 index 0fd91bbea354553f70525c939e33bd1954dd4c1f..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 57 ccmd0;jL%F_U~qEtRbXLcU|?Y31QNsm0IEa-IsgCw diff --git a/test/assets/kaldi/spec-2.0175-0-2.9099-1.0000-0.5625-0.28-true-false-true-false-false-blackman.ark b/test/assets/kaldi/spec-2.0175-0-2.9099-1.0000-0.5625-0.28-true-false-true-false-false-blackman.ark deleted file mode 100644 index c8add5b72c852f0a3005e130e8392442eeb3ed46..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 93 zcmV-j0HXhGd0%N{AOJ!}O&|mU000042><{9%&eV3SO=v+^_8?i;q9zJj<23U*UObb zr51-lm7ah>*c?bf!GE7YaxsuW25 pcXE#B8~Pk?JecHo{pw7|a}~XgG0PhqA84dGe!Upv82C%a5dgJkAwB>A diff --git a/test/assets/kaldi/spec-2.2457-0-1.7040-0.7500-0.5625-0.98-true-false-false-false-true-hamming.ark b/test/assets/kaldi/spec-2.2457-0-1.7040-0.7500-0.5625-0.98-true-false-false-false-true-hamming.ark deleted file mode 100644 index 254a44e787cb983b4aedbc2336a82ac5df7f78d7..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 77 zcmd0;jL%F_U~qEtRbXLaU|?Wj2NDcbrgjV>-)$KV^zLN{=-j=dz1Kcs%4U0kkS+EN cRi^uZa(fx}_u2yGtT(jx?gz^42g>aS0A<-5RsaA1 diff --git a/test/assets/kaldi/spec-2.2893-0-1.0286-0.2500-0.5000-0.80-true-false-true-false-false-hanning.ark b/test/assets/kaldi/spec-2.2893-0-1.0286-0.2500-0.5000-0.80-true-false-true-false-false-hanning.ark deleted file mode 100644 index ab08d20abc8986e1e577c9d7d9bc7e20dc85f2fa..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 57 zcmd0;jL%F_U~qEtRbXLeU|;|fURygHBbBQhjdB_t-9)E4b~to6MpOkj%BRkBd@!%t Ju`oT}5dfZ35Xt}m diff --git a/test/assets/kaldi/spec-2.3371-0-4.4192-0.8125-0.6250-0.30-true-false-true-true-true-rectangular.ark b/test/assets/kaldi/spec-2.3371-0-4.4192-0.8125-0.6250-0.30-true-false-true-true-true-rectangular.ark deleted file mode 100644 index 0fd91bbea354553f70525c939e33bd1954dd4c1f..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 57 ccmd0;jL%F_U~qEtRbXLcU|?Y31QNsm0IEa-IsgCw diff --git a/test/assets/kaldi/spec-2.3789-0-3.0234-0.1875-0.3750-0.54-true-false-true-true-true-hamming.ark b/test/assets/kaldi/spec-2.3789-0-3.0234-0.1875-0.3750-0.54-true-false-true-true-true-hamming.ark deleted file mode 100644 index 0c0fb83483900f28016915ca50fd3cca01b7d838..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 57 zcmd0;jL%F_U~qEtRbXLeU|;|f45xnVonYF#KO%hgeg=m+8-}?Sb`6Rtb_@(RZ67%2 K*cU9TwFdyoQW4bv diff --git a/test/assets/kaldi/spec-2.3831-0-4.8325-0.2500-1.1250-0.34-true-true-true-false-true-povey.ark b/test/assets/kaldi/spec-2.3831-0-4.8325-0.2500-1.1250-0.34-true-true-true-false-true-povey.ark deleted file mode 100644 index 1d1e54f1345975676060adce6e6a164f12918eeb..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 33 ccmd0;jL%F_U~qEtRbXLcU|?Wj1`@~s09<{9YLuBlK!=S%Dyf)3&U%zV4Bdi3o`QKn z)k9-J2gy!BNN6lU$+Ve4{85KN12dRGH~g4Eicg9`O6wTto9DQ%X_2GY%sxj)mS#uobp?*I MzeYG#-*1M}+E)9+X L?;9L>k{cZXyw(vw diff --git a/test/assets/kaldi/spec-2.4480-0-3.8782-0.5625-1.1250-0.10-false-true-true-false-true-rectangular.ark b/test/assets/kaldi/spec-2.4480-0-3.8782-0.5625-1.1250-0.10-false-true-true-false-true-rectangular.ark deleted file mode 100644 index 0fd91bbea354553f70525c939e33bd1954dd4c1f..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 57 ccmd0;jL%F_U~qEtRbXLcU|?Y31QNsm0IEa-IsgCw diff --git a/test/assets/kaldi/spec-2.5164-0-2.7455-0.8750-0.9375-0.55-false-true-false-false-false-hanning.ark b/test/assets/kaldi/spec-2.5164-0-2.7455-0.8750-0.9375-0.55-false-true-false-false-false-hanning.ark deleted file mode 100644 index c5ff017a494c56a6126c29ccd3994eb214558976..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 53 zcmd0;jL%F_U~qEtRbXLcU|?Y301{#EdL3mlIvp>2%ye85FvT&_Bg?V&zqzAcjf7)= H2)iQye~b^s diff --git a/test/assets/kaldi/spec-2.5316-0-2.3286-0.7500-0.7500-0.61-false-false-false-false-true-rectangular.ark b/test/assets/kaldi/spec-2.5316-0-2.3286-0.7500-0.7500-0.61-false-false-false-false-true-rectangular.ark deleted file mode 100644 index c4c54f45502667e6eb94603254e267fd830f0a4c..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 77 zcmd0;jL%F_U~qEtRbXLaU|?Wj2NDbtOZGG*rSETeP;Y0`Bzr*P%$ofN>~GpJ-0`#l c%Gm(r?16IoESh8;49={ve_(%eA5d-&0JvNn`2YX_ diff --git a/test/assets/kaldi/spec-2.5487-0-3.8457-1.1875-0.9375-0.63-true-true-true-true-false-hanning.ark b/test/assets/kaldi/spec-2.5487-0-3.8457-1.1875-0.9375-0.63-true-true-true-true-false-hanning.ark deleted file mode 100644 index a0885fee884f439f3f2698f16427e5ccf4d29ae3..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 89 zcmd0;jL%F_U~qEtRbXLcU|?Vo1QLS#XFGawn>)6pWH>U5^gBKfpY7-`G~ZDzY>uOy t$|T1N1!azHZ=D@0*BChNJgw|l#{1f#D2c;SgnhBYXV;4kyX>|(003qa9YO#A diff --git a/test/assets/kaldi/spec-2.6121-0-4.3165-0.6875-1.1875-0.19-false-true-true-true-false-rectangular.ark b/test/assets/kaldi/spec-2.6121-0-4.3165-0.6875-1.1875-0.19-false-true-true-true-false-rectangular.ark deleted file mode 100644 index d53af666daa831c58a835ab839c131edb82d617a..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 57 zcmd0;jL%F_U~qEtRbXLcU|?Y31QLB*(;W9MYj-qwJ>N0Xd!b{9LAm3XbIp!EAuW!z MTdN!sZ)7?G0MhppOaK4? diff --git a/test/assets/kaldi/spec-2.6768-0-2.4181-1.1250-0.6875-0.14-true-true-false-false-true-hamming.ark b/test/assets/kaldi/spec-2.6768-0-2.4181-1.1250-0.6875-0.14-true-true-false-false-true-hamming.ark deleted file mode 100644 index 5dd34d8af4065d1300b33e8af085f9dcc3e6fa46..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 101 zcmd0;jL%F_U~qEtRbXLaU|?Y30ul@jCN>E|%l0*#m)XbQG2ND7kFssT+5P(%`crK! zR!!Y+aL{=F3(=SM3>7AO9E6tH0oBlTwLU?sjZwuXS9&WaQRnDYobDKTs>N}dQHNvg Pgciqb<+YBlI7=M?5y%u+ diff --git a/test/assets/kaldi/spec-2.9074-0-1.6849-1.1250-0.6250-0.79-false-true-true-false-false-blackman.ark b/test/assets/kaldi/spec-2.9074-0-1.6849-1.1250-0.6250-0.79-false-true-true-false-false-blackman.ark deleted file mode 100644 index 77170ed57f728eed9f9adbd69922ab24ea12883c..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 157 zcmV;O0Al}bd0%N{AOJ!}O&|mU000045dZ)HfDo%e(7dZbG8L;qP7IYntZTJF!jZW_ zOMJ0G_P(7#n5L*f-fW~nIt`scdykYskY9{JvHXrfCeMRGIAMH2qs&}E9#*SCRyM9d ze9o&uF`t$}bPu&bWi7cufgiF#0b89xRidUr2t%hqLkponRJD;oWowW@D+rE3`%8yG LVmO9DTAF}CGUGj2 diff --git a/test/assets/kaldi/spec-2.9303-0-3.5172-0.5000-0.5000-0.04-true-false-true-true-true-rectangular.ark b/test/assets/kaldi/spec-2.9303-0-3.5172-0.5000-0.5000-0.04-true-false-true-true-true-rectangular.ark deleted file mode 100644 index d8dadfd361bf922feec67b4ccf1eabcc57cc27cc..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 61 zcmd0;jL%F_U~qEtRbXLaU|?Wj1riJe#dZu+RqYO3-nXyer^EgW(pmd~V*7w%`xvh5 Ovs>`f!Ty1CmOTI{E)|df diff --git a/test/assets/kaldi/spec-3.0700-0-3.5254-0.7500-0.8750-0.96-false-true-false-true-false-povey.ark b/test/assets/kaldi/spec-3.0700-0-3.5254-0.7500-0.8750-0.96-false-true-false-true-false-povey.ark deleted file mode 100644 index 6e04e9a91b8e5a02a29dd5267daf4ed823e30f48..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 49 zcmd0;jL%F_U~qEtRbXLcU|?Wj2NHR_{f={-COR&?H`6gDq1TaFQQfgAtHI&+wI&Au DGkgxk diff --git a/test/assets/kaldi/spec-3.1297-0-0.3513-0.4375-0.3125-0.20-true-true-true-true-false-povey.ark b/test/assets/kaldi/spec-3.1297-0-0.3513-0.4375-0.3125-0.20-true-true-true-true-false-povey.ark deleted file mode 100644 index d631887dae639df4e71818a205476f80a4a8a1cd..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 81 zcmd0;jL%F_U~qEtRbXLeU|?Wj1rkTxXfDsp7K@9M~Tc9Ns!kv_+^ kx*kX8`vs0a<&+(lDo%0Svu}bUQ$mj;|N275OIr4h0N>LabpQYW diff --git a/test/assets/kaldi/spec-3.2080-0-1.8656-0.3125-0.4375-0.55-false-false-true-true-true-hanning.ark b/test/assets/kaldi/spec-3.2080-0-1.8656-0.3125-0.4375-0.55-false-false-true-true-true-hanning.ark deleted file mode 100644 index d3403dbcb838f5397682192652886c927b406951..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 81 zcmV-X0IvUSd0%N{AOJ!}O&|mV000041poj50FZAy0PZk700>UJ0LZPo0Q9Rp0MKbZ nfL66W06b$U}FzIz}l5Q zz|NjN0BbP5$Qq}=fHnF)fK)6#08A^rfV0g$zG9eSw=nPaTs%1)`xrs=uc}ayy+t X*@}@tn7D{Rr=E*Jr1FMAHe`oE=HXm} diff --git a/test/assets/kaldi/spec-3.5370-0-1.7032-0.3750-0.8750-0.17-false-true-true-false-true-hamming.ark b/test/assets/kaldi/spec-3.5370-0-1.7032-0.3750-0.8750-0.17-false-true-true-false-true-hamming.ark deleted file mode 100644 index 2d2a4a0a3ac06ec14f9d4f1f4e834ab3c900878a..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 41 ccmd0;jL%F_U~qEtRbXLcU|?Wj1rpc*0Cq$JHUIzs diff --git a/test/assets/kaldi/spec-3.5378-0-3.6594-0.2500-0.6250-0.54-true-true-true-true-true-rectangular.ark b/test/assets/kaldi/spec-3.5378-0-3.6594-0.2500-0.6250-0.54-true-true-true-true-true-rectangular.ark deleted file mode 100644 index f1b6968f5b7915b0055bee11ef7debbb095b668f..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 45 wcmd0;jL%F_U~qEtRbXLaU|?Wj1`-UCdu$k)4 t?5Ej|8=kLmbh*0T@!qi|j$BFEj>0{ijt1PWjuvsHj%@MTj{48j9RaUrA`t)p diff --git a/test/assets/kaldi/spec-3.6308-0-1.1407-0.3125-0.0625-0.17-false-true-true-true-true-rectangular.ark b/test/assets/kaldi/spec-3.6308-0-1.1407-0.3125-0.0625-0.17-false-true-true-true-true-rectangular.ark deleted file mode 100644 index 4e753b682380e96d9d64a506d18e2eda698aac31..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 341 zcmWN>ODIHP6ae6ZnUtm|8x8U(*?6vS&42zIQ5dl!rYNI4n)0Z@%2~)v3R@A~loetk zkIX&y7fKln#$GjT|9h#-Y6nAU= z7G1f~Xqn-!+o**3fPlnGgtmR5MiThVu`J-!F{Eg$x^Ec1PXy$Zn-8al z66R)2x(+a9H=tg-#b5r2q-Zay#X<=qV;q|`uqfZ5;PKO>k}L*y+(kJ7(f6_1Es7$tF5VGA1RAaC3z~3II#vZ6`lIvfwi_c^XSndx{wvdytZqsOsvvWX)A4xkOo diff --git a/test/assets/kaldi/spec-3.7632-0-3.7271-0.6875-0.3125-0.86-true-true-true-true-true-hamming.ark b/test/assets/kaldi/spec-3.7632-0-3.7271-0.6875-0.3125-0.86-true-true-true-true-true-hamming.ark deleted file mode 100644 index a419736fc1ba43c76dfa7ca2483200243b048f3d..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 93 zcmd0;jL%F_U~qEtRbXLaU|?Y31QHDU=G!tHxU!q!LZ>x@fZiSkfe+RUv$onOxQOrf sux{PI!$ai&!`}IO88%$82CCW3z@cXYRI?kXW)Dz}eSmeVJy4AU04Vz&?f?J) diff --git a/test/assets/kaldi/spec-3.7759-0-1.7002-1.0625-0.6875-0.42-false-false-true-true-true-hamming.ark b/test/assets/kaldi/spec-3.7759-0-1.7002-1.0625-0.6875-0.42-false-false-true-true-true-hamming.ark deleted file mode 100644 index 1b3f06a3f31b14a95c28a5a86fee15928c05f011..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 89 ccmd0;jL%F_U~qEtRbXLcU|?Vo1QOH$029*#LI3~& diff --git a/test/assets/kaldi/spec-3.7921-0-3.4087-0.2500-1.0000-0.54-true-true-true-false-false-blackman.ark b/test/assets/kaldi/spec-3.7921-0-3.4087-0.2500-1.0000-0.54-true-true-true-false-false-blackman.ark deleted file mode 100644 index 5c16493cc3dd66e4ff55914228b8a15be1298f44..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 33 ncmd0;jL%F_U~qEtRbXLcU|?Wj1`_jRCpfO^pXZpgexV}(fKCX@ diff --git a/test/assets/kaldi/spec-3.7954-0-3.5651-0.5000-0.8125-0.06-false-true-true-false-true-blackman.ark b/test/assets/kaldi/spec-3.7954-0-3.5651-0.5000-0.8125-0.06-false-true-true-false-true-blackman.ark deleted file mode 100644 index d4a6008afb84abe24919fd1b365d71d9bea2e040..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 61 zcmd0;jL%F_U~qEtRbXLaU|?Wj1riK88}=~#JHB^h#cY6LwhN@1 N_cI)OW(ySC4*(+46)pe( diff --git a/test/assets/kaldi/spec-3.7990-0-3.0026-0.6250-1.0000-0.82-false-true-false-true-true-hamming.ark b/test/assets/kaldi/spec-3.7990-0-3.0026-0.6250-1.0000-0.82-false-true-false-true-true-hamming.ark deleted file mode 100644 index 088b2337ddf515f9da058bf9cdb87acf1c445b90..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 45 ccmd0;jL%F_U~qEtRbXLcU|?Wj0}{9Z0E0LKHvj+t diff --git a/test/assets/kaldi/spec-3.8659-0-1.7487-1.1875-0.3750-1.00-true-true-true-true-false-hanning.ark b/test/assets/kaldi/spec-3.8659-0-1.7487-1.1875-0.3750-1.00-true-true-true-true-false-hanning.ark deleted file mode 100644 index 1e5b22da375a9591409a4ab573835817bfa46b93..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 89 zcmd0;jL%F_U~qEtRbXLcU|?Vo1QLS#XFJAv`8euGXFE2jOmw^81d|KTxb=o(FC9`-Pr|ezoQ1a=m!&3fr4gk7ZAT0m@ diff --git a/test/assets/kaldi/spec-3.9039-0-3.8315-0.3125-0.7500-0.55-false-true-true-false-true-hamming.ark b/test/assets/kaldi/spec-3.9039-0-3.8315-0.3125-0.7500-0.55-false-true-true-false-true-hamming.ark deleted file mode 100644 index cb5b74d2324e98d1b984de914bf3d6da93f7bdf1..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 61 zcmd0;jL%F_U~qEtRbXLaU|?Wj1riKfj@U5BG}&u?jl?;Hnc3 diff --git a/test/assets/kaldi/spec-3.9510-0-0.3903-1.1250-1.0000-0.41-true-false-false-true-true-rectangular.ark b/test/assets/kaldi/spec-3.9510-0-0.3903-1.1250-1.0000-0.41-true-false-false-true-true-rectangular.ark deleted file mode 100644 index bf0818130da6ca9181a44b59513b36c1b850a3a4..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 61 ccmd0;jL%F_U~qEtRbXLcU|?Y30usam0Jm5JI{*Lx diff --git a/test/assets/kaldi/spec-3.9659-0-3.8318-0.1875-0.3750-0.58-false-false-true-false-true-rectangular.ark b/test/assets/kaldi/spec-3.9659-0-3.8318-0.1875-0.3750-0.58-false-false-true-false-true-rectangular.ark deleted file mode 100644 index 752a06c1356eb9d868a88690363a78c07e7ff735..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 57 zcmd0;jL%F_U~qEtRbXLeU|;|f2fj_;cYxv6zJ@glb_@?T?PgHo*~@TE*Y?1{S#}OB Luk9F=eD(nV|HBjw diff --git a/test/assets/kaldi/spec-4.0045-0-3.0610-0.6250-1.0625-0.74-false-false-true-false-true-hanning.ark b/test/assets/kaldi/spec-4.0045-0-3.0610-0.6250-1.0625-0.74-false-false-true-false-true-hanning.ark deleted file mode 100644 index 0fd91bbea354553f70525c939e33bd1954dd4c1f..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 57 ccmd0;jL%F_U~qEtRbXLcU|?Y31QNsm0IEa-IsgCw diff --git a/test/assets/kaldi/spec-4.0187-0-4.8148-0.3750-0.6875-0.68-true-true-false-false-false-hanning.ark b/test/assets/kaldi/spec-4.0187-0-4.8148-0.3750-0.6875-0.68-true-true-false-false-false-hanning.ark deleted file mode 100644 index c0a243ecd45dd516a233ad294e5632543e0fe979..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 53 zcmd0;jL%F_U~qEtRbXLaU|?Wj0TMy?COJO*-Ra2F)#UiHEXc8)b&_MKMYrR-lqSbh H3XYBdnamMm diff --git a/test/assets/kaldi/spec-4.0320-0-2.2019-1.1250-0.2500-0.78-true-true-true-true-true-rectangular.ark b/test/assets/kaldi/spec-4.0320-0-2.2019-1.1250-0.2500-0.78-true-true-true-true-true-rectangular.ark deleted file mode 100644 index 1b3f06a3f31b14a95c28a5a86fee15928c05f011..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 89 ccmd0;jL%F_U~qEtRbXLcU|?Vo1QOH$029*#LI3~& diff --git a/test/assets/kaldi/spec-4.0468-0-0.5053-0.3125-0.1875-0.52-false-true-true-true-true-rectangular.ark b/test/assets/kaldi/spec-4.0468-0-0.5053-0.3125-0.1875-0.52-false-true-true-true-true-rectangular.ark deleted file mode 100644 index ebf7071b70ff81a2e47db7b55bec6a5a330e1715..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 141 zcmV;80CN9rd0%N{AOJ!}O&|mY000041poj501*YgK;?(N03u^O;2n8CK+qmQ0C}*z z0BZ%l0MNj^Kz%qrSe@HH04xN(0H|}k0G)xofD*?(K*7X50BG1e0P~(b00d&a0F^hr v=BCfU0Qsyv0Misc0KlQTKsg}4V9$X*fXxg(03kp=0K~IB5V^F!aJkbz64*5q diff --git a/test/assets/kaldi/spec-4.0627-0-4.1729-0.6250-1.1250-0.89-false-false-false-false-false-povey.ark b/test/assets/kaldi/spec-4.0627-0-4.1729-0.6250-1.1250-0.89-false-false-false-false-false-povey.ark deleted file mode 100644 index d9231bd53cfc62bd7c7ac023b133654d1831d873..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 45 zcmd0;jL%F_U~qEtRbXLcU|?Wj0}`61J&r*aCphY!nBw>#qrs8)wT+|Yl^O>C|I`g< diff --git a/test/assets/kaldi/spec-4.0736-0-0.9155-1.0625-0.5625-0.82-false-true-true-true-true-hamming.ark b/test/assets/kaldi/spec-4.0736-0-0.9155-1.0625-0.5625-0.82-false-true-true-true-true-hamming.ark deleted file mode 100644 index 1b3f06a3f31b14a95c28a5a86fee15928c05f011..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 89 ccmd0;jL%F_U~qEtRbXLcU|?Vo1QOH$029*#LI3~& diff --git a/test/assets/kaldi/spec-4.1131-0-3.9204-0.5000-0.1250-0.39-false-true-true-false-false-hanning.ark b/test/assets/kaldi/spec-4.1131-0-3.9204-0.5000-0.1250-0.39-false-true-true-false-false-hanning.ark deleted file mode 100644 index b36f43e0bb84b54ea31c5832045ff0ff66a949fa..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 221 zcmV<303!cwd0%N{AOJ!}O&|mc000041poj5O#z2NjMk1pIsu145~Nx|=9yGMm4u8z z%^8wGaq5dfDG6yot2H!1%6y1H^lFbm!tIMeRikD>(HcHMy0wcz?y!+Tj~k3ZJVa$d z+Ndl+wGWFyaP*KtoBoSI5pZQezmOyJJ`s6mWD$^w!> zS{{r+e&u9A#ugeu<@NBaO#9X*5G78s25s6MmJm# diff --git a/test/assets/kaldi/spec-4.1816-0-1.6650-0.8125-0.3750-0.37-true-false-true-true-false-rectangular.ark b/test/assets/kaldi/spec-4.1816-0-1.6650-0.8125-0.3750-0.37-true-false-true-true-false-rectangular.ark deleted file mode 100644 index 38565d3c924883448e33f87ff9d0d737e14a9595..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 93 zcmd0;jL%F_U~qEtRbXLaU|?Y31QL8%a~!)W^Brs0XE~-7FLBI{?sMcR40HT+qtVeR wxzn*zyW8=U*BnRTlw3#ilQSI;crS6>soCpz@lKNC9{pxV#fcq`e7iaw0ZG&$9{>OV diff --git a/test/assets/kaldi/spec-4.1897-0-1.2668-0.1875-0.6250-0.74-true-false-true-false-false-hamming.ark b/test/assets/kaldi/spec-4.1897-0-1.2668-0.1875-0.6250-0.74-true-false-true-false-false-hamming.ark deleted file mode 100644 index 7bf41c7ebfd98867da9380c0bd9f4f10fb1dfa67..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 45 zcmd0;jL%F_U~qEtRbXLaU|?Wj1`_<&COW=i>~OT$+UDr8u+8z%h89P)`W8n32DA;K diff --git a/test/assets/kaldi/spec-4.2217-0-3.6775-0.3125-0.1250-0.01-true-false-true-false-false-hamming.ark b/test/assets/kaldi/spec-4.2217-0-3.6775-0.3125-0.1250-0.01-true-false-true-false-false-hamming.ark deleted file mode 100644 index 86c7a1715b129db64220bf89598a9a6fb6929595..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 221 zcmV<303!cwd0%N{AOJ!}O&|mc000041poj5SIU<`V8oI^mduPnzS4j}46A5CM;VVn z8WVp(8oPo)LH&9`$6swh1l^TE3k8rt_nnJDlRJPxrq5JC#p;zozqph^2!D=2zovpg zSzjJ;;yd;A`UbuQe4SZ@r`DT?tcWaD6W3h=rX4-v0?bI(palVy7^b(dq z_+*bkN`8YuYZr1sPppwalizc@$1>tD&wFj!P2LN`HDER;Y diff --git a/test/assets/kaldi/spec-4.3304-0-1.0538-0.8750-1.1250-0.92-true-false-true-false-false-povey.ark b/test/assets/kaldi/spec-4.3304-0-1.0538-0.8750-1.1250-0.92-true-false-true-false-false-povey.ark deleted file mode 100644 index 05c4d4301f86a5a8e6cd8c7fd7057c506ff11fdc..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 57 zcmd0;jL%F_U~qEtRbXLcU|?Y31QK#vXFIaJZgyPvW~Srem9reT8g)5p-f?mamTGZO Mcl_qC>eVU-0O6+--~a#s diff --git a/test/assets/kaldi/spec-4.3942-0-3.9813-0.7500-0.6875-0.27-false-true-true-true-true-blackman.ark b/test/assets/kaldi/spec-4.3942-0-3.9813-0.7500-0.6875-0.27-false-true-true-true-true-blackman.ark deleted file mode 100644 index 0fd91bbea354553f70525c939e33bd1954dd4c1f..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 57 ccmd0;jL%F_U~qEtRbXLcU|?Y31QNsm0IEa-IsgCw diff --git a/test/assets/kaldi/spec-4.4432-0-2.0441-0.5000-0.6875-0.77-false-false-true-true-false-hanning.ark b/test/assets/kaldi/spec-4.4432-0-2.0441-0.5000-0.6875-0.77-false-false-true-true-false-hanning.ark deleted file mode 100644 index db41d359bd981d28b1fa14c7b8cc16369058bbbb..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 61 zcmd0;jL%F_U~qEtRbXLaU|?Wj1rjGBIvg+Z_d6a@=yBXxknVWktBqs)|8~bJpI*n` Qr@9>@mD3$XX2>}L064)E{r~^~ diff --git a/test/assets/kaldi/spec-4.4459-0-0.5135-0.2500-0.1875-0.29-false-false-true-false-true-hanning.ark b/test/assets/kaldi/spec-4.4459-0-0.5135-0.2500-0.1875-0.29-false-false-true-false-true-hanning.ark deleted file mode 100644 index a4a50c60705c9a36376f905f31f94b86fb6d2e62..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 105 zcmd0;jL%F_U~qEtRbXLfU|?Wj1`-aP-|Rs6!lsk<8`2i+2jLmh9@ro7j{{?ab<6Dy qG`jbL@P-R|_72yoz?k91%zX*pYWIWigI4JS4IvHoAguCM^#A~Go-LmM diff --git a/test/assets/kaldi/spec-4.4807-0-3.5660-0.6250-0.1250-0.08-false-true-false-false-false-povey.ark b/test/assets/kaldi/spec-4.4807-0-3.5660-0.6250-0.1250-0.08-false-true-false-false-false-povey.ark deleted file mode 100644 index 99b149e13ce12b90b0a1713d79ca6c0518316cf1..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 261 zcmV+g0s8)Jd0%N{AOJ!}O&|mc000041^@s6c}R~z_r{k&mZ*|JyPs-7?)hLrD*hQk zT_}-3f@YXOxnGq*es_RD{vj1XW05sM$LWnhMr)Ko5jmAXn$>|p%Kk<{`nfSd0uhiw zFRhkA45*bscMX9-)wMlAL_G>YQqqn=x>c1ycWaeF!+wE5Ph&$tRaPlM_FRrZ`sb8E zHcXX4uC#$c-OfcpG43uw=`N5#*2tDYcCnQ~di;PvK#4p-pw6y8*))zp#Ick?227Pf z%(a0*p1Vas*%vQC!S|3sA9I*Np&OM!o2r08oK7o2gYY*&QbLbG&EJomuvTeBVg zcTIG3s_$^DPiS*oEK#G&>)i%Nqm7MV9K;*r*veW1#tR$^9dA#l T1mjGrCP#0rMlg<^U+oA01&14| diff --git a/test/assets/kaldi/spec-4.6971-0-1.3632-0.8750-0.9375-0.44-false-true-false-true-false-blackman.ark b/test/assets/kaldi/spec-4.6971-0-1.3632-0.8750-0.9375-0.44-false-true-false-true-false-blackman.ark deleted file mode 100644 index a6bc357d66de07eee431f33bfafc329235048fa5..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 53 zcmd0;jL%F_U~qEtRbXLcU|?Y301|(eZ*sh4GS_kDti6s;ayK}(Z{6tFc6otgt!<|x IH+Quo0Klsf>;M1& diff --git a/test/assets/kaldi_test_mfcc_args.json b/test/assets/kaldi_test_mfcc_args.json index 7ec5959dc1..7808a2442e 100644 --- a/test/assets/kaldi_test_mfcc_args.json +++ b/test/assets/kaldi_test_mfcc_args.json @@ -1,4 +1,3 @@ -{"blackman_coeff": 0.0063, "energy_floor": 3.0323, "frame_length": 0.625, "frame_shift": 0.0625, "high_freq": 5842, "htk_compat": false, "low_freq": 3240, "num_mel_bins": 4, "preemphasis_coefficient": 0.29, "raw_energy": true, "remove_dc_offset": false, "round_to_power_of_two": true, "snip_edges": true, "subtract_mean": true, "use_energy": true, "num_ceps": 2, "cepstral_lifter": 73.5792, "vtln_high": 5749, "vtln_low": 4449, "vtln_warp": 1.0, "window_type": "blackman", "dither": 0.0} {"blackman_coeff": 0.013, "energy_floor": 1.8509, "frame_length": 1.1875, "frame_shift": 0.625, "high_freq": 7999, "htk_compat": false, "low_freq": 4330, "num_mel_bins": 5, "preemphasis_coefficient": 0.38, "raw_energy": true, "remove_dc_offset": false, "round_to_power_of_two": true, "snip_edges": false, "subtract_mean": false, "use_energy": true, "num_ceps": 3, "cepstral_lifter": 8.1048, "vtln_high": 7497, "vtln_low": 7397, "vtln_warp": 1.0, "window_type": "blackman", "dither": 0.0} {"blackman_coeff": 0.0487, "energy_floor": 1.3641, "frame_length": 1.0, "frame_shift": 0.8125, "high_freq": 7892, "htk_compat": true, "low_freq": 1904, "num_mel_bins": 8, "preemphasis_coefficient": 0.26, "raw_energy": true, "remove_dc_offset": true, "round_to_power_of_two": true, "snip_edges": false, "subtract_mean": false, "use_energy": false, "num_ceps": 5, "cepstral_lifter": 34.0918, "vtln_high": 4400, "vtln_low": 2737, "vtln_warp": 1.0, "window_type": "rectangular", "dither": 0.0} {"blackman_coeff": 0.0577, "energy_floor": 2.4313, "frame_length": 1.0625, "frame_shift": 0.875, "high_freq": 2922, "htk_compat": true, "low_freq": 274, "num_mel_bins": 6, "preemphasis_coefficient": 0.48, "raw_energy": false, "remove_dc_offset": false, "round_to_power_of_two": true, "snip_edges": true, "subtract_mean": false, "use_energy": true, "num_ceps": 5, "cepstral_lifter": 21.3007, "vtln_high": 1352, "vtln_low": 280, "vtln_warp": 1.0, "window_type": "hanning", "dither": 0.0} @@ -69,13 +68,11 @@ {"blackman_coeff": 2.9211, "energy_floor": 4.144, "frame_length": 0.75, "frame_shift": 0.375, "high_freq": 7210, "htk_compat": true, "low_freq": 3666, "num_mel_bins": 4, "preemphasis_coefficient": 0.93, "raw_energy": false, "remove_dc_offset": false, "round_to_power_of_two": true, "snip_edges": true, "subtract_mean": false, "use_energy": false, "num_ceps": 4, "cepstral_lifter": 94.5907, "vtln_high": 6682, "vtln_low": 4979, "vtln_warp": 1.0, "window_type": "hamming", "dither": 0.0} {"blackman_coeff": 2.9464, "energy_floor": 0.6798, "frame_length": 1.125, "frame_shift": 0.0625, "high_freq": 4445, "htk_compat": true, "low_freq": 323, "num_mel_bins": 6, "preemphasis_coefficient": 0.46, "raw_energy": false, "remove_dc_offset": true, "round_to_power_of_two": true, "snip_edges": false, "subtract_mean": true, "use_energy": false, "num_ceps": 6, "cepstral_lifter": 7.8133, "vtln_high": 3755, "vtln_low": 1137, "vtln_warp": 1.0, "window_type": "hanning", "dither": 0.0} {"blackman_coeff": 2.9633, "energy_floor": 1.9565, "frame_length": 0.875, "frame_shift": 0.0625, "high_freq": 6835, "htk_compat": false, "low_freq": 649, "num_mel_bins": 5, "preemphasis_coefficient": 0.77, "raw_energy": false, "remove_dc_offset": false, "round_to_power_of_two": false, "snip_edges": true, "subtract_mean": false, "use_energy": false, "num_ceps": 2, "cepstral_lifter": 80.8871, "vtln_high": 6691, "vtln_low": 6581, "vtln_warp": 1.0, "window_type": "povey", "dither": 0.0} -{"blackman_coeff": 2.9643, "energy_floor": 3.8883, "frame_length": 0.75, "frame_shift": 0.25, "high_freq": 7373, "htk_compat": false, "low_freq": 1698, "num_mel_bins": 4, "preemphasis_coefficient": 0.92, "raw_energy": false, "remove_dc_offset": false, "round_to_power_of_two": true, "snip_edges": false, "subtract_mean": true, "use_energy": true, "num_ceps": 4, "cepstral_lifter": 63.3036, "vtln_high": 6650, "vtln_low": 5500, "vtln_warp": 1.0, "window_type": "povey", "dither": 0.0} {"blackman_coeff": 2.9697, "energy_floor": 2.0241, "frame_length": 1.125, "frame_shift": 0.6875, "high_freq": 2170, "htk_compat": false, "low_freq": 180, "num_mel_bins": 5, "preemphasis_coefficient": 0.28, "raw_energy": false, "remove_dc_offset": true, "round_to_power_of_two": true, "snip_edges": true, "subtract_mean": true, "use_energy": true, "num_ceps": 3, "cepstral_lifter": 95.8111, "vtln_high": 1266, "vtln_low": 521, "vtln_warp": 1.0, "window_type": "blackman", "dither": 0.0} {"blackman_coeff": 3.0358, "energy_floor": 1.7295, "frame_length": 1.1875, "frame_shift": 1.0, "high_freq": 7222, "htk_compat": true, "low_freq": 858, "num_mel_bins": 4, "preemphasis_coefficient": 0.16, "raw_energy": false, "remove_dc_offset": true, "round_to_power_of_two": true, "snip_edges": false, "subtract_mean": false, "use_energy": true, "num_ceps": 4, "cepstral_lifter": 64.7537, "vtln_high": 6220, "vtln_low": 5229, "vtln_warp": 1.0, "window_type": "povey", "dither": 0.0} {"blackman_coeff": 3.0421, "energy_floor": 3.3343, "frame_length": 1.0, "frame_shift": 0.9375, "high_freq": 6477, "htk_compat": false, "low_freq": 1402, "num_mel_bins": 5, "preemphasis_coefficient": 0.99, "raw_energy": false, "remove_dc_offset": true, "round_to_power_of_two": true, "snip_edges": true, "subtract_mean": true, "use_energy": true, "num_ceps": 4, "cepstral_lifter": 26.1743, "vtln_high": 6381, "vtln_low": 5017, "vtln_warp": 1.0, "window_type": "hamming", "dither": 0.0} {"blackman_coeff": 3.0919, "energy_floor": 4.5103, "frame_length": 0.625, "frame_shift": 1.0, "high_freq": 5323, "htk_compat": true, "low_freq": 937, "num_mel_bins": 5, "preemphasis_coefficient": 0.95, "raw_energy": false, "remove_dc_offset": false, "round_to_power_of_two": true, "snip_edges": true, "subtract_mean": true, "use_energy": false, "num_ceps": 5, "cepstral_lifter": 82.2405, "vtln_high": 5130, "vtln_low": 5086, "vtln_warp": 1.0, "window_type": "hanning", "dither": 0.0} {"blackman_coeff": 3.1463, "energy_floor": 4.5068, "frame_length": 0.6875, "frame_shift": 0.3125, "high_freq": 7587, "htk_compat": true, "low_freq": 3542, "num_mel_bins": 7, "preemphasis_coefficient": 0.78, "raw_energy": true, "remove_dc_offset": false, "round_to_power_of_two": true, "snip_edges": true, "subtract_mean": true, "use_energy": true, "num_ceps": 4, "cepstral_lifter": 28.5808, "vtln_high": 7478, "vtln_low": 7326, "vtln_warp": 1.0, "window_type": "blackman", "dither": 0.0} -{"blackman_coeff": 3.2007, "energy_floor": 1.3677, "frame_length": 1.125, "frame_shift": 0.1875, "high_freq": 4726, "htk_compat": true, "low_freq": 2027, "num_mel_bins": 4, "preemphasis_coefficient": 0.74, "raw_energy": false, "remove_dc_offset": true, "round_to_power_of_two": false, "snip_edges": false, "subtract_mean": true, "use_energy": false, "num_ceps": 4, "cepstral_lifter": 3.5732, "vtln_high": 4583, "vtln_low": 3742, "vtln_warp": 1.0, "window_type": "povey", "dither": 0.0} {"blackman_coeff": 3.2416, "energy_floor": 1.0604, "frame_length": 0.875, "frame_shift": 0.5, "high_freq": 4730, "htk_compat": false, "low_freq": 968, "num_mel_bins": 4, "preemphasis_coefficient": 0.11, "raw_energy": true, "remove_dc_offset": true, "round_to_power_of_two": true, "snip_edges": false, "subtract_mean": true, "use_energy": true, "num_ceps": 3, "cepstral_lifter": 60.5751, "vtln_high": 3542, "vtln_low": 1943, "vtln_warp": 1.0, "window_type": "blackman", "dither": 0.0} {"blackman_coeff": 3.2698, "energy_floor": 3.0361, "frame_length": 1.0625, "frame_shift": 0.75, "high_freq": 4870, "htk_compat": true, "low_freq": 1281, "num_mel_bins": 7, "preemphasis_coefficient": 0.64, "raw_energy": false, "remove_dc_offset": true, "round_to_power_of_two": true, "snip_edges": false, "subtract_mean": true, "use_energy": true, "num_ceps": 3, "cepstral_lifter": 28.536, "vtln_high": 4401, "vtln_low": 3315, "vtln_warp": 1.0, "window_type": "blackman", "dither": 0.0} {"blackman_coeff": 3.3078, "energy_floor": 4.9217, "frame_length": 1.0, "frame_shift": 0.3125, "high_freq": 6758, "htk_compat": true, "low_freq": 760, "num_mel_bins": 5, "preemphasis_coefficient": 0.98, "raw_energy": true, "remove_dc_offset": true, "round_to_power_of_two": true, "snip_edges": true, "subtract_mean": false, "use_energy": true, "num_ceps": 3, "cepstral_lifter": 97.4694, "vtln_high": 6022, "vtln_low": 5650, "vtln_warp": 1.0, "window_type": "rectangular", "dither": 0.0} diff --git a/test/assets/kaldi_test_spectrogram_args.json b/test/assets/kaldi_test_spectrogram_args.json new file mode 100644 index 0000000000..c44245b6c0 --- /dev/null +++ b/test/assets/kaldi_test_spectrogram_args.json @@ -0,0 +1,109 @@ +{"blackman_coeff": 0.0016, "dither": 0, "energy_floor": 4.668, "frame_length": 0.625, "frame_shift": 0.25, "preemphasis_coefficient": 0.82, "raw_energy": false, "remove_dc_offset": false, "round_to_power_of_two": false, "snip_edges": false, "subtract_mean": false, "window_type": "povey"} +{"blackman_coeff": 0.0121, "dither": 0, "energy_floor": 4.9643, "frame_length": 0.875, "frame_shift": 0.1875, "preemphasis_coefficient": 0.98, "raw_energy": false, "remove_dc_offset": false, "round_to_power_of_two": false, "snip_edges": true, "subtract_mean": false, "window_type": "rectangular"} +{"blackman_coeff": 0.0378, "dither": 0, "energy_floor": 3.777, "frame_length": 0.5, "frame_shift": 0.625, "preemphasis_coefficient": 0.76, "raw_energy": false, "remove_dc_offset": true, "round_to_power_of_two": true, "snip_edges": true, "subtract_mean": false, "window_type": "blackman"} +{"blackman_coeff": 0.0545, "dither": 0, "energy_floor": 0.0732, "frame_length": 1.0, "frame_shift": 0.75, "preemphasis_coefficient": 0.81, "raw_energy": false, "remove_dc_offset": true, "round_to_power_of_two": true, "snip_edges": true, "subtract_mean": true, "window_type": "hanning"} +{"blackman_coeff": 0.1005, "dither": 0, "energy_floor": 0.3739, "frame_length": 0.5625, "frame_shift": 0.625, "preemphasis_coefficient": 0.19, "raw_energy": false, "remove_dc_offset": false, "round_to_power_of_two": true, "snip_edges": true, "subtract_mean": false, "window_type": "blackman"} +{"blackman_coeff": 0.1088, "dither": 0, "energy_floor": 0.6933, "frame_length": 0.5, "frame_shift": 0.75, "preemphasis_coefficient": 0.51, "raw_energy": true, "remove_dc_offset": true, "round_to_power_of_two": false, "snip_edges": true, "subtract_mean": false, "window_type": "povey"} +{"blackman_coeff": 0.1777, "dither": 0, "energy_floor": 3.8992, "frame_length": 1.0, "frame_shift": 0.3125, "preemphasis_coefficient": 0.96, "raw_energy": true, "remove_dc_offset": false, "round_to_power_of_two": false, "snip_edges": true, "subtract_mean": false, "window_type": "blackman"} +{"blackman_coeff": 0.2384, "dither": 0, "energy_floor": 0.308, "frame_length": 0.375, "frame_shift": 0.25, "preemphasis_coefficient": 0.98, "raw_energy": true, "remove_dc_offset": false, "round_to_power_of_two": false, "snip_edges": false, "subtract_mean": true, "window_type": "povey"} +{"blackman_coeff": 0.2669, "dither": 0, "energy_floor": 2.4329, "frame_length": 0.625, "frame_shift": 1.1875, "preemphasis_coefficient": 0.18, "raw_energy": false, "remove_dc_offset": true, "round_to_power_of_two": false, "snip_edges": true, "subtract_mean": false, "window_type": "blackman"} +{"blackman_coeff": 0.334, "dither": 0, "energy_floor": 0.5962, "frame_length": 0.25, "frame_shift": 0.5625, "preemphasis_coefficient": 0.38, "raw_energy": false, "remove_dc_offset": false, "round_to_power_of_two": true, "snip_edges": false, "subtract_mean": true, "window_type": "hamming"} +{"blackman_coeff": 0.4268, "dither": 0, "energy_floor": 2.4431, "frame_length": 0.5625, "frame_shift": 0.0625, "preemphasis_coefficient": 0.95, "raw_energy": true, "remove_dc_offset": true, "round_to_power_of_two": true, "snip_edges": true, "subtract_mean": false, "window_type": "hamming"} +{"blackman_coeff": 0.4774, "dither": 0, "energy_floor": 0.6982, "frame_length": 1.125, "frame_shift": 1.125, "preemphasis_coefficient": 0.27, "raw_energy": false, "remove_dc_offset": true, "round_to_power_of_two": false, "snip_edges": true, "subtract_mean": true, "window_type": "povey"} +{"blackman_coeff": 0.4992, "dither": 0, "energy_floor": 3.7665, "frame_length": 0.4375, "frame_shift": 1.125, "preemphasis_coefficient": 0.42, "raw_energy": false, "remove_dc_offset": false, "round_to_power_of_two": true, "snip_edges": false, "subtract_mean": true, "window_type": "rectangular"} +{"blackman_coeff": 0.544, "dither": 0, "energy_floor": 1.6641, "frame_length": 0.9375, "frame_shift": 0.875, "preemphasis_coefficient": 0.13, "raw_energy": true, "remove_dc_offset": true, "round_to_power_of_two": true, "snip_edges": true, "subtract_mean": true, "window_type": "rectangular"} +{"blackman_coeff": 0.5785, "dither": 0, "energy_floor": 2.8162, "frame_length": 1.125, "frame_shift": 1.0625, "preemphasis_coefficient": 0.17, "raw_energy": false, "remove_dc_offset": false, "round_to_power_of_two": false, "snip_edges": true, "subtract_mean": false, "window_type": "blackman"} +{"blackman_coeff": 0.8072, "dither": 0, "energy_floor": 4.0404, "frame_length": 0.5, "frame_shift": 1.1875, "preemphasis_coefficient": 0.74, "raw_energy": false, "remove_dc_offset": false, "round_to_power_of_two": false, "snip_edges": true, "subtract_mean": true, "window_type": "hamming"} +{"blackman_coeff": 0.8418, "dither": 0, "energy_floor": 4.1771, "frame_length": 0.3125, "frame_shift": 0.25, "preemphasis_coefficient": 0.48, "raw_energy": false, "remove_dc_offset": false, "round_to_power_of_two": true, "snip_edges": true, "subtract_mean": false, "window_type": "hanning"} +{"blackman_coeff": 0.8431, "dither": 0, "energy_floor": 0.0728, "frame_length": 0.75, "frame_shift": 0.8125, "preemphasis_coefficient": 0.1, "raw_energy": true, "remove_dc_offset": false, "round_to_power_of_two": true, "snip_edges": false, "subtract_mean": false, "window_type": "povey"} +{"blackman_coeff": 0.885, "dither": 0, "energy_floor": 3.9292, "frame_length": 0.375, "frame_shift": 0.75, "preemphasis_coefficient": 0.27, "raw_energy": true, "remove_dc_offset": false, "round_to_power_of_two": false, "snip_edges": true, "subtract_mean": false, "window_type": "blackman"} +{"blackman_coeff": 0.9625, "dither": 0, "energy_floor": 2.5481, "frame_length": 0.6875, "frame_shift": 1.0, "preemphasis_coefficient": 0.06, "raw_energy": false, "remove_dc_offset": true, "round_to_power_of_two": true, "snip_edges": true, "subtract_mean": false, "window_type": "blackman"} +{"blackman_coeff": 0.9826, "dither": 0, "energy_floor": 0.7377, "frame_length": 0.375, "frame_shift": 0.6875, "preemphasis_coefficient": 0.7, "raw_energy": false, "remove_dc_offset": false, "round_to_power_of_two": true, "snip_edges": false, "subtract_mean": true, "window_type": "rectangular"} +{"blackman_coeff": 0.9854, "dither": 0, "energy_floor": 3.8819, "frame_length": 0.25, "frame_shift": 1.0, "preemphasis_coefficient": 0.54, "raw_energy": true, "remove_dc_offset": false, "round_to_power_of_two": false, "snip_edges": false, "subtract_mean": true, "window_type": "povey"} +{"blackman_coeff": 1.0303, "dither": 0, "energy_floor": 4.4583, "frame_length": 0.375, "frame_shift": 0.875, "preemphasis_coefficient": 0.39, "raw_energy": false, "remove_dc_offset": true, "round_to_power_of_two": false, "snip_edges": true, "subtract_mean": false, "window_type": "blackman"} +{"blackman_coeff": 1.0743, "dither": 0, "energy_floor": 0.4642, "frame_length": 1.125, "frame_shift": 0.625, "preemphasis_coefficient": 0.39, "raw_energy": true, "remove_dc_offset": true, "round_to_power_of_two": true, "snip_edges": true, "subtract_mean": true, "window_type": "hanning"} +{"blackman_coeff": 1.0788, "dither": 0, "energy_floor": 1.442, "frame_length": 0.1875, "frame_shift": 0.3125, "preemphasis_coefficient": 0.53, "raw_energy": true, "remove_dc_offset": true, "round_to_power_of_two": true, "snip_edges": true, "subtract_mean": true, "window_type": "hanning"} +{"blackman_coeff": 1.0816, "dither": 0, "energy_floor": 0.205, "frame_length": 0.1875, "frame_shift": 0.6875, "preemphasis_coefficient": 0.02, "raw_energy": false, "remove_dc_offset": false, "round_to_power_of_two": true, "snip_edges": true, "subtract_mean": false, "window_type": "hamming"} +{"blackman_coeff": 1.1385, "dither": 0, "energy_floor": 4.738, "frame_length": 0.625, "frame_shift": 0.3125, "preemphasis_coefficient": 0.23, "raw_energy": true, "remove_dc_offset": false, "round_to_power_of_two": false, "snip_edges": false, "subtract_mean": false, "window_type": "hanning"} +{"blackman_coeff": 1.3142, "dither": 0, "energy_floor": 4.8914, "frame_length": 0.875, "frame_shift": 0.1875, "preemphasis_coefficient": 0.34, "raw_energy": true, "remove_dc_offset": true, "round_to_power_of_two": false, "snip_edges": false, "subtract_mean": false, "window_type": "blackman"} +{"blackman_coeff": 1.3189, "dither": 0, "energy_floor": 3.683, "frame_length": 1.125, "frame_shift": 1.125, "preemphasis_coefficient": 0.88, "raw_energy": false, "remove_dc_offset": false, "round_to_power_of_two": false, "snip_edges": false, "subtract_mean": true, "window_type": "hamming"} +{"blackman_coeff": 1.3235, "dither": 0, "energy_floor": 3.8538, "frame_length": 0.25, "frame_shift": 1.0625, "preemphasis_coefficient": 0.07, "raw_energy": false, "remove_dc_offset": false, "round_to_power_of_two": true, "snip_edges": false, "subtract_mean": true, "window_type": "blackman"} +{"blackman_coeff": 1.3389, "dither": 0, "energy_floor": 1.6152, "frame_length": 0.375, "frame_shift": 0.5, "preemphasis_coefficient": 0.21, "raw_energy": false, "remove_dc_offset": false, "round_to_power_of_two": false, "snip_edges": true, "subtract_mean": false, "window_type": "blackman"} +{"blackman_coeff": 1.3887, "dither": 0, "energy_floor": 3.3198, "frame_length": 0.375, "frame_shift": 0.125, "preemphasis_coefficient": 0.14, "raw_energy": false, "remove_dc_offset": false, "round_to_power_of_two": true, "snip_edges": false, "subtract_mean": false, "window_type": "hanning"} +{"blackman_coeff": 1.4127, "dither": 0, "energy_floor": 2.6264, "frame_length": 0.875, "frame_shift": 0.375, "preemphasis_coefficient": 0.69, "raw_energy": false, "remove_dc_offset": false, "round_to_power_of_two": true, "snip_edges": false, "subtract_mean": false, "window_type": "povey"} +{"blackman_coeff": 1.5178, "dither": 0, "energy_floor": 2.8631, "frame_length": 1.0, "frame_shift": 0.8125, "preemphasis_coefficient": 0.95, "raw_energy": true, "remove_dc_offset": true, "round_to_power_of_two": true, "snip_edges": true, "subtract_mean": false, "window_type": "blackman"} +{"blackman_coeff": 1.5403, "dither": 0, "energy_floor": 0.0133, "frame_length": 1.1875, "frame_shift": 0.25, "preemphasis_coefficient": 0.59, "raw_energy": true, "remove_dc_offset": false, "round_to_power_of_two": true, "snip_edges": false, "subtract_mean": false, "window_type": "blackman"} +{"blackman_coeff": 1.5754, "dither": 0, "energy_floor": 0.954, "frame_length": 1.0, "frame_shift": 0.9375, "preemphasis_coefficient": 0.2, "raw_energy": false, "remove_dc_offset": false, "round_to_power_of_two": true, "snip_edges": true, "subtract_mean": true, "window_type": "rectangular"} +{"blackman_coeff": 1.5959, "dither": 0, "energy_floor": 0.9033, "frame_length": 0.75, "frame_shift": 1.0, "preemphasis_coefficient": 0.14, "raw_energy": true, "remove_dc_offset": true, "round_to_power_of_two": true, "snip_edges": true, "subtract_mean": false, "window_type": "hanning"} +{"blackman_coeff": 1.6923, "dither": 0, "energy_floor": 3.5626, "frame_length": 0.6875, "frame_shift": 1.0625, "preemphasis_coefficient": 0.27, "raw_energy": true, "remove_dc_offset": false, "round_to_power_of_two": true, "snip_edges": false, "subtract_mean": false, "window_type": "rectangular"} +{"blackman_coeff": 1.6972, "dither": 0, "energy_floor": 1.0863, "frame_length": 1.1875, "frame_shift": 0.875, "preemphasis_coefficient": 0.86, "raw_energy": true, "remove_dc_offset": true, "round_to_power_of_two": true, "snip_edges": true, "subtract_mean": false, "window_type": "rectangular"} +{"blackman_coeff": 1.744, "dither": 0, "energy_floor": 0.5308, "frame_length": 0.5, "frame_shift": 0.125, "preemphasis_coefficient": 0.33, "raw_energy": true, "remove_dc_offset": true, "round_to_power_of_two": false, "snip_edges": false, "subtract_mean": false, "window_type": "hamming"} +{"blackman_coeff": 1.7642, "dither": 0, "energy_floor": 0.4833, "frame_length": 0.25, "frame_shift": 0.8125, "preemphasis_coefficient": 0.94, "raw_energy": false, "remove_dc_offset": true, "round_to_power_of_two": false, "snip_edges": true, "subtract_mean": false, "window_type": "blackman"} +{"blackman_coeff": 1.8072, "dither": 0, "energy_floor": 0.8085, "frame_length": 0.5, "frame_shift": 0.25, "preemphasis_coefficient": 0.96, "raw_energy": false, "remove_dc_offset": true, "round_to_power_of_two": true, "snip_edges": false, "subtract_mean": false, "window_type": "hanning"} +{"blackman_coeff": 1.8836, "dither": 0, "energy_floor": 4.5145, "frame_length": 0.875, "frame_shift": 1.0625, "preemphasis_coefficient": 0.4, "raw_energy": false, "remove_dc_offset": false, "round_to_power_of_two": true, "snip_edges": true, "subtract_mean": true, "window_type": "hanning"} +{"blackman_coeff": 1.8946, "dither": 0, "energy_floor": 4.1442, "frame_length": 0.3125, "frame_shift": 0.875, "preemphasis_coefficient": 0.73, "raw_energy": true, "remove_dc_offset": true, "round_to_power_of_two": true, "snip_edges": true, "subtract_mean": true, "window_type": "rectangular"} +{"blackman_coeff": 1.8988, "dither": 0, "energy_floor": 3.0931, "frame_length": 1.0625, "frame_shift": 0.3125, "preemphasis_coefficient": 0.35, "raw_energy": true, "remove_dc_offset": true, "round_to_power_of_two": true, "snip_edges": true, "subtract_mean": true, "window_type": "hanning"} +{"blackman_coeff": 1.9501, "dither": 0, "energy_floor": 4.3519, "frame_length": 0.4375, "frame_shift": 0.25, "preemphasis_coefficient": 0.61, "raw_energy": false, "remove_dc_offset": false, "round_to_power_of_two": true, "snip_edges": false, "subtract_mean": true, "window_type": "hanning"} +{"blackman_coeff": 2.0137, "dither": 0, "energy_floor": 3.1007, "frame_length": 0.625, "frame_shift": 1.0625, "preemphasis_coefficient": 0.67, "raw_energy": true, "remove_dc_offset": false, "round_to_power_of_two": true, "snip_edges": true, "subtract_mean": true, "window_type": "rectangular"} +{"blackman_coeff": 2.0175, "dither": 0, "energy_floor": 2.9099, "frame_length": 1.0, "frame_shift": 0.5625, "preemphasis_coefficient": 0.28, "raw_energy": true, "remove_dc_offset": false, "round_to_power_of_two": true, "snip_edges": false, "subtract_mean": false, "window_type": "blackman"} +{"blackman_coeff": 2.1114, "dither": 0, "energy_floor": 4.5618, "frame_length": 0.25, "frame_shift": 0.875, "preemphasis_coefficient": 0.61, "raw_energy": true, "remove_dc_offset": true, "round_to_power_of_two": false, "snip_edges": false, "subtract_mean": false, "window_type": "povey"} +{"blackman_coeff": 2.1472, "dither": 0, "energy_floor": 0.2, "frame_length": 1.125, "frame_shift": 0.875, "preemphasis_coefficient": 0.58, "raw_energy": true, "remove_dc_offset": true, "round_to_power_of_two": false, "snip_edges": true, "subtract_mean": true, "window_type": "hamming"} +{"blackman_coeff": 2.1947, "dither": 0, "energy_floor": 1.8065, "frame_length": 0.875, "frame_shift": 0.75, "preemphasis_coefficient": 0.45, "raw_energy": false, "remove_dc_offset": true, "round_to_power_of_two": false, "snip_edges": false, "subtract_mean": false, "window_type": "povey"} +{"blackman_coeff": 2.2457, "dither": 0, "energy_floor": 1.704, "frame_length": 0.75, "frame_shift": 0.5625, "preemphasis_coefficient": 0.98, "raw_energy": true, "remove_dc_offset": false, "round_to_power_of_two": false, "snip_edges": false, "subtract_mean": true, "window_type": "hamming"} +{"blackman_coeff": 2.2893, "dither": 0, "energy_floor": 1.0286, "frame_length": 0.25, "frame_shift": 0.5, "preemphasis_coefficient": 0.8, "raw_energy": true, "remove_dc_offset": false, "round_to_power_of_two": true, "snip_edges": false, "subtract_mean": false, "window_type": "hanning"} +{"blackman_coeff": 2.3371, "dither": 0, "energy_floor": 4.4192, "frame_length": 0.8125, "frame_shift": 0.625, "preemphasis_coefficient": 0.3, "raw_energy": true, "remove_dc_offset": false, "round_to_power_of_two": true, "snip_edges": true, "subtract_mean": true, "window_type": "rectangular"} +{"blackman_coeff": 2.3831, "dither": 0, "energy_floor": 4.8325, "frame_length": 0.25, "frame_shift": 1.125, "preemphasis_coefficient": 0.34, "raw_energy": true, "remove_dc_offset": true, "round_to_power_of_two": true, "snip_edges": false, "subtract_mean": true, "window_type": "povey"} +{"blackman_coeff": 2.423, "dither": 0, "energy_floor": 0.6363, "frame_length": 0.875, "frame_shift": 0.3125, "preemphasis_coefficient": 0.77, "raw_energy": true, "remove_dc_offset": true, "round_to_power_of_two": true, "snip_edges": false, "subtract_mean": false, "window_type": "hanning"} +{"blackman_coeff": 2.4378, "dither": 0, "energy_floor": 1.4617, "frame_length": 0.9375, "frame_shift": 0.375, "preemphasis_coefficient": 0.53, "raw_energy": true, "remove_dc_offset": false, "round_to_power_of_two": true, "snip_edges": true, "subtract_mean": false, "window_type": "rectangular"} +{"blackman_coeff": 2.4454, "dither": 0, "energy_floor": 1.936, "frame_length": 1.0, "frame_shift": 0.9375, "preemphasis_coefficient": 0.66, "raw_energy": false, "remove_dc_offset": true, "round_to_power_of_two": false, "snip_edges": false, "subtract_mean": false, "window_type": "rectangular"} +{"blackman_coeff": 2.448, "dither": 0, "energy_floor": 3.8782, "frame_length": 0.5625, "frame_shift": 1.125, "preemphasis_coefficient": 0.1, "raw_energy": false, "remove_dc_offset": true, "round_to_power_of_two": true, "snip_edges": false, "subtract_mean": true, "window_type": "rectangular"} +{"blackman_coeff": 2.5164, "dither": 0, "energy_floor": 2.7455, "frame_length": 0.875, "frame_shift": 0.9375, "preemphasis_coefficient": 0.55, "raw_energy": false, "remove_dc_offset": true, "round_to_power_of_two": false, "snip_edges": false, "subtract_mean": false, "window_type": "hanning"} +{"blackman_coeff": 2.5316, "dither": 0, "energy_floor": 2.3286, "frame_length": 0.75, "frame_shift": 0.75, "preemphasis_coefficient": 0.61, "raw_energy": false, "remove_dc_offset": false, "round_to_power_of_two": false, "snip_edges": false, "subtract_mean": true, "window_type": "rectangular"} +{"blackman_coeff": 2.5487, "dither": 0, "energy_floor": 3.8457, "frame_length": 1.1875, "frame_shift": 0.9375, "preemphasis_coefficient": 0.63, "raw_energy": true, "remove_dc_offset": true, "round_to_power_of_two": true, "snip_edges": true, "subtract_mean": false, "window_type": "hanning"} +{"blackman_coeff": 2.6121, "dither": 0, "energy_floor": 4.3165, "frame_length": 0.6875, "frame_shift": 1.1875, "preemphasis_coefficient": 0.19, "raw_energy": false, "remove_dc_offset": true, "round_to_power_of_two": true, "snip_edges": true, "subtract_mean": false, "window_type": "rectangular"} +{"blackman_coeff": 2.6988, "dither": 0, "energy_floor": 2.3417, "frame_length": 1.0, "frame_shift": 0.6875, "preemphasis_coefficient": 0.38, "raw_energy": false, "remove_dc_offset": false, "round_to_power_of_two": true, "snip_edges": false, "subtract_mean": false, "window_type": "rectangular"} +{"blackman_coeff": 2.7457, "dither": 0, "energy_floor": 1.3662, "frame_length": 0.25, "frame_shift": 0.875, "preemphasis_coefficient": 0.74, "raw_energy": false, "remove_dc_offset": true, "round_to_power_of_two": false, "snip_edges": true, "subtract_mean": true, "window_type": "blackman"} +{"blackman_coeff": 2.8577, "dither": 0, "energy_floor": 4.1431, "frame_length": 0.375, "frame_shift": 1.0, "preemphasis_coefficient": 1.0, "raw_energy": false, "remove_dc_offset": true, "round_to_power_of_two": true, "snip_edges": false, "subtract_mean": false, "window_type": "hamming"} +{"blackman_coeff": 2.8693, "dither": 0, "energy_floor": 4.3801, "frame_length": 0.75, "frame_shift": 1.0, "preemphasis_coefficient": 0.95, "raw_energy": true, "remove_dc_offset": true, "round_to_power_of_two": true, "snip_edges": true, "subtract_mean": true, "window_type": "rectangular"} +{"blackman_coeff": 2.8888, "dither": 0, "energy_floor": 0.4078, "frame_length": 0.3125, "frame_shift": 0.625, "preemphasis_coefficient": 0.25, "raw_energy": false, "remove_dc_offset": true, "round_to_power_of_two": true, "snip_edges": true, "subtract_mean": false, "window_type": "hanning"} +{"blackman_coeff": 2.9074, "dither": 0, "energy_floor": 1.6849, "frame_length": 1.125, "frame_shift": 0.625, "preemphasis_coefficient": 0.79, "raw_energy": false, "remove_dc_offset": true, "round_to_power_of_two": true, "snip_edges": false, "subtract_mean": false, "window_type": "blackman"} +{"blackman_coeff": 2.9303, "dither": 0, "energy_floor": 3.5172, "frame_length": 0.5, "frame_shift": 0.5, "preemphasis_coefficient": 0.04, "raw_energy": true, "remove_dc_offset": false, "round_to_power_of_two": true, "snip_edges": true, "subtract_mean": true, "window_type": "rectangular"} +{"blackman_coeff": 3.07, "dither": 0, "energy_floor": 3.5254, "frame_length": 0.75, "frame_shift": 0.875, "preemphasis_coefficient": 0.96, "raw_energy": false, "remove_dc_offset": true, "round_to_power_of_two": false, "snip_edges": true, "subtract_mean": false, "window_type": "povey"} +{"blackman_coeff": 3.1297, "dither": 0, "energy_floor": 0.3513, "frame_length": 0.4375, "frame_shift": 0.3125, "preemphasis_coefficient": 0.2, "raw_energy": true, "remove_dc_offset": true, "round_to_power_of_two": true, "snip_edges": true, "subtract_mean": false, "window_type": "povey"} +{"blackman_coeff": 3.2523, "dither": 0, "energy_floor": 3.5376, "frame_length": 0.3125, "frame_shift": 0.25, "preemphasis_coefficient": 0.46, "raw_energy": false, "remove_dc_offset": false, "round_to_power_of_two": true, "snip_edges": true, "subtract_mean": true, "window_type": "rectangular"} +{"blackman_coeff": 3.3896, "dither": 0, "energy_floor": 0.4666, "frame_length": 1.125, "frame_shift": 0.25, "preemphasis_coefficient": 0.05, "raw_energy": false, "remove_dc_offset": true, "round_to_power_of_two": false, "snip_edges": false, "subtract_mean": false, "window_type": "rectangular"} +{"blackman_coeff": 3.537, "dither": 0, "energy_floor": 1.7032, "frame_length": 0.375, "frame_shift": 0.875, "preemphasis_coefficient": 0.17, "raw_energy": false, "remove_dc_offset": true, "round_to_power_of_two": true, "snip_edges": false, "subtract_mean": true, "window_type": "hamming"} +{"blackman_coeff": 3.5378, "dither": 0, "energy_floor": 3.6594, "frame_length": 0.25, "frame_shift": 0.625, "preemphasis_coefficient": 0.54, "raw_energy": true, "remove_dc_offset": true, "round_to_power_of_two": true, "snip_edges": true, "subtract_mean": true, "window_type": "rectangular"} +{"blackman_coeff": 3.5847, "dither": 0, "energy_floor": 3.6357, "frame_length": 1.0, "frame_shift": 0.3125, "preemphasis_coefficient": 0.79, "raw_energy": false, "remove_dc_offset": false, "round_to_power_of_two": false, "snip_edges": true, "subtract_mean": false, "window_type": "povey"} +{"blackman_coeff": 3.6057, "dither": 0, "energy_floor": 1.6902, "frame_length": 1.0625, "frame_shift": 0.6875, "preemphasis_coefficient": 0.65, "raw_energy": false, "remove_dc_offset": true, "round_to_power_of_two": true, "snip_edges": true, "subtract_mean": false, "window_type": "blackman"} +{"blackman_coeff": 3.6498, "dither": 0, "energy_floor": 0.2005, "frame_length": 0.9375, "frame_shift": 1.125, "preemphasis_coefficient": 0.37, "raw_energy": false, "remove_dc_offset": true, "round_to_power_of_two": true, "snip_edges": false, "subtract_mean": true, "window_type": "rectangular"} +{"blackman_coeff": 3.6648, "dither": 0, "energy_floor": 4.6742, "frame_length": 0.625, "frame_shift": 1.1875, "preemphasis_coefficient": 0.88, "raw_energy": false, "remove_dc_offset": true, "round_to_power_of_two": false, "snip_edges": true, "subtract_mean": true, "window_type": "blackman"} +{"blackman_coeff": 3.6701, "dither": 0, "energy_floor": 3.7451, "frame_length": 0.8125, "frame_shift": 0.25, "preemphasis_coefficient": 0.19, "raw_energy": true, "remove_dc_offset": false, "round_to_power_of_two": true, "snip_edges": true, "subtract_mean": true, "window_type": "blackman"} +{"blackman_coeff": 3.7232, "dither": 0, "energy_floor": 0.4912, "frame_length": 0.375, "frame_shift": 0.875, "preemphasis_coefficient": 0.34, "raw_energy": false, "remove_dc_offset": true, "round_to_power_of_two": false, "snip_edges": false, "subtract_mean": true, "window_type": "rectangular"} +{"blackman_coeff": 3.7605, "dither": 0, "energy_floor": 1.6813, "frame_length": 0.25, "frame_shift": 0.5625, "preemphasis_coefficient": 0.27, "raw_energy": true, "remove_dc_offset": true, "round_to_power_of_two": true, "snip_edges": false, "subtract_mean": false, "window_type": "rectangular"} +{"blackman_coeff": 3.7759, "dither": 0, "energy_floor": 1.7002, "frame_length": 1.0625, "frame_shift": 0.6875, "preemphasis_coefficient": 0.42, "raw_energy": false, "remove_dc_offset": false, "round_to_power_of_two": true, "snip_edges": true, "subtract_mean": true, "window_type": "hamming"} +{"blackman_coeff": 3.7921, "dither": 0, "energy_floor": 3.4087, "frame_length": 0.25, "frame_shift": 1.0, "preemphasis_coefficient": 0.54, "raw_energy": true, "remove_dc_offset": true, "round_to_power_of_two": true, "snip_edges": false, "subtract_mean": false, "window_type": "blackman"} +{"blackman_coeff": 3.7954, "dither": 0, "energy_floor": 3.5651, "frame_length": 0.5, "frame_shift": 0.8125, "preemphasis_coefficient": 0.06, "raw_energy": false, "remove_dc_offset": true, "round_to_power_of_two": true, "snip_edges": false, "subtract_mean": true, "window_type": "blackman"} +{"blackman_coeff": 3.799, "dither": 0, "energy_floor": 3.0026, "frame_length": 0.625, "frame_shift": 1.0, "preemphasis_coefficient": 0.82, "raw_energy": false, "remove_dc_offset": true, "round_to_power_of_two": false, "snip_edges": true, "subtract_mean": true, "window_type": "hamming"} +{"blackman_coeff": 3.8659, "dither": 0, "energy_floor": 1.7487, "frame_length": 1.1875, "frame_shift": 0.375, "preemphasis_coefficient": 1.0, "raw_energy": true, "remove_dc_offset": true, "round_to_power_of_two": true, "snip_edges": true, "subtract_mean": false, "window_type": "hanning"} +{"blackman_coeff": 3.951, "dither": 0, "energy_floor": 0.3903, "frame_length": 1.125, "frame_shift": 1.0, "preemphasis_coefficient": 0.41, "raw_energy": true, "remove_dc_offset": false, "round_to_power_of_two": false, "snip_edges": true, "subtract_mean": true, "window_type": "rectangular"} +{"blackman_coeff": 4.0045, "dither": 0, "energy_floor": 3.061, "frame_length": 0.625, "frame_shift": 1.0625, "preemphasis_coefficient": 0.74, "raw_energy": false, "remove_dc_offset": false, "round_to_power_of_two": true, "snip_edges": false, "subtract_mean": true, "window_type": "hanning"} +{"blackman_coeff": 4.0187, "dither": 0, "energy_floor": 4.8148, "frame_length": 0.375, "frame_shift": 0.6875, "preemphasis_coefficient": 0.68, "raw_energy": true, "remove_dc_offset": true, "round_to_power_of_two": false, "snip_edges": false, "subtract_mean": false, "window_type": "hanning"} +{"blackman_coeff": 4.032, "dither": 0, "energy_floor": 2.2019, "frame_length": 1.125, "frame_shift": 0.25, "preemphasis_coefficient": 0.78, "raw_energy": true, "remove_dc_offset": true, "round_to_power_of_two": true, "snip_edges": true, "subtract_mean": true, "window_type": "rectangular"} +{"blackman_coeff": 4.0627, "dither": 0, "energy_floor": 4.1729, "frame_length": 0.625, "frame_shift": 1.125, "preemphasis_coefficient": 0.89, "raw_energy": false, "remove_dc_offset": false, "round_to_power_of_two": false, "snip_edges": false, "subtract_mean": false, "window_type": "povey"} +{"blackman_coeff": 4.0736, "dither": 0, "energy_floor": 0.9155, "frame_length": 1.0625, "frame_shift": 0.5625, "preemphasis_coefficient": 0.82, "raw_energy": false, "remove_dc_offset": true, "round_to_power_of_two": true, "snip_edges": true, "subtract_mean": true, "window_type": "hamming"} +{"blackman_coeff": 4.1131, "dither": 0, "energy_floor": 3.9204, "frame_length": 0.5, "frame_shift": 0.125, "preemphasis_coefficient": 0.39, "raw_energy": false, "remove_dc_offset": true, "round_to_power_of_two": true, "snip_edges": false, "subtract_mean": false, "window_type": "hanning"} +{"blackman_coeff": 4.1816, "dither": 0, "energy_floor": 1.665, "frame_length": 0.8125, "frame_shift": 0.375, "preemphasis_coefficient": 0.37, "raw_energy": true, "remove_dc_offset": false, "round_to_power_of_two": true, "snip_edges": true, "subtract_mean": false, "window_type": "rectangular"} +{"blackman_coeff": 4.1897, "dither": 0, "energy_floor": 1.2668, "frame_length": 0.1875, "frame_shift": 0.625, "preemphasis_coefficient": 0.74, "raw_energy": true, "remove_dc_offset": false, "round_to_power_of_two": true, "snip_edges": false, "subtract_mean": false, "window_type": "hamming"} +{"blackman_coeff": 4.2217, "dither": 0, "energy_floor": 3.6775, "frame_length": 0.3125, "frame_shift": 0.125, "preemphasis_coefficient": 0.01, "raw_energy": true, "remove_dc_offset": false, "round_to_power_of_two": true, "snip_edges": false, "subtract_mean": false, "window_type": "hamming"} +{"blackman_coeff": 4.2785, "dither": 0, "energy_floor": 0.7201, "frame_length": 0.8125, "frame_shift": 0.8125, "preemphasis_coefficient": 0.3, "raw_energy": false, "remove_dc_offset": false, "round_to_power_of_two": true, "snip_edges": false, "subtract_mean": true, "window_type": "hanning"} +{"blackman_coeff": 4.3304, "dither": 0, "energy_floor": 1.0538, "frame_length": 0.875, "frame_shift": 1.125, "preemphasis_coefficient": 0.92, "raw_energy": true, "remove_dc_offset": false, "round_to_power_of_two": true, "snip_edges": false, "subtract_mean": false, "window_type": "povey"} +{"blackman_coeff": 4.3942, "dither": 0, "energy_floor": 3.9813, "frame_length": 0.75, "frame_shift": 0.6875, "preemphasis_coefficient": 0.27, "raw_energy": false, "remove_dc_offset": true, "round_to_power_of_two": true, "snip_edges": true, "subtract_mean": true, "window_type": "blackman"} +{"blackman_coeff": 4.4432, "dither": 0, "energy_floor": 2.0441, "frame_length": 0.5, "frame_shift": 0.6875, "preemphasis_coefficient": 0.77, "raw_energy": false, "remove_dc_offset": false, "round_to_power_of_two": true, "snip_edges": true, "subtract_mean": false, "window_type": "hanning"} +{"blackman_coeff": 4.4459, "dither": 0, "energy_floor": 0.5135, "frame_length": 0.25, "frame_shift": 0.1875, "preemphasis_coefficient": 0.29, "raw_energy": false, "remove_dc_offset": false, "round_to_power_of_two": true, "snip_edges": false, "subtract_mean": true, "window_type": "hanning"} +{"blackman_coeff": 4.5486, "dither": 0, "energy_floor": 1.3248, "frame_length": 0.1875, "frame_shift": 1.125, "preemphasis_coefficient": 0.91, "raw_energy": false, "remove_dc_offset": false, "round_to_power_of_two": true, "snip_edges": false, "subtract_mean": true, "window_type": "hanning"} +{"blackman_coeff": 4.5535, "dither": 0, "energy_floor": 2.1772, "frame_length": 0.4375, "frame_shift": 0.875, "preemphasis_coefficient": 0.21, "raw_energy": true, "remove_dc_offset": false, "round_to_power_of_two": true, "snip_edges": true, "subtract_mean": true, "window_type": "hanning"} +{"blackman_coeff": 4.5835, "dither": 0, "energy_floor": 0.3781, "frame_length": 0.875, "frame_shift": 0.875, "preemphasis_coefficient": 0.04, "raw_energy": true, "remove_dc_offset": false, "round_to_power_of_two": true, "snip_edges": true, "subtract_mean": true, "window_type": "hamming"} +{"blackman_coeff": 4.6297, "dither": 0, "energy_floor": 2.49, "frame_length": 0.5, "frame_shift": 0.25, "preemphasis_coefficient": 0.03, "raw_energy": false, "remove_dc_offset": false, "round_to_power_of_two": true, "snip_edges": true, "subtract_mean": false, "window_type": "rectangular"} +{"blackman_coeff": 4.6749, "dither": 0, "energy_floor": 4.8853, "frame_length": 0.25, "frame_shift": 0.25, "preemphasis_coefficient": 0.48, "raw_energy": false, "remove_dc_offset": true, "round_to_power_of_two": false, "snip_edges": false, "subtract_mean": false, "window_type": "povey"} +{"blackman_coeff": 4.6971, "dither": 0, "energy_floor": 1.3632, "frame_length": 0.875, "frame_shift": 0.9375, "preemphasis_coefficient": 0.44, "raw_energy": false, "remove_dc_offset": true, "round_to_power_of_two": false, "snip_edges": true, "subtract_mean": false, "window_type": "blackman"} diff --git a/test/common_utils.py b/test/common_utils.py index 00d10a6df1..fe045d9db8 100644 --- a/test/common_utils.py +++ b/test/common_utils.py @@ -1,16 +1,15 @@ import os import tempfile import unittest -from typing import Type, Iterable, Union -from contextlib import contextmanager +from typing import Union from shutil import copytree import torch -from torch.testing._internal.common_utils import TestCase +from torch.testing._internal.common_utils import TestCase as PytorchTestCase import torchaudio _TEST_DIR_PATH = os.path.dirname(os.path.realpath(__file__)) -BACKENDS = torchaudio._backend._audio_backends +BACKENDS = torchaudio.list_audio_backends() def get_asset_path(*paths): @@ -55,24 +54,14 @@ def random_float_tensor(seed, size, a=22695477, c=1, m=2 ** 32): return torch.tensor(arr).float().view(size) / m -@contextmanager -def AudioBackendScope(new_backend): - previous_backend = torchaudio.get_audio_backend() - try: - torchaudio.set_audio_backend(new_backend) - yield - finally: - torchaudio.set_audio_backend(previous_backend) - - def filter_backends_with_mp3(backends): # Filter out backends that do not support mp3 test_filepath = get_asset_path('steam-train-whistle-daniel_simon.mp3') def supports_mp3(backend): + torchaudio.set_audio_backend(backend) try: - with AudioBackendScope(backend): - torchaudio.load(test_filepath) + torchaudio.load(test_filepath) return True except (RuntimeError, ImportError): return False @@ -83,49 +72,38 @@ def supports_mp3(backend): BACKENDS_MP3 = filter_backends_with_mp3(BACKENDS) -class TestBaseMixin: - dtype = None - device = None - - -_SKIP_IF_NO_CUDA = unittest.skipIf(not torch.cuda.is_available(), reason='CUDA not available') +def set_audio_backend(backend): + """Allow additional backend value, 'default'""" + if backend == 'default': + if 'sox' in BACKENDS: + be = 'sox' + elif 'soundfile' in BACKENDS: + be = 'soundfile' + else: + raise unittest.SkipTest('No default backend available') + else: + be = backend + torchaudio.set_audio_backend(be) -def define_test_suite(testbase: Type[TestBaseMixin], dtype: str, device: str): - if dtype not in ['float32', 'float64']: - raise NotImplementedError(f'Unexpected dtype: {dtype}') - if device not in ['cpu', 'cuda']: - raise NotImplementedError(f'Unexpected device: {device}') - name = f'Test{testbase.__name__}_{device.upper()}_{dtype.capitalize()}' - attrs = {'dtype': getattr(torch, dtype), 'device': torch.device(device)} - testsuite = type(name, (testbase, TestCase), attrs) +class TestBaseMixin: + """Mixin to provide consistent way to define device/dtype/backend aware TestCase""" + dtype = None + device = None + backend = None - if device == 'cuda': - testsuite = _SKIP_IF_NO_CUDA(testsuite) - return testsuite + def setUp(self): + super().setUp() + set_audio_backend(self.backend) -def define_test_suites( - scope: dict, - testbases: Iterable[Type[TestBaseMixin]], - dtypes: Iterable[str] = ('float32', 'float64'), - devices: Iterable[str] = ('cpu', 'cuda'), -): - for suite in testbases: - for device in devices: - for dtype in dtypes: - t = define_test_suite(suite, dtype, device) - scope[t.__name__] = t +class TorchaudioTestCase(TestBaseMixin, PytorchTestCase): + pass -def common_test_class_parameters( - dtypes: Iterable[str] = ("float32", "float64"), - devices: Iterable[str] = ("cpu", "cuda"), -): - for device in devices: - for dtype in dtypes: - yield {"device": torch.device(device), "dtype": getattr(torch, dtype)} +skipIfNoSoxBackend = unittest.skipIf('sox' not in BACKENDS, 'Sox backend not available') +skipIfNoCuda = unittest.skipIf(not torch.cuda.is_available(), reason='CUDA not available') def get_whitenoise( diff --git a/test/test_functional.py b/test/functional_cpu_test.py similarity index 90% rename from test/test_functional.py rename to test/functional_cpu_test.py index ac90b7bde5..470d6ab770 100644 --- a/test/test_functional.py +++ b/test/functional_cpu_test.py @@ -7,38 +7,20 @@ import pytest from . import common_utils +from .functional_impl import Lfilter -class Lfilter(common_utils.TestBaseMixin): - def test_simple(self): - """ - Create a very basic signal, - Then make a simple 4th order delay - The output should be same as the input but shifted - """ +class TestLFilterFloat32(Lfilter, common_utils.PytorchTestCase): + dtype = torch.float32 + device = torch.device('cpu') - torch.random.manual_seed(42) - waveform = torch.rand(2, 44100 * 1, dtype=self.dtype, device=self.device) - b_coeffs = torch.tensor([0, 0, 0, 1], dtype=self.dtype, device=self.device) - a_coeffs = torch.tensor([1, 0, 0, 0], dtype=self.dtype, device=self.device) - output_waveform = F.lfilter(waveform, a_coeffs, b_coeffs) - self.assertEqual(output_waveform[:, 3:], waveform[:, 0:-3], atol=1e-5, rtol=1e-5) +class TestLFilterFloat64(Lfilter, common_utils.PytorchTestCase): + dtype = torch.float64 + device = torch.device('cpu') - def test_clamp(self): - input_signal = torch.ones(1, 44100 * 1, dtype=self.dtype, device=self.device) - b_coeffs = torch.tensor([1, 0], dtype=self.dtype, device=self.device) - a_coeffs = torch.tensor([1, -0.95], dtype=self.dtype, device=self.device) - output_signal = F.lfilter(input_signal, a_coeffs, b_coeffs, clamp=True) - assert output_signal.max() <= 1 - output_signal = F.lfilter(input_signal, a_coeffs, b_coeffs, clamp=False) - assert output_signal.max() > 1 - -common_utils.define_test_suites(globals(), [Lfilter]) - - -class TestComputeDeltas(unittest.TestCase): +class TestComputeDeltas(common_utils.TorchaudioTestCase): """Test suite for correctness of compute_deltas""" def test_one_channel(self): specgram = torch.tensor([[[1.0, 2.0, 3.0, 4.0]]]) @@ -75,7 +57,7 @@ def _test_istft_is_inverse_of_stft(kwargs): _compare_estimate(sound, estimate) -class TestIstft(unittest.TestCase): +class TestIstft(common_utils.TorchaudioTestCase): """Test suite for correctness of istft with various input""" number_of_trials = 100 @@ -291,7 +273,9 @@ def test_linearity_of_istft4(self): self._test_linearity_of_istft(data_size, kwargs4, atol=1e-5, rtol=1e-8) -class TestDetectPitchFrequency(unittest.TestCase): +class TestDetectPitchFrequency(common_utils.TorchaudioTestCase): + backend = 'default' + def test_pitch(self): test_filepath_100 = common_utils.get_asset_path("100Hz_44100Hz_16bit_05sec.wav") test_filepath_440 = common_utils.get_asset_path("440Hz_44100Hz_16bit_05sec.wav") @@ -312,7 +296,7 @@ def test_pitch(self): self.assertFalse(s) -class TestDB_to_amplitude(unittest.TestCase): +class TestDB_to_amplitude(common_utils.TorchaudioTestCase): def test_DB_to_amplitude(self): # Make some noise x = torch.rand(1000) @@ -381,7 +365,7 @@ def test_mask_along_axis(specgram, mask_param, mask_value, axis): masked_columns = (mask_specgram == mask_value).sum(other_axis) num_masked_columns = (masked_columns == mask_specgram.size(other_axis)).sum() - num_masked_columns /= mask_specgram.size(0) + num_masked_columns //= mask_specgram.size(0) assert mask_specgram.size() == specgram.size() assert num_masked_columns < mask_param diff --git a/test/functional_cuda_test.py b/test/functional_cuda_test.py new file mode 100644 index 0000000000..9602dcf071 --- /dev/null +++ b/test/functional_cuda_test.py @@ -0,0 +1,16 @@ +import torch + +from . import common_utils +from .functional_impl import Lfilter + + +@common_utils.skipIfNoCuda +class TestLFilterFloat32(Lfilter, common_utils.PytorchTestCase): + dtype = torch.float32 + device = torch.device('cuda') + + +@common_utils.skipIfNoCuda +class TestLFilterFloat64(Lfilter, common_utils.PytorchTestCase): + dtype = torch.float64 + device = torch.device('cuda') diff --git a/test/functional_impl.py b/test/functional_impl.py new file mode 100644 index 0000000000..fb5e7dc7ac --- /dev/null +++ b/test/functional_impl.py @@ -0,0 +1,31 @@ +"""Test defintion common to CPU and CUDA""" +import torch +import torchaudio.functional as F + +from . import common_utils + + +class Lfilter(common_utils.TestBaseMixin): + def test_simple(self): + """ + Create a very basic signal, + Then make a simple 4th order delay + The output should be same as the input but shifted + """ + + torch.random.manual_seed(42) + waveform = torch.rand(2, 44100 * 1, dtype=self.dtype, device=self.device) + b_coeffs = torch.tensor([0, 0, 0, 1], dtype=self.dtype, device=self.device) + a_coeffs = torch.tensor([1, 0, 0, 0], dtype=self.dtype, device=self.device) + output_waveform = F.lfilter(waveform, a_coeffs, b_coeffs) + + self.assertEqual(output_waveform[:, 3:], waveform[:, 0:-3], atol=1e-5, rtol=1e-5) + + def test_clamp(self): + input_signal = torch.ones(1, 44100 * 1, dtype=self.dtype, device=self.device) + b_coeffs = torch.tensor([1, 0], dtype=self.dtype, device=self.device) + a_coeffs = torch.tensor([1, -0.95], dtype=self.dtype, device=self.device) + output_signal = F.lfilter(input_signal, a_coeffs, b_coeffs, clamp=True) + assert output_signal.max() <= 1 + output_signal = F.lfilter(input_signal, a_coeffs, b_coeffs, clamp=False) + assert output_signal.max() > 1 diff --git a/test/kaldi_compatibility_cpu_test.py b/test/kaldi_compatibility_cpu_test.py index cd85074ac0..3357123296 100644 --- a/test/kaldi_compatibility_cpu_test.py +++ b/test/kaldi_compatibility_cpu_test.py @@ -1,5 +1,14 @@ +import torch + from . import common_utils from .kaldi_compatibility_impl import Kaldi -common_utils.define_test_suites(globals(), [Kaldi], devices=['cpu']) +class TestKaldiFloat32(Kaldi, common_utils.PytorchTestCase): + dtype = torch.float32 + device = torch.device('cpu') + + +class TestKaldiFloat64(Kaldi, common_utils.PytorchTestCase): + dtype = torch.float64 + device = torch.device('cpu') diff --git a/test/kaldi_compatibility_cuda_test.py b/test/kaldi_compatibility_cuda_test.py index acaa2408f5..e23dbf3f40 100644 --- a/test/kaldi_compatibility_cuda_test.py +++ b/test/kaldi_compatibility_cuda_test.py @@ -1,5 +1,16 @@ +import torch + from . import common_utils from .kaldi_compatibility_impl import Kaldi -common_utils.define_test_suites(globals(), [Kaldi], devices=['cuda']) +@common_utils.skipIfNoCuda +class TestKaldiFloat32(Kaldi, common_utils.PytorchTestCase): + dtype = torch.float32 + device = torch.device('cuda') + + +@common_utils.skipIfNoCuda +class TestKaldiFloat64(Kaldi, common_utils.PytorchTestCase): + dtype = torch.float64 + device = torch.device('cuda') diff --git a/test/kaldi_compatibility_impl.py b/test/kaldi_compatibility_impl.py index 2d3313d007..ec58a3fa44 100644 --- a/test/kaldi_compatibility_impl.py +++ b/test/kaldi_compatibility_impl.py @@ -55,6 +55,8 @@ def _load_params(path): class Kaldi(common_utils.TestBaseMixin): + backend = 'sox' + def assert_equal(self, output, *, expected, rtol=None, atol=None): expected = expected.to(dtype=self.dtype, device=self.device) self.assertEqual(output, expected, rtol=rtol, atol=atol) @@ -86,6 +88,17 @@ def test_fbank(self, kwargs): kaldi_result = _run_kaldi(command, 'scp', wave_file) self.assert_equal(result, expected=kaldi_result, rtol=1e-4, atol=1e-8) + @parameterized.expand(_load_params(common_utils.get_asset_path('kaldi_test_spectrogram_args.json'))) + @unittest.skipIf(_not_available('compute-spectrogram-feats'), '`compute-spectrogram-feats` not available') + def test_spectrogram(self, kwargs): + """spectrogram should be numerically compatible with compute-spectrogram-feats""" + wave_file = common_utils.get_asset_path('kaldi_file.wav') + waveform = torchaudio.load_wav(wave_file)[0].to(dtype=self.dtype, device=self.device) + result = torchaudio.compliance.kaldi.spectrogram(waveform, **kwargs) + command = ['compute-spectrogram-feats'] + _convert_args(**kwargs) + ['scp:-', 'ark:-'] + kaldi_result = _run_kaldi(command, 'scp', wave_file) + self.assert_equal(result, expected=kaldi_result, rtol=1e-4, atol=1e-8) + @parameterized.expand(_load_params(common_utils.get_asset_path('kaldi_test_mfcc_args.json'))) @unittest.skipIf(_not_available('compute-mfcc-feats'), '`compute-mfcc-feats` not available') def test_mfcc(self, kwargs): diff --git a/test/test_backend.py b/test/test_backend.py new file mode 100644 index 0000000000..1e8f9e4fd6 --- /dev/null +++ b/test/test_backend.py @@ -0,0 +1,42 @@ +import unittest + +import torchaudio +from torchaudio._internal.module_utils import is_module_available + +from . import common_utils + + +class BackendSwitchMixin: + """Test set/get_audio_backend works""" + backend = None + backend_module = None + + def test_switch(self): + torchaudio.set_audio_backend(self.backend) + if self.backend is None: + assert torchaudio.get_audio_backend() is None + else: + assert torchaudio.get_audio_backend() == self.backend + assert torchaudio.load == self.backend_module.load + assert torchaudio.load_wav == self.backend_module.load_wav + assert torchaudio.save == self.backend_module.save + assert torchaudio.info == self.backend_module.info + + +class TestBackendSwitch_NoBackend(BackendSwitchMixin, common_utils.TorchaudioTestCase): + backend = None + backend_module = torchaudio.backend.no_backend + + +@unittest.skipIf( + not is_module_available('torchaudio._torchaudio'), + 'torchaudio C++ extension not available') +class TestBackendSwitch_SoX(BackendSwitchMixin, common_utils.TorchaudioTestCase): + backend = 'sox' + backend_module = torchaudio.backend.sox_backend + + +@unittest.skipIf(not is_module_available('soundfile'), '"soundfile" not available') +class TestBackendSwitch_soundfile(BackendSwitchMixin, common_utils.TorchaudioTestCase): + backend = 'soundfile' + backend_module = torchaudio.backend.soundfile_backend diff --git a/test/test_batch_consistency.py b/test/test_batch_consistency.py index 103d83bb84..2a88598f88 100644 --- a/test/test_batch_consistency.py +++ b/test/test_batch_consistency.py @@ -2,14 +2,14 @@ import unittest import torch -from torch.testing._internal.common_utils import TestCase import torchaudio import torchaudio.functional as F from . import common_utils -class TestFunctional(TestCase): +class TestFunctional(common_utils.TorchaudioTestCase): + backend = 'default' """Test functions defined in `functional` module""" def assert_batch_consistency( self, functional, tensor, *args, batch_size=1, atol=1e-8, rtol=1e-5, seed=42, **kwargs): @@ -98,12 +98,15 @@ def test_sliding_window_cmn(self): self.assert_batch_consistencies(F.sliding_window_cmn, waveform, center=False, norm_vars=False) def test_vad(self): + common_utils.set_audio_backend('default') filepath = common_utils.get_asset_path("vad-go-mono-32000.wav") waveform, sample_rate = torchaudio.load(filepath) self.assert_batch_consistencies(F.vad, waveform, sample_rate=sample_rate) -class TestTransforms(TestCase): +class TestTransforms(common_utils.TorchaudioTestCase): + backend = 'default' + """Test suite for classes defined in `transforms` module""" def test_batch_AmplitudeToDB(self): spec = torch.rand((6, 201)) diff --git a/test/test_compliance_kaldi.py b/test/test_compliance_kaldi.py index 2a255a5a4b..f9e097e09c 100644 --- a/test/test_compliance_kaldi.py +++ b/test/test_compliance_kaldi.py @@ -1,13 +1,13 @@ -import math import os +import math +import unittest + import torch import torchaudio import torchaudio.compliance.kaldi as kaldi -import unittest from . import common_utils from .compliance import utils as compliance_utils -from .common_utils import AudioBackendScope, BACKENDS def extract_window(window, wave, f, frame_length, frame_shift, snip_edges): @@ -46,7 +46,10 @@ def first_sample_of_frame(frame, window_size, window_shift, snip_edges): window[f, s] = wave[s_in_wave] -class Test_Kaldi(unittest.TestCase): +@common_utils.skipIfNoSoxBackend +class Test_Kaldi(common_utils.TorchaudioTestCase): + backend = 'sox' + test_filepath = common_utils.get_asset_path('kaldi_file.wav') test_8000_filepath = common_utils.get_asset_path('kaldi_file_8000.wav') kaldi_output_dir = common_utils.get_asset_path('kaldi') @@ -158,98 +161,10 @@ def _compliance_test_helper(self, sound_filepath, filepath_key, expected_num_fil self._print_diagnostic(output, kaldi_output) torch.testing.assert_allclose(output, kaldi_output, atol=atol, rtol=rtol) - @unittest.skipIf("sox" not in BACKENDS, "sox not available") - @AudioBackendScope("sox") - def test_spectrogram(self): - def get_output_fn(sound, args): - output = kaldi.spectrogram( - sound, - blackman_coeff=args[1], - dither=args[2], - energy_floor=args[3], - frame_length=args[4], - frame_shift=args[5], - preemphasis_coefficient=args[6], - raw_energy=args[7], - remove_dc_offset=args[8], - round_to_power_of_two=args[9], - snip_edges=args[10], - subtract_mean=args[11], - window_type=args[12]) - return output - - self._compliance_test_helper(self.test_filepath, 'spec', 131, 13, get_output_fn, atol=1e-3, rtol=0) - - @unittest.skipIf("sox" not in BACKENDS, "sox not available") - @AudioBackendScope("sox") - def test_fbank(self): - def get_output_fn(sound, args): - output = kaldi.fbank( - sound, - blackman_coeff=args[1], - dither=0.0, - energy_floor=args[2], - frame_length=args[3], - frame_shift=args[4], - high_freq=args[5], - htk_compat=args[6], - low_freq=args[7], - num_mel_bins=args[8], - preemphasis_coefficient=args[9], - raw_energy=args[10], - remove_dc_offset=args[11], - round_to_power_of_two=args[12], - snip_edges=args[13], - subtract_mean=args[14], - use_energy=args[15], - use_log_fbank=args[16], - use_power=args[17], - vtln_high=args[18], - vtln_low=args[19], - vtln_warp=args[20], - window_type=args[21]) - return output - - self._compliance_test_helper(self.test_filepath, 'fbank', 97, 22, get_output_fn, atol=1e-3, rtol=1e-1) - - @unittest.skipIf("sox" not in BACKENDS, "sox not available") - @AudioBackendScope("sox") - def test_mfcc(self): - def get_output_fn(sound, args): - output = kaldi.mfcc( - sound, - blackman_coeff=args[1], - dither=0.0, - energy_floor=args[2], - frame_length=args[3], - frame_shift=args[4], - high_freq=args[5], - htk_compat=args[6], - low_freq=args[7], - num_mel_bins=args[8], - preemphasis_coefficient=args[9], - raw_energy=args[10], - remove_dc_offset=args[11], - round_to_power_of_two=args[12], - snip_edges=args[13], - subtract_mean=args[14], - use_energy=args[15], - num_ceps=args[16], - cepstral_lifter=args[17], - vtln_high=args[18], - vtln_low=args[19], - vtln_warp=args[20], - window_type=args[21]) - return output - - self._compliance_test_helper(self.test_filepath, 'mfcc', 145, 22, get_output_fn, atol=1e-3) - def test_mfcc_empty(self): # Passing in an empty tensor should result in an error self.assertRaises(AssertionError, kaldi.mfcc, torch.empty(0)) - @unittest.skipIf("sox" not in BACKENDS, "sox not available") - @AudioBackendScope("sox") def test_resample_waveform(self): def get_output_fn(sound, args): output = kaldi.resample_waveform(sound, args[1], args[2]) diff --git a/test/test_dataloader.py b/test/test_dataloader.py index cfcc25e7c4..1bf73ebb64 100644 --- a/test/test_dataloader.py +++ b/test/test_dataloader.py @@ -4,7 +4,6 @@ from torch.utils.data import Dataset, DataLoader from . import common_utils -from .common_utils import AudioBackendScope, BACKENDS class TORCHAUDIODS(Dataset): @@ -28,9 +27,10 @@ def __len__(self): return len(self.data) -class Test_DataLoader(unittest.TestCase): - @unittest.skipIf("sox" not in BACKENDS, "sox not available") - @AudioBackendScope("sox") +class Test_DataLoader(common_utils.TorchaudioTestCase): + backend = 'sox' + + @common_utils.skipIfNoSoxBackend def test_1(self): expected_size = (2, 1, 16000) ds = TORCHAUDIODS() diff --git a/test/test_datasets.py b/test/test_datasets.py index ab1e74e888..3ac7fae8ac 100644 --- a/test/test_datasets.py +++ b/test/test_datasets.py @@ -8,11 +8,13 @@ from torchaudio.datasets.yesno import YESNO from torchaudio.datasets.ljspeech import LJSPEECH from torchaudio.datasets.gtzan import GTZAN +from torchaudio.datasets.cmuarctic import CMUARCTIC from . import common_utils -class TestDatasets(unittest.TestCase): +class TestDatasets(common_utils.TorchaudioTestCase): + backend = 'default' path = common_utils.get_asset_path() def test_yesno(self): @@ -27,12 +29,32 @@ def test_librispeech(self): data = LIBRISPEECH(self.path, "dev-clean") data[0] - @unittest.skipIf("sox" not in common_utils.BACKENDS, "sox not available") + def test_ljspeech(self): + data = LJSPEECH(self.path) + data[0] + + def test_speechcommands(self): + data = SPEECHCOMMANDS(self.path) + data[0] + + def test_gtzan(self): + data = GTZAN(self.path) + data[0] + + def test_cmuarctic(self): + data = CMUARCTIC(self.path) + data[0] + + +@common_utils.skipIfNoSoxBackend +class TestCommonVoice(common_utils.TorchaudioTestCase): + backend = 'sox' + path = common_utils.get_asset_path() + def test_commonvoice(self): data = COMMONVOICE(self.path, url="tatar") data[0] - @unittest.skipIf("sox" not in common_utils.BACKENDS, "sox not available") def test_commonvoice_diskcache(self): data = COMMONVOICE(self.path, url="tatar") data = diskcache_iterator(data) @@ -41,25 +63,12 @@ def test_commonvoice_diskcache(self): # Load data[0] - @unittest.skipIf("sox" not in common_utils.BACKENDS, "sox not available") def test_commonvoice_bg(self): data = COMMONVOICE(self.path, url="tatar") data = bg_iterator(data, 5) for _ in data: pass - def test_ljspeech(self): - data = LJSPEECH(self.path) - data[0] - - def test_speechcommands(self): - data = SPEECHCOMMANDS(self.path) - data[0] - - def test_gtzan(self): - data = GTZAN(self.path) - data[0] - if __name__ == "__main__": unittest.main() diff --git a/test/test_io.py b/test/test_io.py index 0295cb785e..f58f66ed11 100644 --- a/test/test_io.py +++ b/test/test_io.py @@ -1,9 +1,11 @@ +import os +import math import unittest + import torch import torchaudio -import math -import os -from .common_utils import AudioBackendScope, BACKENDS, BACKENDS_MP3, create_temp_assets_dir + +from .common_utils import BACKENDS, BACKENDS_MP3, create_temp_assets_dir class Test_LoadSave(unittest.TestCase): @@ -16,13 +18,13 @@ class Test_LoadSave(unittest.TestCase): def test_1_save(self): for backend in BACKENDS_MP3: with self.subTest(): - with AudioBackendScope(backend): - self._test_1_save(self.test_filepath, False) + torchaudio.set_audio_backend(backend) + self._test_1_save(self.test_filepath, False) for backend in BACKENDS: with self.subTest(): - with AudioBackendScope(backend): - self._test_1_save(self.test_filepath_wav, True) + torchaudio.set_audio_backend(backend) + self._test_1_save(self.test_filepath_wav, True) def _test_1_save(self, test_filepath, normalization): # load signal @@ -67,8 +69,8 @@ def _test_1_save(self, test_filepath, normalization): def test_1_save_sine(self): for backend in BACKENDS: with self.subTest(): - with AudioBackendScope(backend): - self._test_1_save_sine() + torchaudio.set_audio_backend(backend) + self._test_1_save_sine() def _test_1_save_sine(self): @@ -100,13 +102,13 @@ def _test_1_save_sine(self): def test_2_load(self): for backend in BACKENDS_MP3: with self.subTest(): - with AudioBackendScope(backend): - self._test_2_load(self.test_filepath, 278756) + torchaudio.set_audio_backend(backend) + self._test_2_load(self.test_filepath, 278756) for backend in BACKENDS: with self.subTest(): - with AudioBackendScope(backend): - self._test_2_load(self.test_filepath_wav, 276858) + torchaudio.set_audio_backend(backend) + self._test_2_load(self.test_filepath_wav, 276858) def _test_2_load(self, test_filepath, length): # check normal loading @@ -141,8 +143,8 @@ def _test_2_load(self, test_filepath, length): def test_2_load_nonormalization(self): for backend in BACKENDS_MP3: with self.subTest(): - with AudioBackendScope(backend): - self._test_2_load_nonormalization(self.test_filepath, 278756) + torchaudio.set_audio_backend(backend) + self._test_2_load_nonormalization(self.test_filepath, 278756) def _test_2_load_nonormalization(self, test_filepath, length): @@ -158,8 +160,8 @@ def _test_2_load_nonormalization(self, test_filepath, length): def test_3_load_and_save_is_identity(self): for backend in BACKENDS: with self.subTest(): - with AudioBackendScope(backend): - self._test_3_load_and_save_is_identity() + torchaudio.set_audio_backend(backend) + self._test_3_load_and_save_is_identity() def _test_3_load_and_save_is_identity(self): input_path = os.path.join(self.test_dirpath, 'assets', 'sinewave.wav') @@ -179,16 +181,15 @@ def test_3_load_and_save_is_identity_across_backend(self): self._test_3_load_and_save_is_identity_across_backend("soundfile", "sox") def _test_3_load_and_save_is_identity_across_backend(self, backend1, backend2): - with AudioBackendScope(backend1): - - input_path = os.path.join(self.test_dirpath, 'assets', 'sinewave.wav') - tensor1, sample_rate1 = torchaudio.load(input_path) + torchaudio.set_audio_backend(backend1) + input_path = os.path.join(self.test_dirpath, 'assets', 'sinewave.wav') + tensor1, sample_rate1 = torchaudio.load(input_path) - output_path = os.path.join(self.test_dirpath, 'test.wav') - torchaudio.save(output_path, tensor1, sample_rate1) + output_path = os.path.join(self.test_dirpath, 'test.wav') + torchaudio.save(output_path, tensor1, sample_rate1) - with AudioBackendScope(backend2): - tensor2, sample_rate2 = torchaudio.load(output_path) + torchaudio.set_audio_backend(backend2) + tensor2, sample_rate2 = torchaudio.load(output_path) self.assertTrue(tensor1.allclose(tensor2)) self.assertEqual(sample_rate1, sample_rate2) @@ -197,8 +198,8 @@ def _test_3_load_and_save_is_identity_across_backend(self, backend1, backend2): def test_4_load_partial(self): for backend in BACKENDS_MP3: with self.subTest(): - with AudioBackendScope(backend): - self._test_4_load_partial() + torchaudio.set_audio_backend(backend) + self._test_4_load_partial() def _test_4_load_partial(self): num_frames = 101 @@ -239,8 +240,8 @@ def _test_4_load_partial(self): def test_5_get_info(self): for backend in BACKENDS: with self.subTest(): - with AudioBackendScope(backend): - self._test_5_get_info() + torchaudio.set_audio_backend(backend) + self._test_5_get_info() def _test_5_get_info(self): input_path = os.path.join(self.test_dirpath, 'assets', 'sinewave.wav') diff --git a/test/test_kaldi_io.py b/test/test_kaldi_io.py index 942b11de35..4bd0fd56a4 100644 --- a/test/test_kaldi_io.py +++ b/test/test_kaldi_io.py @@ -6,7 +6,7 @@ from . import common_utils -class Test_KaldiIO(unittest.TestCase): +class Test_KaldiIO(common_utils.TorchaudioTestCase): data1 = [[1, 2, 3], [11, 12, 13], [21, 22, 23]] data2 = [[31, 32, 33], [41, 42, 43], [51, 52, 53]] diff --git a/test/test_librosa_compatibility.py b/test/test_librosa_compatibility.py index 665341d945..62e9d3ca88 100644 --- a/test/test_librosa_compatibility.py +++ b/test/test_librosa_compatibility.py @@ -4,12 +4,13 @@ from distutils.version import StrictVersion import torch -from torch.testing._internal.common_utils import TestCase import torchaudio import torchaudio.functional as F -from torchaudio.common_utils import IMPORT_LIBROSA +from torchaudio._internal.module_utils import is_module_available -if IMPORT_LIBROSA: +LIBROSA_AVAILABLE = is_module_available('librosa') + +if LIBROSA_AVAILABLE: import numpy as np import librosa import scipy @@ -19,8 +20,8 @@ from . import common_utils -@unittest.skipIf(not IMPORT_LIBROSA, "Librosa not available") -class TestFunctional(TestCase): +@unittest.skipIf(not LIBROSA_AVAILABLE, "Librosa not available") +class TestFunctional(common_utils.TorchaudioTestCase): """Test suite for functions in `functional` module.""" def test_griffinlim(self): # NOTE: This test is flaky without a fixed random seed @@ -115,12 +116,8 @@ def test_amplitude_to_DB(self): ]) @pytest.mark.parametrize('rate', [0.5, 1.01, 1.3]) @pytest.mark.parametrize('hop_length', [256]) +@unittest.skipIf(not LIBROSA_AVAILABLE, "Librosa not available") def test_phase_vocoder(complex_specgrams, rate, hop_length): - - # Using a decorator here causes parametrize to fail on Python 2 - if not IMPORT_LIBROSA: - raise unittest.SkipTest('Librosa is not available') - # Due to cummulative sum, numerical error in using torch.float32 will # result in bottom right values of the stretched sectrogram to not # match with librosa. @@ -158,10 +155,11 @@ def _load_audio_asset(*asset_paths, **kwargs): return sound, sample_rate -@unittest.skipIf(not IMPORT_LIBROSA, "Librosa not available") -class TestTransforms(TestCase): +@unittest.skipIf(not LIBROSA_AVAILABLE, "Librosa not available") +class TestTransforms(common_utils.TorchaudioTestCase): """Test suite for functions in `transforms` module.""" def assert_compatibilities(self, n_fft, hop_length, power, n_mels, n_mfcc, sample_rate): + common_utils.set_audio_backend('default') sound, sample_rate = _load_audio_asset('sinewave.wav') sound_librosa = sound.cpu().numpy().squeeze() # (64000) @@ -271,8 +269,7 @@ def test_basics4(self): } self.assert_compatibilities(**kwargs) - @unittest.skipIf("sox" not in common_utils.BACKENDS, "sox not available") - @common_utils.AudioBackendScope("sox") + @unittest.skipIf(not common_utils.BACKENDS_MP3, 'no backend to read mp3') def test_MelScale(self): """MelScale transform is comparable to that of librosa""" n_fft = 2048 @@ -280,6 +277,7 @@ def test_MelScale(self): hop_length = n_fft // 4 # Prepare spectrogram input. We use torchaudio to compute one. + common_utils.set_audio_backend('default') sound, sample_rate = _load_audio_asset('whitenoise_1min.mp3') sound = sound.mean(dim=0, keepdim=True) spec_ta = F.spectrogram( @@ -302,6 +300,7 @@ def test_InverseMelScale(self): hop_length = n_fft // 4 # Prepare mel spectrogram input. We use torchaudio to compute one. + common_utils.set_audio_backend('default') sound, sample_rate = _load_audio_asset( 'steam-train-whistle-daniel_simon.wav', offset=2**10, num_frames=2**14) sound = sound.mean(dim=0, keepdim=True) diff --git a/test/test_models.py b/test/test_models.py index fe8df9a167..7bd3f3819d 100644 --- a/test/test_models.py +++ b/test/test_models.py @@ -1,30 +1,51 @@ -import pytest - import torch -from torchaudio.models import Wav2Letter +from torchaudio.models import Wav2Letter, _MelResNet class TestWav2Letter: - @pytest.mark.parametrize('batch_size', [2]) - @pytest.mark.parametrize('num_features', [1]) - @pytest.mark.parametrize('num_classes', [40]) - @pytest.mark.parametrize('input_length', [320]) - def test_waveform(self, batch_size, num_features, num_classes, input_length): - model = Wav2Letter() + + def test_waveform(self): + batch_size = 2 + num_features = 1 + num_classes = 40 + input_length = 320 + + model = Wav2Letter(num_classes=num_classes, num_features=num_features) x = torch.rand(batch_size, num_features, input_length) out = model(x) assert out.size() == (batch_size, num_classes, 2) - @pytest.mark.parametrize('batch_size', [2]) - @pytest.mark.parametrize('num_features', [13]) - @pytest.mark.parametrize('num_classes', [40]) - @pytest.mark.parametrize('input_length', [2]) - def test_mfcc(self, batch_size, num_features, num_classes, input_length): - model = Wav2Letter(input_type="mfcc", num_features=13) + def test_mfcc(self): + batch_size = 2 + num_features = 13 + num_classes = 40 + input_length = 2 + + model = Wav2Letter(num_classes=num_classes, input_type="mfcc", num_features=num_features) x = torch.rand(batch_size, num_features, input_length) out = model(x) assert out.size() == (batch_size, num_classes, 2) + + +class TestMelResNet: + + def test_waveform(self): + + batch_size = 2 + num_features = 200 + input_dims = 100 + output_dims = 128 + res_blocks = 10 + hidden_dims = 128 + pad = 2 + + model = _MelResNet(res_blocks, input_dims, hidden_dims, output_dims, pad) + + x = torch.rand(batch_size, input_dims, num_features) + out = model(x) + + assert out.size() == (batch_size, output_dims, num_features - pad * 2) diff --git a/test/test_sox_compatibility.py b/test/test_sox_compatibility.py index b6e6dbaedd..23d58a3fb1 100644 --- a/test/test_sox_compatibility.py +++ b/test/test_sox_compatibility.py @@ -1,18 +1,17 @@ import unittest import torch -from torch.testing._internal.common_utils import TestCase import torchaudio import torchaudio.functional as F import torchaudio.transforms as T from . import common_utils -from .common_utils import AudioBackendScope, BACKENDS -class TestFunctionalFiltering(TestCase): - @unittest.skipIf("sox" not in BACKENDS, "sox not available") - @AudioBackendScope("sox") +@common_utils.skipIfNoSoxBackend +class TestFunctionalFiltering(common_utils.TorchaudioTestCase): + backend = 'sox' + def test_gain(self): test_filepath = common_utils.get_asset_path('steam-train-whistle-daniel_simon.wav') waveform, _ = torchaudio.load(test_filepath) @@ -27,8 +26,6 @@ def test_gain(self): self.assertEqual(waveform_gain, sox_gain_waveform, atol=1e-04, rtol=1e-5) - @unittest.skipIf("sox" not in BACKENDS, "sox not available") - @AudioBackendScope("sox") def test_dither(self): test_filepath = common_utils.get_asset_path('steam-train-whistle-daniel_simon.wav') waveform, _ = torchaudio.load(test_filepath) @@ -49,8 +46,6 @@ def test_dither(self): self.assertEqual(waveform_dithered_noiseshaped, sox_dither_waveform_ns, atol=1e-02, rtol=1e-5) - @unittest.skipIf("sox" not in BACKENDS, "sox not available") - @AudioBackendScope("sox") def test_vctk_transform_pipeline(self): test_filepath_vctk = common_utils.get_asset_path('VCTK-Corpus', 'wav48', 'p224', 'p224_002.wav') wf_vctk, sr_vctk = torchaudio.load(test_filepath_vctk) @@ -72,8 +67,6 @@ def test_vctk_transform_pipeline(self): self.assertEqual(wf_vctk, wf_vctk_sox, rtol=1e-03, atol=1e-03) - @unittest.skipIf("sox" not in BACKENDS, "sox not available") - @AudioBackendScope("sox") def test_lowpass(self): """ Test biquad lowpass filter, compare to SoX implementation @@ -92,8 +85,6 @@ def test_lowpass(self): self.assertEqual(output_waveform, sox_output_waveform, atol=1e-4, rtol=1e-5) - @unittest.skipIf("sox" not in BACKENDS, "sox not available") - @AudioBackendScope("sox") def test_highpass(self): """ Test biquad highpass filter, compare to SoX implementation @@ -113,8 +104,6 @@ def test_highpass(self): # TBD - this fails at the 1e-4 level, debug why self.assertEqual(output_waveform, sox_output_waveform, atol=1e-3, rtol=1e-5) - @unittest.skipIf("sox" not in BACKENDS, "sox not available") - @AudioBackendScope("sox") def test_allpass(self): """ Test biquad allpass filter, compare to SoX implementation @@ -134,8 +123,6 @@ def test_allpass(self): self.assertEqual(output_waveform, sox_output_waveform, atol=1e-4, rtol=1e-5) - @unittest.skipIf("sox" not in BACKENDS, "sox not available") - @AudioBackendScope("sox") def test_bandpass_with_csg(self): """ Test biquad bandpass filter, compare to SoX implementation @@ -156,8 +143,6 @@ def test_bandpass_with_csg(self): self.assertEqual(output_waveform, sox_output_waveform, atol=1e-4, rtol=1e-5) - @unittest.skipIf("sox" not in BACKENDS, "sox not available") - @AudioBackendScope("sox") def test_bandpass_without_csg(self): """ Test biquad bandpass filter, compare to SoX implementation @@ -178,8 +163,6 @@ def test_bandpass_without_csg(self): self.assertEqual(output_waveform, sox_output_waveform, atol=1e-4, rtol=1e-5) - @unittest.skipIf("sox" not in BACKENDS, "sox not available") - @AudioBackendScope("sox") def test_bandreject(self): """ Test biquad bandreject filter, compare to SoX implementation @@ -199,8 +182,6 @@ def test_bandreject(self): self.assertEqual(output_waveform, sox_output_waveform, atol=1e-4, rtol=1e-5) - @unittest.skipIf("sox" not in BACKENDS, "sox not available") - @AudioBackendScope("sox") def test_band_with_noise(self): """ Test biquad band filter with noise mode, compare to SoX implementation @@ -221,8 +202,6 @@ def test_band_with_noise(self): self.assertEqual(output_waveform, sox_output_waveform, atol=1e-4, rtol=1e-5) - @unittest.skipIf("sox" not in BACKENDS, "sox not available") - @AudioBackendScope("sox") def test_band_without_noise(self): """ Test biquad band filter without noise mode, compare to SoX implementation @@ -243,8 +222,6 @@ def test_band_without_noise(self): self.assertEqual(output_waveform, sox_output_waveform, atol=1e-4, rtol=1e-5) - @unittest.skipIf("sox" not in BACKENDS, "sox not available") - @AudioBackendScope("sox") def test_treble(self): """ Test biquad treble filter, compare to SoX implementation @@ -265,8 +242,6 @@ def test_treble(self): self.assertEqual(output_waveform, sox_output_waveform, atol=1e-4, rtol=1e-5) - @unittest.skipIf("sox" not in BACKENDS, "sox not available") - @AudioBackendScope("sox") def test_bass(self): """ Test biquad bass filter, compare to SoX implementation @@ -287,8 +262,6 @@ def test_bass(self): self.assertEqual(output_waveform, sox_output_waveform, atol=1.5e-4, rtol=1e-5) - @unittest.skipIf("sox" not in BACKENDS, "sox not available") - @AudioBackendScope("sox") def test_deemph(self): """ Test biquad deemph filter, compare to SoX implementation @@ -305,8 +278,6 @@ def test_deemph(self): self.assertEqual(output_waveform, sox_output_waveform, atol=1e-4, rtol=1e-5) - @unittest.skipIf("sox" not in BACKENDS, "sox not available") - @AudioBackendScope("sox") def test_riaa(self): """ Test biquad riaa filter, compare to SoX implementation @@ -323,8 +294,6 @@ def test_riaa(self): self.assertEqual(output_waveform, sox_output_waveform, atol=1e-4, rtol=1e-5) - @unittest.skipIf("sox" not in BACKENDS, "sox not available") - @AudioBackendScope("sox") def test_contrast(self): """ Test contrast effect, compare to SoX implementation @@ -341,8 +310,6 @@ def test_contrast(self): self.assertEqual(output_waveform, sox_output_waveform, atol=1e-4, rtol=1e-5) - @unittest.skipIf("sox" not in BACKENDS, "sox not available") - @AudioBackendScope("sox") def test_dcshift_with_limiter(self): """ Test dcshift effect, compare to SoX implementation @@ -360,8 +327,6 @@ def test_dcshift_with_limiter(self): self.assertEqual(output_waveform, sox_output_waveform, atol=1e-4, rtol=1e-5) - @unittest.skipIf("sox" not in BACKENDS, "sox not available") - @AudioBackendScope("sox") def test_dcshift_without_limiter(self): """ Test dcshift effect, compare to SoX implementation @@ -378,8 +343,6 @@ def test_dcshift_without_limiter(self): self.assertEqual(output_waveform, sox_output_waveform, atol=1e-4, rtol=1e-5) - @unittest.skipIf("sox" not in BACKENDS, "sox not available") - @AudioBackendScope("sox") def test_overdrive(self): """ Test overdrive effect, compare to SoX implementation @@ -397,8 +360,6 @@ def test_overdrive(self): self.assertEqual(output_waveform, sox_output_waveform, atol=1e-4, rtol=1e-5) - @unittest.skipIf("sox" not in BACKENDS, "sox not available") - @AudioBackendScope("sox") def test_phaser_sine(self): """ Test phaser effect with sine moduldation, compare to SoX implementation @@ -419,8 +380,6 @@ def test_phaser_sine(self): self.assertEqual(output_waveform, sox_output_waveform, atol=1e-4, rtol=1e-5) - @unittest.skipIf("sox" not in BACKENDS, "sox not available") - @AudioBackendScope("sox") def test_phaser_triangle(self): """ Test phaser effect with triangle modulation, compare to SoX implementation @@ -441,8 +400,6 @@ def test_phaser_triangle(self): self.assertEqual(output_waveform, sox_output_waveform, atol=1e-4, rtol=1e-5) - @unittest.skipIf("sox" not in BACKENDS, "sox not available") - @AudioBackendScope("sox") def test_flanger_triangle_linear(self): """ Test flanger effect with triangle modulation and linear interpolation, compare to SoX implementation @@ -465,8 +422,6 @@ def test_flanger_triangle_linear(self): torch.testing.assert_allclose(output_waveform, sox_output_waveform, atol=1e-4, rtol=1e-5) - @unittest.skipIf("sox" not in BACKENDS, "sox not available") - @AudioBackendScope("sox") def test_flanger_triangle_quad(self): """ Test flanger effect with triangle modulation and quadratic interpolation, compare to SoX implementation @@ -489,8 +444,6 @@ def test_flanger_triangle_quad(self): torch.testing.assert_allclose(output_waveform, sox_output_waveform, atol=1e-4, rtol=1e-5) - @unittest.skipIf("sox" not in BACKENDS, "sox not available") - @AudioBackendScope("sox") def test_flanger_sine_linear(self): """ Test flanger effect with sine modulation and linear interpolation, compare to SoX implementation @@ -513,8 +466,6 @@ def test_flanger_sine_linear(self): torch.testing.assert_allclose(output_waveform, sox_output_waveform, atol=1e-4, rtol=1e-5) - @unittest.skipIf("sox" not in BACKENDS, "sox not available") - @AudioBackendScope("sox") def test_flanger_sine_quad(self): """ Test flanger effect with sine modulation and quadratic interpolation, compare to SoX implementation @@ -537,8 +488,6 @@ def test_flanger_sine_quad(self): torch.testing.assert_allclose(output_waveform, sox_output_waveform, atol=1e-4, rtol=1e-5) - @unittest.skipIf("sox" not in BACKENDS, "sox not available") - @AudioBackendScope("sox") def test_equalizer(self): """ Test biquad peaking equalizer filter, compare to SoX implementation @@ -559,8 +508,6 @@ def test_equalizer(self): self.assertEqual(output_waveform, sox_output_waveform, atol=1e-4, rtol=1e-5) - @unittest.skipIf("sox" not in BACKENDS, "sox not available") - @AudioBackendScope("sox") def test_perf_biquad_filtering(self): fn_sine = common_utils.get_asset_path('whitenoise.wav') diff --git a/test/test_sox_effects.py b/test/test_sox_effects.py index 213477537e..68440db8d2 100644 --- a/test/test_sox_effects.py +++ b/test/test_sox_effects.py @@ -1,17 +1,18 @@ +import math import unittest + import torch import torchaudio -import math from . import common_utils -from .common_utils import AudioBackendScope, BACKENDS -class Test_SoxEffectsChain(unittest.TestCase): +@common_utils.skipIfNoSoxBackend +class Test_SoxEffectsChain(common_utils.TorchaudioTestCase): + backend = 'sox' + test_filepath = common_utils.get_asset_path("steam-train-whistle-daniel_simon.mp3") - @unittest.skipIf("sox" not in BACKENDS, "sox not available") - @AudioBackendScope("sox") def test_single_channel(self): fn_sine = common_utils.get_asset_path("sinewave.wav") E = torchaudio.sox_effects.SoxEffectsChain() @@ -21,8 +22,6 @@ def test_single_channel(self): # check if effects worked # print(x.size()) - @unittest.skipIf("sox" not in BACKENDS, "sox not available") - @AudioBackendScope("sox") def test_rate_channels(self): target_rate = 16000 target_channels = 1 @@ -35,8 +34,6 @@ def test_rate_channels(self): self.assertEqual(sr, target_rate) self.assertEqual(x.size(0), target_channels) - @unittest.skipIf("sox" not in BACKENDS, "sox not available") - @AudioBackendScope("sox") def test_lowpass_speed(self): speed = .8 si, _ = torchaudio.info(self.test_filepath) @@ -49,8 +46,6 @@ def test_lowpass_speed(self): # check if effects worked self.assertEqual(x.size(1), int((si.length / si.channels) / speed)) - @unittest.skipIf("sox" not in BACKENDS, "sox not available") - @AudioBackendScope("sox") def test_ulaw_and_siginfo(self): si_out = torchaudio.sox_signalinfo_t() ei_out = torchaudio.sox_encodinginfo_t() @@ -68,8 +63,6 @@ def test_ulaw_and_siginfo(self): self.assertLess(x.unique().size(0), 2**8 + 1) self.assertEqual(x.numel(), si_in.length) - @unittest.skipIf("sox" not in BACKENDS, "sox not available") - @AudioBackendScope("sox") def test_band_chorus(self): si_in, ei_in = torchaudio.info(self.test_filepath) ei_in.encoding = torchaudio.get_sox_encoding_t(1) @@ -84,8 +77,6 @@ def test_band_chorus(self): self.assertEqual(x.size(0), si_in.channels) self.assertGreaterEqual(x.size(1) * x.size(0), si_in.length) - @unittest.skipIf("sox" not in BACKENDS, "sox not available") - @AudioBackendScope("sox") def test_synth(self): si_in, ei_in = torchaudio.info(self.test_filepath) len_in_seconds = si_in.length / si_in.channels / si_in.rate @@ -99,8 +90,6 @@ def test_synth(self): self.assertEqual(x.size(0), si_in.channels) self.assertEqual(si_in.length, x.size(0) * x.size(1)) - @unittest.skipIf("sox" not in BACKENDS, "sox not available") - @AudioBackendScope("sox") def test_gain(self): E = torchaudio.sox_effects.SoxEffectsChain() E.set_input_file(self.test_filepath) @@ -124,8 +113,6 @@ def test_gain(self): E.clear_chain() self.assertLess(x.abs().max().item(), 1.) - @unittest.skipIf("sox" not in BACKENDS, "sox not available") - @AudioBackendScope("sox") def test_tempo_or_speed(self): tempo = .8 si, _ = torchaudio.info(self.test_filepath) @@ -159,8 +146,6 @@ def test_tempo_or_speed(self): # check if effect worked self.assertAlmostEqual(x.size(1), math.ceil((si.length / si.channels) / speed), delta=1) - @unittest.skipIf("sox" not in BACKENDS, "sox not available") - @AudioBackendScope("sox") def test_trim(self): x_orig, _ = torchaudio.load(self.test_filepath) offset = "10000s" @@ -174,8 +159,6 @@ def test_trim(self): # check if effect worked self.assertTrue(x.allclose(x_orig[:, offset_int:(offset_int + num_frames_int)], rtol=1e-4, atol=1e-4)) - @unittest.skipIf("sox" not in BACKENDS, "sox not available") - @AudioBackendScope("sox") def test_silence_contrast(self): si, _ = torchaudio.info(self.test_filepath) E = torchaudio.sox_effects.SoxEffectsChain() @@ -186,8 +169,6 @@ def test_silence_contrast(self): # check if effect worked self.assertLess(x.numel(), si.length) - @unittest.skipIf("sox" not in BACKENDS, "sox not available") - @AudioBackendScope("sox") def test_reverse(self): x_orig, _ = torchaudio.load(self.test_filepath) E = torchaudio.sox_effects.SoxEffectsChain() @@ -198,8 +179,6 @@ def test_reverse(self): rev_idx = torch.LongTensor(range(x_orig.size(1))[::-1]) self.assertTrue(x_orig.allclose(x_rev[:, rev_idx], rtol=1e-5, atol=2e-5)) - @unittest.skipIf("sox" not in BACKENDS, "sox not available") - @AudioBackendScope("sox") def test_compand_fade(self): E = torchaudio.sox_effects.SoxEffectsChain() E.set_input_file(self.test_filepath) @@ -209,8 +188,6 @@ def test_compand_fade(self): # check if effect worked # print(x.size()) - @unittest.skipIf("sox" not in BACKENDS, "sox not available") - @AudioBackendScope("sox") def test_biquad_delay(self): si, _ = torchaudio.info(self.test_filepath) E = torchaudio.sox_effects.SoxEffectsChain() @@ -222,8 +199,6 @@ def test_biquad_delay(self): # check if effect worked self.assertTrue(x.size(1) == (si.length / si.channels) + 15000) - @unittest.skipIf("sox" not in BACKENDS, "sox not available") - @AudioBackendScope("sox") def test_invalid_effect_name(self): E = torchaudio.sox_effects.SoxEffectsChain() E.set_input_file(self.test_filepath) @@ -231,8 +206,6 @@ def test_invalid_effect_name(self): with self.assertRaises(LookupError): E.append_effect_to_chain("special", [""]) - @unittest.skipIf("sox" not in BACKENDS, "sox not available") - @AudioBackendScope("sox") def test_unimplemented_effect(self): E = torchaudio.sox_effects.SoxEffectsChain() E.set_input_file(self.test_filepath) @@ -240,8 +213,6 @@ def test_unimplemented_effect(self): with self.assertRaises(NotImplementedError): E.append_effect_to_chain("spectrogram", [""]) - @unittest.skipIf("sox" not in BACKENDS, "sox not available") - @AudioBackendScope("sox") def test_invalid_effect_options(self): E = torchaudio.sox_effects.SoxEffectsChain() E.set_input_file(self.test_filepath) @@ -250,8 +221,6 @@ def test_invalid_effect_options(self): with self.assertRaises(RuntimeError): E.sox_build_flow_effects() - @unittest.skipIf("sox" not in BACKENDS, "sox not available") - @AudioBackendScope("sox") def test_fade(self): x_orig, _ = torchaudio.load(self.test_filepath) fade_in_len = 44100 @@ -268,8 +237,6 @@ def test_fade(self): # check if effect worked self.assertTrue(x.allclose(fade(x_orig), rtol=1e-4, atol=1e-4)) - @unittest.skipIf("sox" not in BACKENDS, "sox not available") - @AudioBackendScope("sox") def test_vol(self): x_orig, _ = torchaudio.load(self.test_filepath) @@ -284,8 +251,6 @@ def test_vol(self): # check if effect worked self.assertTrue(x.allclose(z, rtol=1e-4, atol=1e-4)) - @unittest.skipIf("sox" not in BACKENDS, "sox not available") - @AudioBackendScope("sox") def test_vad(self): sample_files = [ common_utils.get_asset_path("vad-go-stereo-44100.wav"), diff --git a/test/test_transforms.py b/test/test_transforms.py index ad8a55fb4b..af2b834fdb 100644 --- a/test/test_transforms.py +++ b/test/test_transforms.py @@ -2,7 +2,6 @@ import unittest import torch -from torch.testing._internal.common_utils import TestCase import torchaudio import torchaudio.transforms as transforms import torchaudio.functional as F @@ -10,7 +9,8 @@ from . import common_utils -class Tester(TestCase): +class Tester(common_utils.TorchaudioTestCase): + backend = 'default' # create a sinewave signal for testing sample_rate = 16000 diff --git a/test/torchscript_consistency_cpu_test.py b/test/torchscript_consistency_cpu_test.py index 81e6616821..38fe7961fd 100644 --- a/test/torchscript_consistency_cpu_test.py +++ b/test/torchscript_consistency_cpu_test.py @@ -1,14 +1,24 @@ -from parameterized import parameterized_class +import torch -from .common_utils import TestCase, common_test_class_parameters +from . import common_utils from .torchscript_consistency_impl import Functional, Transforms -parameters = list(common_test_class_parameters(devices=['cpu'])) -@parameterized_class(parameters) -class TestFunctional(Functional, TestCase): - pass +class TestFunctionalFloat32(Functional, common_utils.PytorchTestCase): + dtype = torch.float32 + device = torch.device('cpu') -@parameterized_class(parameters) -class TestTransforms(Transforms, TestCase): - pass + +class TestFunctionalFloat64(Functional, common_utils.PytorchTestCase): + dtype = torch.float64 + device = torch.device('cpu') + + +class TestTransformsFloat32(Transforms, common_utils.PytorchTestCase): + dtype = torch.float32 + device = torch.device('cpu') + + +class TestTransformsFloat64(Transforms, common_utils.PytorchTestCase): + dtype = torch.float64 + device = torch.device('cpu') diff --git a/test/torchscript_consistency_cuda_test.py b/test/torchscript_consistency_cuda_test.py index 0899ba2066..b317334ce4 100644 --- a/test/torchscript_consistency_cuda_test.py +++ b/test/torchscript_consistency_cuda_test.py @@ -1,5 +1,28 @@ -from .common_utils import define_test_suites +import torch + +from . import common_utils from .torchscript_consistency_impl import Functional, Transforms -define_test_suites(globals(), [Functional, Transforms], devices=['cuda']) +@common_utils.skipIfNoCuda +class TestFunctionalFloat32(Functional, common_utils.PytorchTestCase): + dtype = torch.float32 + device = torch.device('cuda') + + +@common_utils.skipIfNoCuda +class TestFunctionalFloat64(Functional, common_utils.PytorchTestCase): + dtype = torch.float64 + device = torch.device('cuda') + + +@common_utils.skipIfNoCuda +class TestTransformsFloat32(Transforms, common_utils.PytorchTestCase): + dtype = torch.float32 + device = torch.device('cuda') + + +@common_utils.skipIfNoCuda +class TestTransformsFloat64(Transforms, common_utils.PytorchTestCase): + dtype = torch.float64 + device = torch.device('cuda') diff --git a/test/torchscript_consistency_impl.py b/test/torchscript_consistency_impl.py index a84b629bd7..2527cd5fbf 100644 --- a/test/torchscript_consistency_impl.py +++ b/test/torchscript_consistency_impl.py @@ -616,5 +616,6 @@ def test_SlidingWindowCmn(self): def test_Vad(self): filepath = common_utils.get_asset_path("vad-go-mono-32000.wav") + common_utils.set_audio_backend('default') waveform, sample_rate = torchaudio.load(filepath) self._assert_consistency(T.Vad(sample_rate=sample_rate), waveform) diff --git a/torchaudio/__init__.py b/torchaudio/__init__.py index a08eaf6964..16419ff3ff 100644 --- a/torchaudio/__init__.py +++ b/torchaudio/__init__.py @@ -1,10 +1,5 @@ -import atexit -import os.path -from pathlib import Path -from typing import Any, Callable, Optional, Tuple, Union - -import torch -from torch import Tensor +from . import extension +from torchaudio._internal import module_utils as _mod_utils from torchaudio import ( compliance, datasets, @@ -12,14 +7,23 @@ sox_effects, transforms ) -from torchaudio._backend import ( - check_input, - _audio_backend_guard, - _get_audio_backend_module, +from torchaudio.backend import ( + list_audio_backends, get_audio_backend, set_audio_backend, + save_encinfo, + sox_signalinfo_t, + sox_encodinginfo_t, + get_sox_option_t, + get_sox_encoding_t, + get_sox_bool, + SignalInfo, + EncodingInfo, +) +from torchaudio.sox_effects import ( + init_sox_effects as _init_sox_effects, + shutdown_sox_effects as _shutdown_sox_effects, ) -from torchaudio._soundfile_backend import SignalInfo, EncodingInfo try: from .version import __version__, git_version # noqa: F401 @@ -27,397 +31,25 @@ pass -def load(filepath: Union[str, Path], - out: Optional[Tensor] = None, - normalization: Union[bool, float, Callable] = True, - channels_first: bool = True, - num_frames: int = 0, - offset: int = 0, - signalinfo: Optional[SignalInfo] = None, - encodinginfo: Optional[EncodingInfo] = None, - filetype: Optional[str] = None) -> Tuple[Tensor, int]: - r"""Loads an audio file from disk into a tensor - - Args: - filepath (str or Path): Path to audio file - out (Tensor, optional): An output tensor to use instead of creating one. (Default: ``None``) - normalization (bool, float, or callable, optional): If boolean `True`, then output is divided by `1 << 31` - (assumes signed 32-bit audio), and normalizes to `[-1, 1]`. - If `float`, then output is divided by that number - If `Callable`, then the output is passed as a parameter - to the given function, then the output is divided by - the result. (Default: ``True``) - channels_first (bool, optional): Set channels first or length first in result. (Default: ``True``) - num_frames (int, optional): Number of frames to load. 0 to load everything after the offset. - (Default: ``0``) - offset (int, optional): Number of frames from the start of the file to begin data loading. - (Default: ``0``) - signalinfo (sox_signalinfo_t, optional): A sox_signalinfo_t type, which could be helpful if the - audio type cannot be automatically determined. (Default: ``None``) - encodinginfo (sox_encodinginfo_t, optional): A sox_encodinginfo_t type, which could be set if the - audio type cannot be automatically determined. (Default: ``None``) - filetype (str, optional): A filetype or extension to be set if sox cannot determine it - automatically. (Default: ``None``) - - Returns: - (Tensor, int): An output tensor of size `[C x L]` or `[L x C]` where L is the number - of audio frames and C is the number of channels. An integer which is the sample rate of the - audio (as listed in the metadata of the file) - - Example - >>> data, sample_rate = torchaudio.load('foo.mp3') - >>> print(data.size()) - torch.Size([2, 278756]) - >>> print(sample_rate) - 44100 - >>> data_vol_normalized, _ = torchaudio.load('foo.mp3', normalization=lambda x: torch.abs(x).max()) - >>> print(data_vol_normalized.abs().max()) - 1. - - """ - - return _get_audio_backend_module().load( - filepath, - out=out, - normalization=normalization, - channels_first=channels_first, - num_frames=num_frames, - offset=offset, - signalinfo=signalinfo, - encodinginfo=encodinginfo, - filetype=filetype, - ) - - -def load_wav(filepath: Union[str, Path], **kwargs: Any) -> Tuple[Tensor, int]: - r""" Loads a wave file. It assumes that the wav file uses 16 bit per sample that needs normalization by shifting - the input right by 16 bits. - - Args: - filepath (str or Path): Path to audio file - - Returns: - (Tensor, int): An output tensor of size `[C x L]` or `[L x C]` where L is the number - of audio frames and C is the number of channels. An integer which is the sample rate of the - audio (as listed in the metadata of the file) - """ - kwargs['normalization'] = 1 << 16 - return load(filepath, **kwargs) - - -def save(filepath: str, src: Tensor, sample_rate: int, precision: int = 16, channels_first: bool = True) -> None: - r"""Convenience function for `save_encinfo`. - - Args: - filepath (str): Path to audio file - src (Tensor): An input 2D tensor of shape `[C x L]` or `[L x C]` where L is - the number of audio frames, C is the number of channels - sample_rate (int): An integer which is the sample rate of the - audio (as listed in the metadata of the file) - precision (int, optional): Bit precision (Default: ``16``) - channels_first (bool, optional): Set channels first or length first in result. ( - Default: ``True``) - """ - - return _get_audio_backend_module().save( - filepath, src, sample_rate, precision=precision, channels_first=channels_first - ) - - -@_audio_backend_guard("sox") -def save_encinfo(filepath: str, - src: Tensor, - channels_first: bool = True, - signalinfo: Optional[SignalInfo] = None, - encodinginfo: Optional[EncodingInfo] = None, - filetype: Optional[str] = None) -> None: - r"""Saves a tensor of an audio signal to disk as a standard format like mp3, wav, etc. - - Args: - filepath (str): Path to audio file - src (Tensor): An input 2D tensor of shape `[C x L]` or `[L x C]` where L is - the number of audio frames, C is the number of channels - channels_first (bool, optional): Set channels first or length first in result. (Default: ``True``) - signalinfo (sox_signalinfo_t, optional): A sox_signalinfo_t type, which could be helpful if the - audio type cannot be automatically determined (Default: ``None``). - encodinginfo (sox_encodinginfo_t, optional): A sox_encodinginfo_t type, which could be set if the - audio type cannot be automatically determined (Default: ``None``). - filetype (str, optional): A filetype or extension to be set if sox cannot determine it - automatically. (Default: ``None``) - - Example - >>> data, sample_rate = torchaudio.load('foo.mp3') - >>> torchaudio.save('foo.wav', data, sample_rate) - - """ - ch_idx, len_idx = (0, 1) if channels_first else (1, 0) - - # check if save directory exists - abs_dirpath = os.path.dirname(os.path.abspath(filepath)) - if not os.path.isdir(abs_dirpath): - raise OSError("Directory does not exist: {}".format(abs_dirpath)) - # check that src is a CPU tensor - check_input(src) - # Check/Fix shape of source data - if src.dim() == 1: - # 1d tensors as assumed to be mono signals - src.unsqueeze_(ch_idx) - elif src.dim() > 2 or src.size(ch_idx) > 16: - # assumes num_channels < 16 - raise ValueError( - "Expected format where C < 16, but found {}".format(src.size())) - # sox stores the sample rate as a float, though practically sample rates are almost always integers - # convert integers to floats - if signalinfo: - if signalinfo.rate and not isinstance(signalinfo.rate, float): - if float(signalinfo.rate) == signalinfo.rate: - signalinfo.rate = float(signalinfo.rate) - else: - raise TypeError('Sample rate should be a float or int') - # check if the bit precision (i.e. bits per sample) is an integer - if signalinfo.precision and not isinstance(signalinfo.precision, int): - if int(signalinfo.precision) == signalinfo.precision: - signalinfo.precision = int(signalinfo.precision) - else: - raise TypeError('Bit precision should be an integer') - # programs such as librosa normalize the signal, unnormalize if detected - if src.min() >= -1.0 and src.max() <= 1.0: - src = src * (1 << 31) - src = src.long() - # set filetype and allow for files with no extensions - extension = os.path.splitext(filepath)[1] - filetype = extension[1:] if len(extension) > 0 else filetype - # transpose from C x L -> L x C - if channels_first: - src = src.transpose(1, 0) - # save data to file - src = src.contiguous() - - from . import _torchaudio - _torchaudio.write_audio_file(filepath, src, signalinfo, encodinginfo, filetype) - - -def info(filepath: str) -> Tuple[SignalInfo, EncodingInfo]: - r"""Gets metadata from an audio file without loading the signal. - - Args: - filepath (str): Path to audio file - - Returns: - (sox_signalinfo_t, sox_encodinginfo_t): A si (sox_signalinfo_t) signal - info as a python object. An ei (sox_encodinginfo_t) encoding info - - Example - >>> si, ei = torchaudio.info('foo.wav') - >>> rate, channels, encoding = si.rate, si.channels, ei.encoding - """ - - return _get_audio_backend_module().info(filepath) - - -@_audio_backend_guard("sox") -def sox_signalinfo_t() -> SignalInfo: - r"""Create a sox_signalinfo_t object. This object can be used to set the sample - rate, number of channels, length, bit precision and headroom multiplier - primarily for effects - - Returns: sox_signalinfo_t(object) - - rate (float), sample rate as a float, practically will likely be an integer float - - channel (int), number of audio channels - - precision (int), bit precision - - length (int), length of audio in samples * channels, 0 for unspecified and -1 for unknown - - mult (float, optional), headroom multiplier for effects and ``None`` for no multiplier - - Example - >>> si = torchaudio.sox_signalinfo_t() - >>> si.channels = 1 - >>> si.rate = 16000. - >>> si.precision = 16 - >>> si.length = 0 - """ - - from . import _torchaudio - return _torchaudio.sox_signalinfo_t() - - -@_audio_backend_guard("sox") -def sox_encodinginfo_t() -> EncodingInfo: - r"""Create a sox_encodinginfo_t object. This object can be used to set the encoding - type, bit precision, compression factor, reverse bytes, reverse nibbles, - reverse bits and endianness. This can be used in an effects chain to encode the - final output or to save a file with a specific encoding. For example, one could - use the sox ulaw encoding to do 8-bit ulaw encoding. Note in a tensor output - the result will be a 32-bit number, but number of unique values will be determined by - the bit precision. - - Returns: sox_encodinginfo_t(object) - - encoding (sox_encoding_t), output encoding - - bits_per_sample (int), bit precision, same as `precision` in sox_signalinfo_t - - compression (float), compression for lossy formats, 0.0 for default compression - - reverse_bytes (sox_option_t), reverse bytes, use sox_option_default - - reverse_nibbles (sox_option_t), reverse nibbles, use sox_option_default - - reverse_bits (sox_option_t), reverse bytes, use sox_option_default - - opposite_endian (sox_bool), change endianness, use sox_false - - Example - >>> ei = torchaudio.sox_encodinginfo_t() - >>> ei.encoding = torchaudio.get_sox_encoding_t(1) - >>> ei.bits_per_sample = 16 - >>> ei.compression = 0 - >>> ei.reverse_bytes = torchaudio.get_sox_option_t(2) - >>> ei.reverse_nibbles = torchaudio.get_sox_option_t(2) - >>> ei.reverse_bits = torchaudio.get_sox_option_t(2) - >>> ei.opposite_endian = torchaudio.get_sox_bool(0) - - """ - - from . import _torchaudio - ei = _torchaudio.sox_encodinginfo_t() - sdo = get_sox_option_t(2) # sox_default_option - ei.reverse_bytes = sdo - ei.reverse_nibbles = sdo - ei.reverse_bits = sdo - return ei - - -@_audio_backend_guard("sox") -def get_sox_encoding_t(i: int = None) -> EncodingInfo: - r"""Get enum of sox_encoding_t for sox encodings. - - Args: - i (int, optional): Choose type or get a dict with all possible options - use ``__members__`` to see all options when not specified. (Default: ``None``) - - Returns: - sox_encoding_t: A sox_encoding_t type for output encoding - """ - - from . import _torchaudio - if i is None: - # one can see all possible values using the .__members__ attribute - return _torchaudio.sox_encoding_t - else: - return _torchaudio.sox_encoding_t(i) - - -@_audio_backend_guard("sox") -def get_sox_option_t(i: int = 2) -> Any: - r"""Get enum of sox_option_t for sox encodinginfo options. - - Args: - i (int, optional): Choose type or get a dict with all possible options - use ``__members__`` to see all options when not specified. - (Default: ``sox_option_default`` or ``2``) - Returns: - sox_option_t: A sox_option_t type - """ - - from . import _torchaudio - if i is None: - return _torchaudio.sox_option_t - else: - return _torchaudio.sox_option_t(i) - - -@_audio_backend_guard("sox") -def get_sox_bool(i: int = 0) -> Any: - r"""Get enum of sox_bool for sox encodinginfo options. - - Args: - i (int, optional): Choose type or get a dict with all possible options - use ``__members__`` to see all options when not specified. (Default: - ``sox_false`` or ``0``) - - Returns: - sox_bool: A sox_bool type - """ - - from . import _torchaudio - if i is None: - return _torchaudio.sox_bool - else: - return _torchaudio.sox_bool(i) - - -_SOX_INITIALIZED: Optional[bool] = False -# This variable has a micro lifecycle. (False -> True -> None) -# False: Not initialized -# True: Initialized -# None: Already shut down (should not be initialized again.) - -_SOX_SUCCESS_CODE = 0 -# defined at -# https://fossies.org/dox/sox-14.4.2/sox_8h.html#a8e07e80cebeff3339265d89c387cea93a9ef2b87ec303edfe40751d9a85fadeeb - - -@_audio_backend_guard("sox") +@_mod_utils.deprecated( + "Please remove the function call to initialize_sox. " + "Resource initialization is now automatically handled.") def initialize_sox() -> int: - """Initialize sox for use with effects chains. - - You only need to call this function once to use SoX effects chains multiple times. - It is safe to call this function multiple times as long as ``shutdown_sox`` is not yet called. - Once ``shutdown_sox`` is called, you can no longer use SoX effects and calling this function - results in `RuntimeError`. + """Initialize sox effects. - Note: - This function is not required for simple loading. - - Returns: - int: Code corresponding to sox_error_t enum. See - https://fossies.org/dox/sox-14.4.2/sox_8h.html#a8e07e80cebeff3339265d89c387cea93 + This function is deprecated. See ``torchaudio.sox_effects.init_sox_effects`` """ - global _SOX_INITIALIZED - if _SOX_INITIALIZED is None: - raise RuntimeError('SoX effects chain has been already shut down. Can not initialize again.') - if not _SOX_INITIALIZED: - from . import _torchaudio - code = _torchaudio.initialize_sox() - if code == _SOX_SUCCESS_CODE: - _SOX_INITIALIZED = True - atexit.register(shutdown_sox) - return code - return _SOX_SUCCESS_CODE - - -@_audio_backend_guard("sox") -def shutdown_sox() -> int: - """Showdown sox for effects chain. + _init_sox_effects() - You do not need to call this function as it will be called automatically - at the end of program execution, if ``initialize_sox`` was called. - It is safe to call this function multiple times. +@_mod_utils.deprecated( + "Please remove the function call to torchaudio.shutdown_sox. " + "Resource clean up is now automatically handled. " + "In the unlikely event that you need to manually shutdown sox, " + "please use torchaudio.sox_effects.shutdown_sox_effects.") +def shutdown_sox(): + """Shutdown sox effects. - Returns: - int: Code corresponding to sox_error_t enum. See - https://fossies.org/dox/sox-14.4.2/sox_8h.html#a8e07e80cebeff3339265d89c387cea93 + This function is deprecated. See ``torchaudio.sox_effects.shutdown_sox_effects`` """ - global _SOX_INITIALIZED - if _SOX_INITIALIZED: - from . import _torchaudio - code = _torchaudio.shutdown_sox() - if code == _SOX_INITIALIZED: - _SOX_INITIALIZED = None - return code - return _SOX_SUCCESS_CODE - - -def _audio_normalization(signal: Tensor, normalization: Union[bool, float, Callable]) -> None: - """Audio normalization of a tensor in-place. The normalization can be a bool, - a number, or a callable that takes the audio tensor as an input. SoX uses - 32-bit signed integers internally, thus bool normalizes based on that assumption. - """ - - if not normalization: - return - - if isinstance(normalization, bool): - normalization = 1 << 31 - - if isinstance(normalization, (float, int)): - # normalize with custom value - a = normalization - signal /= a - elif callable(normalization): - a = normalization(signal) - signal /= a + _shutdown_sox_effects() diff --git a/torchaudio/_backend.py b/torchaudio/_backend.py deleted file mode 100644 index f5646d7970..0000000000 --- a/torchaudio/_backend.py +++ /dev/null @@ -1,68 +0,0 @@ -from functools import wraps -from typing import Any, List, Union - -import platform -import torch -from torch import Tensor - -from . import _soundfile_backend, _sox_backend - - -if platform.system() == "Windows": - _audio_backend = "soundfile" - _audio_backends = {"soundfile": _soundfile_backend} -else: - _audio_backend = "sox" - _audio_backends = {"sox": _sox_backend, "soundfile": _soundfile_backend} - - -def set_audio_backend(backend: str) -> None: - """ - Specifies the package used to load. - Args: - backend (str): Name of the backend. One of {}. - """.format(_audio_backends.keys()) - global _audio_backend - if backend not in _audio_backends: - raise ValueError( - "Invalid backend '{}'. Options are {}.".format(backend, _audio_backends.keys()) - ) - _audio_backend = backend - - -def get_audio_backend() -> str: - """ - Gets the name of the package used to load. - """ - return _audio_backend - - -def _get_audio_backend_module() -> Any: - """ - Gets the module backend to load. - """ - backend = get_audio_backend() - return _audio_backends[backend] - - -def _audio_backend_guard(backends: Union[str, List[str]]) -> Any: - - if isinstance(backends, str): - backends = [backends] - - def decorator(func): - @wraps(func) - def wrapper(*args, **kwargs): - if get_audio_backend() not in backends: - raise RuntimeError("Function {} requires backend to be one of {}.".format(func.__name__, backends)) - return func(*args, **kwargs) - return wrapper - - return decorator - - -def check_input(src: Tensor) -> None: - if not torch.is_tensor(src): - raise TypeError('Expected a tensor, got %s' % type(src)) - if src.is_cuda: - raise TypeError('Expected a CPU based tensor, got %s' % type(src)) diff --git a/torchaudio/_internal/__init__.py b/torchaudio/_internal/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/torchaudio/_internal/misc_ops.py b/torchaudio/_internal/misc_ops.py new file mode 100644 index 0000000000..b67b8d1598 --- /dev/null +++ b/torchaudio/_internal/misc_ops.py @@ -0,0 +1,30 @@ +from typing import Union, Callable + +import torch +from torch import Tensor + + +def normalize_audio(signal: Tensor, normalization: Union[bool, float, Callable]) -> None: + """Audio normalization of a tensor in-place. The normalization can be a bool, + a number, or a callable that takes the audio tensor as an input. SoX uses + 32-bit signed integers internally, thus bool normalizes based on that assumption. + """ + + if not normalization: + return + + if isinstance(normalization, bool): + normalization = 1 << 31 + + if isinstance(normalization, (float, int)): + # normalize with custom value + signal /= normalization + elif callable(normalization): + signal /= normalization(signal) + + +def check_input(src: Tensor) -> None: + if not torch.is_tensor(src): + raise TypeError('Expected a tensor, got %s' % type(src)) + if src.is_cuda: + raise TypeError('Expected a CPU based tensor, got %s' % type(src)) diff --git a/torchaudio/_internal/module_utils.py b/torchaudio/_internal/module_utils.py new file mode 100644 index 0000000000..575a76c1ed --- /dev/null +++ b/torchaudio/_internal/module_utils.py @@ -0,0 +1,56 @@ +import warnings +import importlib.util +from typing import Optional +from functools import wraps + + +def is_module_available(*modules: str) -> bool: + r"""Returns if a top-level module with :attr:`name` exists *without** + importing it. This is generally safer than try-catch block around a + `import X`. It avoids third party libraries breaking assumptions of some of + our tests, e.g., setting multiprocessing start method when imported + (see librosa/#747, torchvision/#544). + """ + return all(importlib.util.find_spec(m) is not None for m in modules) + + +def requires_module(*modules: str): + """Decorate function to give error message if invoked without required optional modules. + + This decorator is to give better error message to users rather + than raising ``NameError: name 'module' is not defined`` at random places. + """ + missing = [m for m in modules if not is_module_available(m)] + + if not missing: + # fall through. If all the modules are available, no need to decorate + def decorator(func): + return func + else: + req = f'module: {missing[0]}' if len(missing) == 1 else f'modules: {missing}' + + def decorator(func): + @wraps(func) + def wrapped(*args, **kwargs): + raise RuntimeError(f'{func.__module__}.{func.__name__} requires {req}') + return wrapped + return decorator + + +def deprecated(direction: str, version: Optional[str] = None): + """Decorator to add deprecation message + + Args: + direction: Migration steps to be given to users. + """ + def decorator(func): + @wraps(func) + def wrapped(*args, **kwargs): + message = ( + f'{func.__module__}.{func.__name__} has been deprecated ' + f'and will be removed from {"future" if version is None else version} release.' + f'{direction}') + warnings.warn(message, stacklevel=2) + return func(*args, **kwargs) + return wrapped + return decorator diff --git a/torchaudio/_sox_backend.py b/torchaudio/_sox_backend.py deleted file mode 100644 index 3478d30d50..0000000000 --- a/torchaudio/_sox_backend.py +++ /dev/null @@ -1,72 +0,0 @@ -import os.path -from typing import Optional, Tuple - -import torch -from torch import Tensor -import torchaudio -from torchaudio._soundfile_backend import SignalInfo, EncodingInfo - - -def load(filepath: str, - out: Optional[Tensor] = None, - normalization: bool = True, - channels_first: bool = True, - num_frames: int = 0, - offset: int = 0, - signalinfo: SignalInfo = None, - encodinginfo: EncodingInfo = None, - filetype: Optional[str] = None) -> Tuple[Tensor, int]: - r"""See torchaudio.load""" - - # stringify if `pathlib.Path` (noop if already `str`) - filepath = str(filepath) - # check if valid file - if not os.path.isfile(filepath): - raise OSError("{} not found or is a directory".format(filepath)) - - # initialize output tensor - if out is not None: - torchaudio.check_input(out) - else: - out = torch.FloatTensor() - - if num_frames < -1: - raise ValueError("Expected value for num_samples -1 (entire file) or >=0") - if offset < 0: - raise ValueError("Expected positive offset value") - - from . import _torchaudio - sample_rate = _torchaudio.read_audio_file( - filepath, - out, - channels_first, - num_frames, - offset, - signalinfo, - encodinginfo, - filetype - ) - - # normalize if needed - torchaudio._audio_normalization(out, normalization) - - return out, sample_rate - - -def save(filepath: str, src: Tensor, sample_rate: int, precision: int = 16, channels_first: bool = True) -> None: - r"""See torchaudio.save""" - - si = torchaudio.sox_signalinfo_t() - ch_idx = 0 if channels_first else 1 - si.rate = sample_rate - si.channels = 1 if src.dim() == 1 else src.size(ch_idx) - si.length = src.numel() - si.precision = precision - return torchaudio.save_encinfo(filepath, src, channels_first, si) - - -def info(filepath: str) -> Tuple[SignalInfo, EncodingInfo]: - r"""See torchaudio.info""" - - from . import _torchaudio - return _torchaudio.get_info(filepath) diff --git a/torchaudio/backend/__init__.py b/torchaudio/backend/__init__.py new file mode 100644 index 0000000000..0812c09cf4 --- /dev/null +++ b/torchaudio/backend/__init__.py @@ -0,0 +1,21 @@ +from . import utils +from .utils import ( + list_audio_backends, + get_audio_backend, + set_audio_backend, +) +from .sox_backend import ( + save_encinfo, + sox_signalinfo_t, + sox_encodinginfo_t, + get_sox_option_t, + get_sox_encoding_t, + get_sox_bool, +) +from .common import ( + SignalInfo, + EncodingInfo, +) + + +utils._init_audio_backend() diff --git a/torchaudio/backend/common.py b/torchaudio/backend/common.py new file mode 100644 index 0000000000..0593c34bd5 --- /dev/null +++ b/torchaudio/backend/common.py @@ -0,0 +1,143 @@ +from typing import Any, Optional + + +class SignalInfo: + def __init__(self, + channels: Optional[int] = None, + rate: Optional[float] = None, + precision: Optional[int] = None, + length: Optional[int] = None) -> None: + self.channels = channels + self.rate = rate + self.precision = precision + self.length = length + + +class EncodingInfo: + def __init__(self, + encoding: Any = None, + bits_per_sample: Optional[int] = None, + compression: Optional[float] = None, + reverse_bytes: Any = None, + reverse_nibbles: Any = None, + reverse_bits: Any = None, + opposite_endian: Optional[bool] = None) -> None: + self.encoding = encoding + self.bits_per_sample = bits_per_sample + self.compression = compression + self.reverse_bytes = reverse_bytes + self.reverse_nibbles = reverse_nibbles + self.reverse_bits = reverse_bits + self.opposite_endian = opposite_endian + + +_LOAD_DOCSTRING = r"""Loads an audio file from disk into a tensor + +Args: + filepath: Path to audio file + + out: An optional output tensor to use instead of creating one. (Default: ``None``) + + normalization: Optional normalization. + If boolean `True`, then output is divided by `1 << 31`. + Assuming the input is signed 32-bit audio, this normalizes to `[-1, 1]`. + If `float`, then output is divided by that number. + If `Callable`, then the output is passed as a paramete to the given function, + then the output is divided by the result. (Default: ``True``) + + channels_first: Set channels first or length first in result. (Default: ``True``) + + num_frames: Number of frames to load. 0 to load everything after the offset. + (Default: ``0``) + + offset: Number of frames from the start of the file to begin data loading. + (Default: ``0``) + + signalinfo: A sox_signalinfo_t type, which could be helpful if the + audio type cannot be automatically determined. (Default: ``None``) + + encodinginfo: A sox_encodinginfo_t type, which could be set if the + audio type cannot be automatically determined. (Default: ``None``) + + filetype: A filetype or extension to be set if sox cannot determine it + automatically. (Default: ``None``) + +Returns: + (Tensor, int): An output tensor of size `[C x L]` or `[L x C]` where + L is the number of audio frames and + C is the number of channels. + An integer which is the sample rate of the audio (as listed in the metadata of the file) + +Example + >>> data, sample_rate = torchaudio.load('foo.mp3') + >>> print(data.size()) + torch.Size([2, 278756]) + >>> print(sample_rate) + 44100 + >>> data_vol_normalized, _ = torchaudio.load('foo.mp3', normalization=lambda x: torch.abs(x).max()) + >>> print(data_vol_normalized.abs().max()) + 1. +""" + + +_LOAD_WAV_DOCSTRING = r""" Loads a wave file. + +It assumes that the wav file uses 16 bit per sample that needs normalization by +shifting the input right by 16 bits. + +Args: + filepath: Path to audio file + +Returns: + (Tensor, int): An output tensor of size `[C x L]` or `[L x C]` where L is the number + of audio frames and C is the number of channels. An integer which is the sample rate of the + audio (as listed in the metadata of the file) +""" + +_SAVE_DOCSTRING = r"""Saves a Tensor on file as an audio file + +Args: + filepath: Path to audio file + src: An input 2D tensor of shape `[C x L]` or `[L x C]` where L is + the number of audio frames, C is the number of channels + sample_rate: An integer which is the sample rate of the + audio (as listed in the metadata of the file) + precision Bit precision (Default: ``16``) + channels_first (bool, optional): Set channels first or length first in result. ( + Default: ``True``) +""" + + +_INFO_DOCSTRING = r"""Gets metadata from an audio file without loading the signal. + +Args: + filepath: Path to audio file + +Returns: + (sox_signalinfo_t, sox_encodinginfo_t): A si (sox_signalinfo_t) signal + info as a python object. An ei (sox_encodinginfo_t) encoding info + +Example + >>> si, ei = torchaudio.info('foo.wav') + >>> rate, channels, encoding = si.rate, si.channels, ei.encoding +""" + + +def _impl_load(func): + setattr(func, '__doc__', _LOAD_DOCSTRING) + return func + + +def _impl_load_wav(func): + setattr(func, '__doc__', _LOAD_WAV_DOCSTRING) + return func + + +def _impl_save(func): + setattr(func, '__doc__', _SAVE_DOCSTRING) + return func + + +def _impl_info(func): + setattr(func, '__doc__', _INFO_DOCSTRING) + return func diff --git a/torchaudio/backend/no_backend.py b/torchaudio/backend/no_backend.py new file mode 100644 index 0000000000..60571c34a9 --- /dev/null +++ b/torchaudio/backend/no_backend.py @@ -0,0 +1,35 @@ +from pathlib import Path +from typing import Any, Callable, Optional, Tuple, Union + +from torch import Tensor + +from . import common +from .common import SignalInfo, EncodingInfo + + +@common._impl_load +def load(filepath: Union[str, Path], + out: Optional[Tensor] = None, + normalization: Union[bool, float, Callable] = True, + channels_first: bool = True, + num_frames: int = 0, + offset: int = 0, + signalinfo: Optional[SignalInfo] = None, + encodinginfo: Optional[EncodingInfo] = None, + filetype: Optional[str] = None) -> Tuple[Tensor, int]: + raise RuntimeError('No audio I/O backend is available.') + + +@common._impl_load_wav +def load_wav(filepath: Union[str, Path], **kwargs: Any) -> Tuple[Tensor, int]: + raise RuntimeError('No audio I/O backend is available.') + + +@common._impl_save +def save(filepath: str, src: Tensor, sample_rate: int, precision: int = 16, channels_first: bool = True) -> None: + raise RuntimeError('No audio I/O backend is available.') + + +@common._impl_info +def info(filepath: str) -> Tuple[SignalInfo, EncodingInfo]: + raise RuntimeError('No audio I/O backend is available.') diff --git a/torchaudio/_soundfile_backend.py b/torchaudio/backend/soundfile_backend.py similarity index 67% rename from torchaudio/_soundfile_backend.py rename to torchaudio/backend/soundfile_backend.py index 1a88ba5e80..680264bcd6 100644 --- a/torchaudio/_soundfile_backend.py +++ b/torchaudio/backend/soundfile_backend.py @@ -1,9 +1,20 @@ import os -from typing import Any, Optional, Tuple, Union +from typing import Optional, Tuple import torch from torch import Tensor +from torchaudio._internal import ( + module_utils as _mod_utils, + misc_ops as _misc_ops, +) +from . import common +from .common import SignalInfo, EncodingInfo + +if _mod_utils.is_module_available('soundfile'): + import soundfile + + _subtype_to_precision = { 'PCM_S8': 8, 'PCM_16': 16, @@ -13,43 +24,8 @@ } -class SignalInfo: - def __init__(self, - channels: Optional[int] = None, - rate: Optional[float] = None, - precision: Optional[int] = None, - length: Optional[int] = None) -> None: - self.channels = channels - self.rate = rate - self.precision = precision - self.length = length - - -class EncodingInfo: - def __init__(self, - encoding: Any = None, - bits_per_sample: Optional[int] = None, - compression: Optional[float] = None, - reverse_bytes: Any = None, - reverse_nibbles: Any = None, - reverse_bits: Any = None, - opposite_endian: Optional[bool] = None) -> None: - self.encoding = encoding - self.bits_per_sample = bits_per_sample - self.compression = compression - self.reverse_bytes = reverse_bytes - self.reverse_nibbles = reverse_nibbles - self.reverse_bits = reverse_bits - self.opposite_endian = opposite_endian - - -def check_input(src: Tensor) -> None: - if not torch.is_tensor(src): - raise TypeError("Expected a tensor, got %s" % type(src)) - if src.is_cuda: - raise TypeError("Expected a CPU based tensor, got %s" % type(src)) - - +@_mod_utils.requires_module('soundfile') +@common._impl_load def load(filepath: str, out: Optional[Tensor] = None, normalization: Optional[bool] = True, @@ -80,8 +56,6 @@ def load(filepath: str, if offset < 0: raise ValueError("Expected positive offset value") - import soundfile - # initialize output tensor # TODO call libsoundfile directly to avoid numpy out, sample_rate = soundfile.read( @@ -98,6 +72,15 @@ def load(filepath: str, return out, sample_rate +@_mod_utils.requires_module('soundfile') +@common._impl_load_wav +def load_wav(filepath, **kwargs): + kwargs['normalization'] = 1 << 16 + return load(filepath, **kwargs) + + +@_mod_utils.requires_module('soundfile') +@common._impl_save def save(filepath: str, src: Tensor, sample_rate: int, precision: int = 16, channels_first: bool = True) -> None: r"""See torchaudio.save""" @@ -108,7 +91,7 @@ def save(filepath: str, src: Tensor, sample_rate: int, precision: int = 16, chan if not os.path.isdir(abs_dirpath): raise OSError("Directory does not exist: {}".format(abs_dirpath)) # check that src is a CPU tensor - check_input(src) + _misc_ops.check_input(src) # Check/Fix shape of source data if src.dim() == 1: # 1d tensors as assumed to be mono signals @@ -127,14 +110,14 @@ def save(filepath: str, src: Tensor, sample_rate: int, precision: int = 16, chan precision = "PCM_S8" if precision == 8 else "PCM_" + str(precision) - import soundfile return soundfile.write(filepath, src, sample_rate, precision) +@_mod_utils.requires_module('soundfile') +@common._impl_info def info(filepath: str) -> Tuple[SignalInfo, EncodingInfo]: r"""See torchaudio.info""" - import soundfile sfi = soundfile.info(filepath) precision = _subtype_to_precision[sfi.subtype] diff --git a/torchaudio/backend/sox_backend.py b/torchaudio/backend/sox_backend.py new file mode 100644 index 0000000000..4e2b118f8b --- /dev/null +++ b/torchaudio/backend/sox_backend.py @@ -0,0 +1,275 @@ +import os.path +from typing import Any, Optional, Tuple + +import torch +from torch import Tensor + +from torchaudio._internal import ( + module_utils as _mod_utils, + misc_ops as _misc_ops, +) +from . import common +from .common import SignalInfo, EncodingInfo + +if _mod_utils.is_module_available('torchaudio._torchaudio'): + from torchaudio import _torchaudio + + +@_mod_utils.requires_module('torchaudio._torchaudio') +@common._impl_load +def load(filepath: str, + out: Optional[Tensor] = None, + normalization: bool = True, + channels_first: bool = True, + num_frames: int = 0, + offset: int = 0, + signalinfo: SignalInfo = None, + encodinginfo: EncodingInfo = None, + filetype: Optional[str] = None) -> Tuple[Tensor, int]: + r"""See torchaudio.load""" + + # stringify if `pathlib.Path` (noop if already `str`) + filepath = str(filepath) + # check if valid file + if not os.path.isfile(filepath): + raise OSError("{} not found or is a directory".format(filepath)) + + # initialize output tensor + if out is not None: + _misc_ops.check_input(out) + else: + out = torch.FloatTensor() + + if num_frames < -1: + raise ValueError("Expected value for num_samples -1 (entire file) or >=0") + if offset < 0: + raise ValueError("Expected positive offset value") + + sample_rate = _torchaudio.read_audio_file( + filepath, + out, + channels_first, + num_frames, + offset, + signalinfo, + encodinginfo, + filetype + ) + + # normalize if needed + _misc_ops.normalize_audio(out, normalization) + + return out, sample_rate + + +@_mod_utils.requires_module('torchaudio._torchaudio') +@common._impl_load_wav +def load_wav(filepath, **kwargs): + kwargs['normalization'] = 1 << 16 + return load(filepath, **kwargs) + + +@_mod_utils.requires_module('torchaudio._torchaudio') +@common._impl_save +def save(filepath: str, src: Tensor, sample_rate: int, precision: int = 16, channels_first: bool = True) -> None: + r"""See torchaudio.save""" + + si = sox_signalinfo_t() + ch_idx = 0 if channels_first else 1 + si.rate = sample_rate + si.channels = 1 if src.dim() == 1 else src.size(ch_idx) + si.length = src.numel() + si.precision = precision + return save_encinfo(filepath, src, channels_first, si) + + +@_mod_utils.requires_module('torchaudio._torchaudio') +@common._impl_info +def info(filepath: str) -> Tuple[SignalInfo, EncodingInfo]: + r"""See torchaudio.info""" + return _torchaudio.get_info(filepath) + + +@_mod_utils.requires_module('torchaudio._torchaudio') +def save_encinfo(filepath: str, + src: Tensor, + channels_first: bool = True, + signalinfo: Optional[SignalInfo] = None, + encodinginfo: Optional[EncodingInfo] = None, + filetype: Optional[str] = None) -> None: + r"""Saves a tensor of an audio signal to disk as a standard format like mp3, wav, etc. + + Args: + filepath (str): Path to audio file + src (Tensor): An input 2D tensor of shape `[C x L]` or `[L x C]` where L is + the number of audio frames, C is the number of channels + channels_first (bool, optional): Set channels first or length first in result. (Default: ``True``) + signalinfo (sox_signalinfo_t, optional): A sox_signalinfo_t type, which could be helpful if the + audio type cannot be automatically determined (Default: ``None``). + encodinginfo (sox_encodinginfo_t, optional): A sox_encodinginfo_t type, which could be set if the + audio type cannot be automatically determined (Default: ``None``). + filetype (str, optional): A filetype or extension to be set if sox cannot determine it + automatically. (Default: ``None``) + + Example + >>> data, sample_rate = torchaudio.load('foo.mp3') + >>> torchaudio.save('foo.wav', data, sample_rate) + + """ + ch_idx, len_idx = (0, 1) if channels_first else (1, 0) + + # check if save directory exists + abs_dirpath = os.path.dirname(os.path.abspath(filepath)) + if not os.path.isdir(abs_dirpath): + raise OSError("Directory does not exist: {}".format(abs_dirpath)) + # check that src is a CPU tensor + _misc_ops.check_input(src) + # Check/Fix shape of source data + if src.dim() == 1: + # 1d tensors as assumed to be mono signals + src.unsqueeze_(ch_idx) + elif src.dim() > 2 or src.size(ch_idx) > 16: + # assumes num_channels < 16 + raise ValueError( + "Expected format where C < 16, but found {}".format(src.size())) + # sox stores the sample rate as a float, though practically sample rates are almost always integers + # convert integers to floats + if signalinfo: + if signalinfo.rate and not isinstance(signalinfo.rate, float): + if float(signalinfo.rate) == signalinfo.rate: + signalinfo.rate = float(signalinfo.rate) + else: + raise TypeError('Sample rate should be a float or int') + # check if the bit precision (i.e. bits per sample) is an integer + if signalinfo.precision and not isinstance(signalinfo.precision, int): + if int(signalinfo.precision) == signalinfo.precision: + signalinfo.precision = int(signalinfo.precision) + else: + raise TypeError('Bit precision should be an integer') + # programs such as librosa normalize the signal, unnormalize if detected + if src.min() >= -1.0 and src.max() <= 1.0: + src = src * (1 << 31) + src = src.long() + # set filetype and allow for files with no extensions + extension = os.path.splitext(filepath)[1] + filetype = extension[1:] if len(extension) > 0 else filetype + # transpose from C x L -> L x C + if channels_first: + src = src.transpose(1, 0) + # save data to file + src = src.contiguous() + _torchaudio.write_audio_file(filepath, src, signalinfo, encodinginfo, filetype) + + +@_mod_utils.requires_module('torchaudio._torchaudio') +def sox_signalinfo_t() -> SignalInfo: + r"""Create a sox_signalinfo_t object. This object can be used to set the sample + rate, number of channels, length, bit precision and headroom multiplier + primarily for effects + + Returns: sox_signalinfo_t(object) + - rate (float), sample rate as a float, practically will likely be an integer float + - channel (int), number of audio channels + - precision (int), bit precision + - length (int), length of audio in samples * channels, 0 for unspecified and -1 for unknown + - mult (float, optional), headroom multiplier for effects and ``None`` for no multiplier + + Example + >>> si = torchaudio.sox_signalinfo_t() + >>> si.channels = 1 + >>> si.rate = 16000. + >>> si.precision = 16 + >>> si.length = 0 + """ + return _torchaudio.sox_signalinfo_t() + + +@_mod_utils.requires_module('torchaudio._torchaudio') +def sox_encodinginfo_t() -> EncodingInfo: + r"""Create a sox_encodinginfo_t object. This object can be used to set the encoding + type, bit precision, compression factor, reverse bytes, reverse nibbles, + reverse bits and endianness. This can be used in an effects chain to encode the + final output or to save a file with a specific encoding. For example, one could + use the sox ulaw encoding to do 8-bit ulaw encoding. Note in a tensor output + the result will be a 32-bit number, but number of unique values will be determined by + the bit precision. + + Returns: sox_encodinginfo_t(object) + - encoding (sox_encoding_t), output encoding + - bits_per_sample (int), bit precision, same as `precision` in sox_signalinfo_t + - compression (float), compression for lossy formats, 0.0 for default compression + - reverse_bytes (sox_option_t), reverse bytes, use sox_option_default + - reverse_nibbles (sox_option_t), reverse nibbles, use sox_option_default + - reverse_bits (sox_option_t), reverse bytes, use sox_option_default + - opposite_endian (sox_bool), change endianness, use sox_false + + Example + >>> ei = torchaudio.sox_encodinginfo_t() + >>> ei.encoding = torchaudio.get_sox_encoding_t(1) + >>> ei.bits_per_sample = 16 + >>> ei.compression = 0 + >>> ei.reverse_bytes = torchaudio.get_sox_option_t(2) + >>> ei.reverse_nibbles = torchaudio.get_sox_option_t(2) + >>> ei.reverse_bits = torchaudio.get_sox_option_t(2) + >>> ei.opposite_endian = torchaudio.get_sox_bool(0) + + """ + ei = _torchaudio.sox_encodinginfo_t() + sdo = get_sox_option_t(2) # sox_default_option + ei.reverse_bytes = sdo + ei.reverse_nibbles = sdo + ei.reverse_bits = sdo + return ei + + +@_mod_utils.requires_module('torchaudio._torchaudio') +def get_sox_encoding_t(i: int = None) -> EncodingInfo: + r"""Get enum of sox_encoding_t for sox encodings. + + Args: + i (int, optional): Choose type or get a dict with all possible options + use ``__members__`` to see all options when not specified. (Default: ``None``) + + Returns: + sox_encoding_t: A sox_encoding_t type for output encoding + """ + if i is None: + # one can see all possible values using the .__members__ attribute + return _torchaudio.sox_encoding_t + else: + return _torchaudio.sox_encoding_t(i) + + +@_mod_utils.requires_module('torchaudio._torchaudio') +def get_sox_option_t(i: int = 2) -> Any: + r"""Get enum of sox_option_t for sox encodinginfo options. + + Args: + i (int, optional): Choose type or get a dict with all possible options + use ``__members__`` to see all options when not specified. + (Default: ``sox_option_default`` or ``2``) + Returns: + sox_option_t: A sox_option_t type + """ + if i is None: + return _torchaudio.sox_option_t + else: + return _torchaudio.sox_option_t(i) + + +@_mod_utils.requires_module('torchaudio._torchaudio') +def get_sox_bool(i: int = 0) -> Any: + r"""Get enum of sox_bool for sox encodinginfo options. + + Args: + i (int, optional): Choose type or get a dict with all possible options + use ``__members__`` to see all options when not specified. (Default: + ``sox_false`` or ``0``) + + Returns: + sox_bool: A sox_bool type + """ + if i is None: + return _torchaudio.sox_bool + else: + return _torchaudio.sox_bool(i) diff --git a/torchaudio/backend/utils.py b/torchaudio/backend/utils.py new file mode 100644 index 0000000000..d537f01daf --- /dev/null +++ b/torchaudio/backend/utils.py @@ -0,0 +1,74 @@ +"""Defines utilities for switching audio backends""" +import warnings +from typing import Optional, List + +import torchaudio +from torchaudio._internal.module_utils import is_module_available +from . import ( + no_backend, + sox_backend, + soundfile_backend, +) + +__all__ = [ + 'list_audio_backends', + 'get_audio_backend', + 'set_audio_backend', +] + + +def list_audio_backends() -> List[str]: + """List available backends""" + backends = [] + if is_module_available('soundfile'): + backends.append('soundfile') + if is_module_available('torchaudio._torchaudio'): + backends.append('sox') + return backends + + +def set_audio_backend(backend: Optional[str]) -> None: + """Set the backend for I/O operation + + Args: + backend (str): Name of the backend. One of "sox" or "soundfile", + based on availability of the system. + """ + if backend is not None and backend not in list_audio_backends(): + raise RuntimeError( + f'Backend "{backend}" is not one of ' + f'available backends: {list_audio_backends()}.') + + if backend is None: + module = no_backend + elif backend == 'sox': + module = sox_backend + elif backend == 'soundfile': + module = soundfile_backend + else: + raise NotImplementedError(f'Unexpected backend "{backend}"') + + for func in ['save', 'load', 'load_wav', 'info']: + setattr(torchaudio, func, getattr(module, func)) + + +def _init_audio_backend(): + backends = list_audio_backends() + if 'sox' in backends: + set_audio_backend('sox') + elif 'soundfile' in backends: + set_audio_backend('soundfile') + else: + warnings.warn('No audio backend is available.') + set_audio_backend(None) + + +def get_audio_backend() -> Optional[str]: + """Get the name of the current backend""" + if torchaudio.load == no_backend.load: + return None + if torchaudio.load == sox_backend.load: + return 'sox' + if torchaudio.load == soundfile_backend.load: + return 'soundfile' + raise ValueError('Unknown backend.') diff --git a/torchaudio/common_utils.py b/torchaudio/common_utils.py deleted file mode 100644 index 28b77200a6..0000000000 --- a/torchaudio/common_utils.py +++ /dev/null @@ -1,38 +0,0 @@ -import sys - -PY3 = sys.version_info > (3, 0) -PY34 = sys.version_info >= (3, 4) - - -def _check_module_exists(name: str) -> bool: - r"""Returns if a top-level module with :attr:`name` exists *without** - importing it. This is generally safer than try-catch block around a - `import X`. It avoids third party libraries breaking assumptions of some of - our tests, e.g., setting multiprocessing start method when imported - (see librosa/#747, torchvision/#544). - """ - if not PY3: # Python 2 - import imp - try: - imp.find_module(name) - return True - except ImportError: - return False - elif not PY34: # Python [3, 3.4) - import importlib - loader = importlib.find_loader(name) - return loader is not None - else: # Python >= 3.4 - import importlib - import importlib.util - spec = importlib.util.find_spec(name) - return spec is not None - -IMPORT_NUMPY = _check_module_exists('numpy') -IMPORT_KALDI_IO = _check_module_exists('kaldi_io') -IMPORT_SCIPY = _check_module_exists('scipy') - -# On Py2, importing librosa 0.6.1 triggers a TypeError (if using newest joblib) -# see librosa/librosa#729. -# TODO: allow Py2 when librosa 0.6.2 releases -IMPORT_LIBROSA = _check_module_exists('librosa') and PY3 diff --git a/torchaudio/compliance/kaldi.py b/torchaudio/compliance/kaldi.py index bdf5f407ba..6211b09f2d 100644 --- a/torchaudio/compliance/kaldi.py +++ b/torchaudio/compliance/kaldi.py @@ -272,6 +272,9 @@ def spectrogram(waveform: Tensor, Tensor: A spectrogram identical to what Kaldi would output. The shape is (m, ``padded_window_size // 2 + 1``) where m is calculated in _get_strided """ + device, dtype = waveform.device, waveform.dtype + epsilon = _get_epsilon(device, dtype) + waveform, window_shift, window_size, padded_window_size = _get_waveform_and_window_properties( waveform, channel, sample_frequency, frame_shift, frame_length, round_to_power_of_two, preemphasis_coefficient) @@ -287,7 +290,7 @@ def spectrogram(waveform: Tensor, fft = torch.rfft(strided_input, 1, normalized=False, onesided=True) # Convert the FFT into a power spectrum - power_spectrum = torch.max(fft.pow(2).sum(2), EPSILON).log() # size (m, padded_window_size // 2 + 1) + power_spectrum = torch.max(fft.pow(2).sum(2), epsilon).log() # size (m, padded_window_size // 2 + 1) power_spectrum[:, 0] = signal_log_energy power_spectrum = _subtract_column_mean(power_spectrum, subtract_mean) diff --git a/torchaudio/csrc/register.cpp b/torchaudio/csrc/register.cpp new file mode 100644 index 0000000000..81b1a84c96 --- /dev/null +++ b/torchaudio/csrc/register.cpp @@ -0,0 +1,18 @@ +#ifndef TORCHAUDIO_REGISTER_H +#define TORCHAUDIO_REGISTER_H + +#include + +namespace torchaudio { +namespace { + +static auto registerSignalInfo = + torch::class_("torchaudio", "SignalInfo") + .def(torch::init()) + .def("get_sample_rate", &SignalInfo::getSampleRate) + .def("get_num_channels", &SignalInfo::getNumChannels) + .def("get_num_samples", &SignalInfo::getNumSamples); + +} // namespace +} // namespace torchaudio +#endif diff --git a/torchaudio/csrc/typedefs.cpp b/torchaudio/csrc/typedefs.cpp new file mode 100644 index 0000000000..7b81d665dc --- /dev/null +++ b/torchaudio/csrc/typedefs.cpp @@ -0,0 +1,23 @@ +#include + +namespace torchaudio { +SignalInfo::SignalInfo( + const int64_t sample_rate_, + const int64_t num_channels_, + const int64_t num_samples_) + : sample_rate(sample_rate_), + num_channels(num_channels_), + num_samples(num_samples_){}; + +int64_t SignalInfo::getSampleRate() const { + return sample_rate; +} + +int64_t SignalInfo::getNumChannels() const { + return num_channels; +} + +int64_t SignalInfo::getNumSamples() const { + return num_samples; +} +} // namespace torchaudio diff --git a/torchaudio/csrc/typedefs.h b/torchaudio/csrc/typedefs.h new file mode 100644 index 0000000000..646ed09f3d --- /dev/null +++ b/torchaudio/csrc/typedefs.h @@ -0,0 +1,23 @@ +#ifndef TORCHAUDIO_TYPDEFS_H +#define TORCHAUDIO_TYPDEFS_H + +#include + +namespace torchaudio { +struct SignalInfo : torch::CustomClassHolder { + int64_t sample_rate; + int64_t num_channels; + int64_t num_samples; + + SignalInfo( + const int64_t sample_rate_, + const int64_t num_channels_, + const int64_t num_samples_); + int64_t getSampleRate() const; + int64_t getNumChannels() const; + int64_t getNumSamples() const; +}; + +} // namespace torchaudio + +#endif diff --git a/torchaudio/datasets/__init__.py b/torchaudio/datasets/__init__.py index 1741889029..942f2c83a1 100644 --- a/torchaudio/datasets/__init__.py +++ b/torchaudio/datasets/__init__.py @@ -6,6 +6,7 @@ from .gtzan import GTZAN from .yesno import YESNO from .ljspeech import LJSPEECH +from .cmuarctic import CMUARCTIC __all__ = ( "COMMONVOICE", @@ -15,6 +16,7 @@ "YESNO", "LJSPEECH", "GTZAN", + "CMUARCTIC", "diskcache_iterator", "bg_iterator", ) diff --git a/torchaudio/datasets/cmuarctic.py b/torchaudio/datasets/cmuarctic.py new file mode 100644 index 0000000000..7aa6d541e5 --- /dev/null +++ b/torchaudio/datasets/cmuarctic.py @@ -0,0 +1,150 @@ +import os +from typing import Tuple + +import torchaudio +from torch import Tensor +from torch.utils.data import Dataset +from torchaudio.datasets.utils import ( + download_url, + extract_archive, + unicode_csv_reader, +) + +URL = "aew" +FOLDER_IN_ARCHIVE = "ARCTIC" +_CHECKSUMS = { + "http://festvox.org/cmu_arctic/packed/cmu_us_aew_arctic.tar.bz2": + "4382b116efcc8339c37e01253cb56295", + "http://festvox.org/cmu_arctic/packed/cmu_us_ahw_arctic.tar.bz2": + "b072d6e961e3f36a2473042d097d6da9", + "http://festvox.org/cmu_arctic/packed/cmu_us_aup_arctic.tar.bz2": + "5301c7aee8919d2abd632e2667adfa7f", + "http://festvox.org/cmu_arctic/packed/cmu_us_awb_arctic.tar.bz2": + "280fdff1e9857119d9a2c57b50e12db7", + "http://festvox.org/cmu_arctic/packed/cmu_us_axb_arctic.tar.bz2": + "5e21cb26c6529c533df1d02ccde5a186", + "http://festvox.org/cmu_arctic/packed/cmu_us_bdl_arctic.tar.bz2": + "b2c3e558f656af2e0a65da0ac0c3377a", + "http://festvox.org/cmu_arctic/packed/cmu_us_clb_arctic.tar.bz2": + "3957c503748e3ce17a3b73c1b9861fb0", + "http://festvox.org/cmu_arctic/packed/cmu_us_eey_arctic.tar.bz2": + "59708e932d27664f9eda3e8e6859969b", + "http://festvox.org/cmu_arctic/packed/cmu_us_fem_arctic.tar.bz2": + "dba4f992ff023347c07c304bf72f4c73", + "http://festvox.org/cmu_arctic/packed/cmu_us_gka_arctic.tar.bz2": + "24a876ea7335c1b0ff21460e1241340f", + "http://festvox.org/cmu_arctic/packed/cmu_us_jmk_arctic.tar.bz2": + "afb69d95f02350537e8a28df5ab6004b", + "http://festvox.org/cmu_arctic/packed/cmu_us_ksp_arctic.tar.bz2": + "4ce5b3b91a0a54b6b685b1b05aa0b3be", + "http://festvox.org/cmu_arctic/packed/cmu_us_ljm_arctic.tar.bz2": + "6f45a3b2c86a4ed0465b353be291f77d", + "http://festvox.org/cmu_arctic/packed/cmu_us_lnh_arctic.tar.bz2": + "c6a15abad5c14d27f4ee856502f0232f", + "http://festvox.org/cmu_arctic/packed/cmu_us_rms_arctic.tar.bz2": + "71072c983df1e590d9e9519e2a621f6e", + "http://festvox.org/cmu_arctic/packed/cmu_us_rxr_arctic.tar.bz2": + "3771ff03a2f5b5c3b53aa0a68b9ad0d5", + "http://festvox.org/cmu_arctic/packed/cmu_us_slp_arctic.tar.bz2": + "9cbf984a832ea01b5058ba9a96862850", + "http://festvox.org/cmu_arctic/packed/cmu_us_slt_arctic.tar.bz2": + "959eecb2cbbc4ac304c6b92269380c81", +} + + +def load_cmuarctic_item(line: str, + path: str, + folder_audio: str, + ext_audio: str) -> Tuple[Tensor, int, str, str]: + + utterance_id, utterance = line[0].strip().split(" ", 2)[1:] + + # Remove space, double quote, and single parenthesis from utterance + utterance = utterance[1:-3] + + file_audio = os.path.join(path, folder_audio, utterance_id + ext_audio) + + # Load audio + waveform, sample_rate = torchaudio.load(file_audio) + + return ( + waveform, + sample_rate, + utterance, + utterance_id.split("_")[1] + ) + + +class CMUARCTIC(Dataset): + """ + Create a Dataset for CMU_arctic. Each item is a tuple of the form: + waveform, sample_rate, utterance, utterance_id + """ + + _file_text = "txt.done.data" + _folder_text = "etc" + _ext_audio = ".wav" + _folder_audio = "wav" + + def __init__(self, + root: str, + url: str = URL, + folder_in_archive: str = FOLDER_IN_ARCHIVE, + download: bool = False) -> None: + + if url in [ + "aew", + "ahw", + "aup", + "awb", + "axb", + "bdl", + "clb", + "eey", + "fem", + "gka", + "jmk", + "ksp", + "ljm", + "lnh", + "rms", + "rxr", + "slp", + "slt" + ]: + + url = "cmu_us_" + url + "_arctic" + ext_archive = ".tar.bz2" + base_url = "http://www.festvox.org/cmu_arctic/packed/" + + url = os.path.join(base_url, url + ext_archive) + + basename = os.path.basename(url) + root = os.path.join(root, folder_in_archive) + if not os.path.isdir(root): + os.mkdir(root) + archive = os.path.join(root, basename) + + basename = basename.split(".")[0] + + self._path = os.path.join(root, basename) + + if download: + if not os.path.isdir(self._path): + if not os.path.isfile(archive): + checksum = _CHECKSUMS.get(url, None) + download_url(url, root, hash_value=checksum, hash_type="md5") + extract_archive(archive) + + self._text = os.path.join(self._path, self._folder_text, self._file_text) + + with open(self._text, "r") as text: + walker = unicode_csv_reader(text, delimiter="\n") + self._walker = list(walker) + + def __getitem__(self, n: int) -> Tuple[Tensor, int, str, str]: + line = self._walker[n] + return load_cmuarctic_item(line, self._path, self._folder_audio, self._ext_audio) + + def __len__(self) -> int: + return len(self._walker) diff --git a/torchaudio/extension/__init__.py b/torchaudio/extension/__init__.py new file mode 100644 index 0000000000..d9b6c76fac --- /dev/null +++ b/torchaudio/extension/__init__.py @@ -0,0 +1,7 @@ +from .extension import ( + _init_extension, +) + +_init_extension() + +del _init_extension diff --git a/torchaudio/extension/extension.py b/torchaudio/extension/extension.py new file mode 100644 index 0000000000..4a2ab82124 --- /dev/null +++ b/torchaudio/extension/extension.py @@ -0,0 +1,49 @@ +import warnings +import importlib +from collections import namedtuple + +import torch +from torchaudio._internal import module_utils as _mod_utils + + +def _init_extension(): + ext = 'torchaudio._torchaudio' + if _mod_utils.is_module_available(ext): + _init_script_module(ext) + else: + warnings.warn('torchaudio C++ extension is not available.') + _init_dummy_module() + + +def _init_script_module(module): + path = importlib.util.find_spec(module).origin + torch.classes.load_library(path) + torch.ops.load_library(path) + + +def _init_dummy_module(): + class SignalInfo: + """Data class for audio format information + + Used when torchaudio C++ extension is not available for annotating + sox_io backend functions so that torchaudio is still importable + without extension. + This class has to implement the same interface as C++ equivalent. + """ + def __init__(self, sample_rate: int, num_channels: int, num_samples: int): + self.sample_rate = sample_rate + self.num_channels = num_channels + self.num_samples = num_samples + + def get_sample_rate(self): + return self.sample_rate + + def get_num_channels(self): + return self.num_channels + + def get_num_samples(self): + return self.num_samples + + DummyModule = namedtuple('torchaudio', ['SignalInfo']) + module = DummyModule(SignalInfo) + setattr(torch.classes, 'torchaudio', module) diff --git a/torchaudio/functional.py b/torchaudio/functional.py index 92580e1d9e..28cb6a3fa2 100644 --- a/torchaudio/functional.py +++ b/torchaudio/functional.py @@ -265,7 +265,7 @@ def griffinlim( angles = rebuilt if momentum: angles = angles - tprev.mul_(momentum / (1 + momentum)) - angles = angles.div_(complex_norm(angles).add_(1e-16).unsqueeze(-1).expand_as(angles)) + angles = angles.div(complex_norm(angles).add(1e-16).unsqueeze(-1).expand_as(angles)) # Return the final phase estimates waveform = istft(specgram * angles, @@ -1317,7 +1317,6 @@ def phaser( delay_buf = torch.zeros(waveform.shape[0], delay_buf_len, dtype=dtype, device=device) mod_buf_len = int(sample_rate / mod_speed + .5) - mod_buf = torch.zeros(mod_buf_len, dtype=dtype, device=device) if sinusoidal: wave_type = 'SINE' @@ -1329,7 +1328,8 @@ def phaser( table_size=mod_buf_len, min=1., max=float(delay_buf_len), - phase=math.pi / 2) + phase=math.pi / 2, + device=device) delay_pos = 0 mod_pos = 0 @@ -1353,7 +1353,8 @@ def _generate_wave_table( table_size: int, min: float, max: float, - phase: float + phase: float, + device: torch.device ) -> Tensor: r"""A helper fucntion for phaser. Generates a table with given parameters @@ -1364,24 +1365,24 @@ def _generate_wave_table( min (float): desired min value max (float): desired max value phase (float): desired phase - + device (torch.device): Torch device on which table must be generated Returns: Tensor: A 1D tensor with wave table values """ phase_offset = int(phase / math.pi / 2 * table_size + 0.5) - t = torch.arange(table_size).to(torch.int32) + t = torch.arange(table_size, device=device, dtype=torch.int32) point = (t + phase_offset) % table_size - d = torch.zeros_like(point).to(torch.float64) + d = torch.zeros_like(point, device=device, dtype=torch.float64) if wave_type == 'SINE': d = (torch.sin(point.to(torch.float64) / table_size * 2 * math.pi) + 1) / 2 elif wave_type == 'TRIANGLE': d = point.to(torch.float64) * 2 / table_size - value = 4 * point / table_size + value = 4 * point // table_size d[value == 0] = d[value == 0] + 0.5 d[value == 1] = 1.5 - d[value == 1] d[value == 2] = 1.5 - d[value == 2] @@ -1487,8 +1488,6 @@ def flanger( lfo_length = int(sample_rate / speed) - lfo = torch.zeros(lfo_length, dtype=dtype, device=device) - table_min = math.floor(delay_min * sample_rate + 0.5) table_max = delay_buf_length - 2. @@ -1497,13 +1496,14 @@ def flanger( table_size=lfo_length, min=float(table_min), max=float(table_max), - phase=3 * math.pi / 2) + phase=3 * math.pi / 2, + device=device) output_waveform = torch.zeros_like(waveform, dtype=dtype, device=device) delay_buf_pos = 0 lfo_pos = 0 - channel_idxs = torch.arange(0, n_channels) + channel_idxs = torch.arange(0, n_channels, device=device) for i in range(waveform.shape[-1]): diff --git a/torchaudio/kaldi_io.py b/torchaudio/kaldi_io.py index d32aaed357..7f14f48e2c 100644 --- a/torchaudio/kaldi_io.py +++ b/torchaudio/kaldi_io.py @@ -1,16 +1,14 @@ # To use this file, the dependency (https://github.com/vesis84/kaldi-io-for-python) # needs to be installed. This is a light wrapper around kaldi_io that returns # torch.Tensors. -from typing import Any, Callable, Iterable, Tuple, Union +from typing import Any, Callable, Iterable, Tuple import torch from torch import Tensor -from torchaudio.common_utils import IMPORT_KALDI_IO, IMPORT_NUMPY +from torchaudio._internal import module_utils as _mod_utils -if IMPORT_NUMPY: +if _mod_utils.is_module_available('kaldi_io', 'numpy'): import numpy as np - -if IMPORT_KALDI_IO: import kaldi_io @@ -38,15 +36,13 @@ def _convert_method_output_to_tensor(file_or_fd: Any, Returns: Iterable[Tuple[str, Tensor]]: The string is the key and the tensor is vec/mat """ - if not IMPORT_KALDI_IO: - raise ImportError('Could not import kaldi_io. Did you install it?') - for key, np_arr in fn(file_or_fd): if convert_contiguous: np_arr = np.ascontiguousarray(np_arr) yield key, torch.from_numpy(np_arr) +@_mod_utils.requires_module('kaldi_io', 'numpy') def read_vec_int_ark(file_or_fd: Any) -> Iterable[Tuple[str, Tensor]]: r"""Create generator of (key,vector) tuples, which reads from the ark file/stream. @@ -66,6 +62,7 @@ def read_vec_int_ark(file_or_fd: Any) -> Iterable[Tuple[str, Tensor]]: return _convert_method_output_to_tensor(file_or_fd, kaldi_io.read_vec_int_ark, convert_contiguous=True) +@_mod_utils.requires_module('kaldi_io', 'numpy') def read_vec_flt_scp(file_or_fd: Any) -> Iterable[Tuple[str, Tensor]]: r"""Create generator of (key,vector) tuples, read according to Kaldi scp. @@ -82,6 +79,7 @@ def read_vec_flt_scp(file_or_fd: Any) -> Iterable[Tuple[str, Tensor]]: return _convert_method_output_to_tensor(file_or_fd, kaldi_io.read_vec_flt_scp) +@_mod_utils.requires_module('kaldi_io', 'numpy') def read_vec_flt_ark(file_or_fd: Any) -> Iterable[Tuple[str, Tensor]]: r"""Create generator of (key,vector) tuples, which reads from the ark file/stream. @@ -98,6 +96,7 @@ def read_vec_flt_ark(file_or_fd: Any) -> Iterable[Tuple[str, Tensor]]: return _convert_method_output_to_tensor(file_or_fd, kaldi_io.read_vec_flt_ark) +@_mod_utils.requires_module('kaldi_io', 'numpy') def read_mat_scp(file_or_fd: Any) -> Iterable[Tuple[str, Tensor]]: r"""Create generator of (key,matrix) tuples, read according to Kaldi scp. @@ -114,6 +113,7 @@ def read_mat_scp(file_or_fd: Any) -> Iterable[Tuple[str, Tensor]]: return _convert_method_output_to_tensor(file_or_fd, kaldi_io.read_mat_scp) +@_mod_utils.requires_module('kaldi_io', 'numpy') def read_mat_ark(file_or_fd: Any) -> Iterable[Tuple[str, Tensor]]: r"""Create generator of (key,matrix) tuples, which reads from the ark file/stream. diff --git a/torchaudio/models/__init__.py b/torchaudio/models/__init__.py index 1abdac6271..20c1bdf265 100644 --- a/torchaudio/models/__init__.py +++ b/torchaudio/models/__init__.py @@ -1 +1,2 @@ from .wav2letter import * +from ._wavernn import * diff --git a/torchaudio/models/_wavernn.py b/torchaudio/models/_wavernn.py new file mode 100644 index 0000000000..04155fb87c --- /dev/null +++ b/torchaudio/models/_wavernn.py @@ -0,0 +1,105 @@ +from torch import Tensor +from torch import nn + +__all__ = ["_ResBlock", "_MelResNet"] + + +class _ResBlock(nn.Module): + r"""This is a ResNet block layer. This layer is based on the paper "Deep Residual Learning + for Image Recognition". Kaiming He, Xiangyu Zhang, Shaoqing Ren, Jian Sun. CVPR, 2016. + It is a block used in WaveRNN. WaveRNN is based on the paper "Efficient Neural Audio Synthesis". + Nal Kalchbrenner, Erich Elsen, Karen Simonyan, Seb Noury, Norman Casagrande, Edward Lockhart, + Florian Stimberg, Aaron van den Oord, Sander Dieleman, Koray Kavukcuoglu. arXiv:1802.08435, 2018. + + Args: + num_dims: the number of compute dimensions in the input (default=128). + + Examples:: + >>> resblock = _ResBlock(num_dims=128) + >>> input = torch.rand(10, 128, 512) + >>> output = resblock(input) + """ + + def __init__(self, num_dims: int = 128) -> None: + super().__init__() + + self.resblock_model = nn.Sequential( + nn.Conv1d(in_channels=num_dims, out_channels=num_dims, kernel_size=1, bias=False), + nn.BatchNorm1d(num_dims), + nn.ReLU(inplace=True), + nn.Conv1d(in_channels=num_dims, out_channels=num_dims, kernel_size=1, bias=False), + nn.BatchNorm1d(num_dims) + ) + + def forward(self, x: Tensor) -> Tensor: + r"""Pass the input through the _ResBlock layer. + + Args: + x: the input sequence to the _ResBlock layer (required). + + Shape: + - x: :math:`(N, S, T)`. + - output: :math:`(N, S, T)`. + where N is the batch size, S is the number of input sequence, + T is the length of input sequence. + """ + + residual = x + return self.resblock_model(x) + residual + + +class _MelResNet(nn.Module): + r"""This is a MelResNet layer based on a stack of ResBlocks. It is a block used in WaveRNN. + WaveRNN is based on the paper "Efficient Neural Audio Synthesis". Nal Kalchbrenner, Erich Elsen, + Karen Simonyan, Seb Noury, Norman Casagrande, Edward Lockhart, Florian Stimberg, Aaron van den Oord, + Sander Dieleman, Koray Kavukcuoglu. arXiv:1802.08435, 2018. + + Args: + res_blocks: the number of ResBlock in stack (default=10). + input_dims: the number of input sequence (default=100). + hidden_dims: the number of compute dimensions (default=128). + output_dims: the number of output sequence (default=128). + pad: the number of kernal size (pad * 2 + 1) in the first Conv1d layer (default=2). + + Examples:: + >>> melresnet = _MelResNet(res_blocks=10, input_dims=100, + hidden_dims=128, output_dims=128, pad=2) + >>> input = torch.rand(10, 100, 512) + >>> output = melresnet(input) + """ + + def __init__(self, res_blocks: int = 10, + input_dims: int = 100, + hidden_dims: int = 128, + output_dims: int = 128, + pad: int = 2) -> None: + super().__init__() + + kernel_size = pad * 2 + 1 + ResBlocks = [] + + for i in range(res_blocks): + ResBlocks.append(_ResBlock(hidden_dims)) + + self.melresnet_model = nn.Sequential( + nn.Conv1d(in_channels=input_dims, out_channels=hidden_dims, kernel_size=kernel_size, bias=False), + nn.BatchNorm1d(hidden_dims), + nn.ReLU(inplace=True), + *ResBlocks, + nn.Conv1d(in_channels=hidden_dims, out_channels=output_dims, kernel_size=1) + ) + + def forward(self, x: Tensor) -> Tensor: + r"""Pass the input through the _MelResNet layer. + + Args: + x: the input sequence to the _MelResNet layer (required). + + Shape: + - x: :math:`(N, S, T)`. + - output: :math:`(N, P, T - 2 * pad)`. + where N is the batch size, S is the number of input sequence, + P is the number of output sequence, T is the length of input sequence. + """ + + return self.melresnet_model(x) diff --git a/torchaudio/sox_effects/__init__.py b/torchaudio/sox_effects/__init__.py new file mode 100644 index 0000000000..115b70c895 --- /dev/null +++ b/torchaudio/sox_effects/__init__.py @@ -0,0 +1,12 @@ +from torchaudio._internal import module_utils as _mod_utils +from .sox_effects import ( + init_sox_effects, + shutdown_sox_effects, + effect_names, + SoxEffect, + SoxEffectsChain, +) + + +if _mod_utils.is_module_available('torchaudio._torchaudio'): + init_sox_effects() diff --git a/torchaudio/sox_effects.py b/torchaudio/sox_effects/sox_effects.py similarity index 71% rename from torchaudio/sox_effects.py rename to torchaudio/sox_effects/sox_effects.py index d1eb04e53f..6a6b5be0a5 100644 --- a/torchaudio/sox_effects.py +++ b/torchaudio/sox_effects/sox_effects.py @@ -1,12 +1,85 @@ +import atexit from typing import Any, Callable, List, Optional, Tuple, Union import torch -import torchaudio from torch import Tensor -from torchaudio._backend import _audio_backend_guard +from torchaudio._internal import ( + module_utils as _mod_utils, + misc_ops as _misc_ops, +) -@_audio_backend_guard("sox") +if _mod_utils.is_module_available('torchaudio._torchaudio'): + from torchaudio import _torchaudio + + +_SOX_INITIALIZED: Optional[bool] = False +# This variable has a micro lifecycle. (False -> True -> None) +# False: Not initialized +# True: Initialized +# None: Already shut down (should not be initialized again.) + +_SOX_SUCCESS_CODE = 0 +# defined at +# https://fossies.org/dox/sox-14.4.2/sox_8h.html#a8e07e80cebeff3339265d89c387cea93a9ef2b87ec303edfe40751d9a85fadeeb + + +@_mod_utils.requires_module('torchaudio._torchaudio') +def init_sox_effects() -> int: + """Initialize resources required to use ``SoxEffectsChain`` + + You do not need to call this function manually. It is called automatically. + + Once initialized, you do not need to call this function again across the multiple call of + ``SoxEffectsChain.sox_build_flow_effects``, though it is safe to do so as long as + ``shutdown_sox_effects`` is not called yet. + Once ``shutdown_sox_effects`` is called, you can no longer use SoX effects and calling + this function results in `RuntimeError`. + + Note: + This function is not required for simple loading. + + Returns: + int: Code corresponding to sox_error_t enum. See + https://fossies.org/dox/sox-14.4.2/sox_8h.html#a8e07e80cebeff3339265d89c387cea93 + """ + global _SOX_INITIALIZED + if _SOX_INITIALIZED is None: + raise RuntimeError('SoX effects chain has been already shut down. Can not initialize again.') + if not _SOX_INITIALIZED: + code = _torchaudio.initialize_sox() + if code == _SOX_SUCCESS_CODE: + _SOX_INITIALIZED = True + atexit.register(shutdown_sox_effects) + return code + return _SOX_SUCCESS_CODE + + +@_mod_utils.requires_module("torchaudio._torchaudio") +def shutdown_sox_effects() -> int: + """Clean up resources required to use ``SoxEffectsChain`` + + You do not need to call this function manually. It is called automatically. + + It is safe to call this function multiple times. + Once ``shutdown_sox_effects`` is called, you can no longer use SoX effects and calling + this function results in `RuntimeError`. + + + Returns: + int: Code corresponding to sox_error_t enum. See + https://fossies.org/dox/sox-14.4.2/sox_8h.html#a8e07e80cebeff3339265d89c387cea93 + """ + global _SOX_INITIALIZED + if _SOX_INITIALIZED: + code = _torchaudio.shutdown_sox() + if code == _SOX_INITIALIZED: + _SOX_INITIALIZED = None + return code + return _SOX_SUCCESS_CODE + + +@_mod_utils.requires_module('torchaudio._torchaudio') def effect_names() -> List[str]: """Gets list of valid sox effect names @@ -15,12 +88,10 @@ def effect_names() -> List[str]: Example >>> EFFECT_NAMES = torchaudio.sox_effects.effect_names() """ - - from . import _torchaudio return _torchaudio.get_effect_names() -@_audio_backend_guard("sox") +@_mod_utils.requires_module('torchaudio._torchaudio') def SoxEffect(): r"""Create an object for passing sox effect information between python and c++ @@ -28,8 +99,6 @@ def SoxEffect(): SoxEffect: An object with the following attributes: ename (str) which is the name of effect, and eopts (List[str]) which is a list of effect options. """ - - from . import _torchaudio return _torchaudio.SoxEffect() @@ -123,7 +192,7 @@ def append_effect_to_chain(self, e.eopts = eargs self.chain.append(e) - @_audio_backend_guard("sox") + @_mod_utils.requires_module('torchaudio._torchaudio') def sox_build_flow_effects(self, out: Optional[Tensor] = None) -> Tuple[Tensor, int]: r"""Build effects chain and flow effects from input file to output tensor @@ -138,7 +207,7 @@ def sox_build_flow_effects(self, """ # initialize output tensor if out is not None: - torchaudio.check_input(out) + _misc_ops.check_input(out) else: out = torch.FloatTensor() if not len(self.chain): @@ -149,8 +218,6 @@ def sox_build_flow_effects(self, # print("effect options:", [x.eopts for x in self.chain]) - torchaudio.initialize_sox() - from . import _torchaudio sr = _torchaudio.build_flow_effects(self.input_file, out, self.channels_first, @@ -160,7 +227,7 @@ def sox_build_flow_effects(self, self.chain, self.MAX_EFFECT_OPTS) - torchaudio._audio_normalization(out, self.normalization) + _misc_ops.normalize_audio(out, self.normalization) return out, sr From 36414bcc0d3b6bb575d0b5dda21735ed98317610 Mon Sep 17 00:00:00 2001 From: Moto Hira Date: Fri, 17 Jul 2020 09:28:17 -0700 Subject: [PATCH 10/73] Import torchaudio 20200714 #782 (#784) Summary: Pull Request resolved: https://github.com/pytorch/audio/pull/784 - Import torchaudio. - Change test util module name from test_case_utils to case_utils Reviewed By: cpuhrsch Differential Revision: D22261638 fbshipit-source-id: eb4df500c1d7db0a60baa100dd22795a63851438 --- README.md | 4 +- .../setup_helpers/build_third_party.sh | 50 --- .../setup_helpers/build_third_party_helper.sh | 217 ----------- build_tools/setup_helpers/extension.py | 36 +- packaging/build_conda.sh | 2 +- packaging/build_wheel.sh | 2 +- packaging/pkg_helpers.bash | 3 +- setup.py | 2 +- test/README.md | 52 +++ .../tt/clips/common_voice_tt_00000000.mp3 | Bin 57136 -> 0 bytes .../tt/clips/common_voice_tt_00000000.wav | Bin 0 -> 80700 bytes .../cv-corpus-4-2019-12-10/tt/train.tsv | 4 +- test/assets/dtmf_30s_stereo.mp3 | Bin 228984 -> 0 bytes test/assets/io/96k_0_1ch.opus | Bin 0 -> 8259 bytes test/assets/io/96k_0_2ch.opus | Bin 0 -> 6740 bytes test/assets/io/96k_10_1ch.opus | Bin 0 -> 15033 bytes test/assets/io/96k_10_2ch.opus | Bin 0 -> 15160 bytes test/assets/io/96k_5_1ch.opus | Bin 0 -> 13074 bytes test/assets/io/96k_5_2ch.opus | Bin 0 -> 10618 bytes test/assets/io/generate_opus.py | 50 +++ test/common_utils.py | 171 --------- test/common_utils/__init__.py | 31 ++ test/common_utils/backend_utils.py | 41 ++ test/common_utils/case_utils.py | 75 ++++ test/common_utils/data_utils.py | 94 +++++ test/common_utils/parameterized_utils.py | 10 + test/common_utils/sox_utils.py | 79 ++++ test/common_utils/wav_utils.py | 86 +++++ test/functional_cpu_test.py | 35 +- test/kaldi_compatibility_impl.py | 52 ++- test/sox_io_backend/__init__.py | 0 test/sox_io_backend/common.py | 2 + test/sox_io_backend/test_info.py | 125 +++++++ test/sox_io_backend/test_load.py | 263 +++++++++++++ test/sox_io_backend/test_roundtrip.py | 52 +++ test/sox_io_backend/test_save.py | 304 +++++++++++++++ test/sox_io_backend/test_torchscript.py | 149 ++++++++ test/test_backend.py | 15 +- test/test_datasets.py | 3 +- test/test_io.py | 33 +- test/test_librosa_compatibility.py | 9 +- test/test_models.py | 117 +++++- test/test_sox_compatibility.py | 206 +++++------ test/test_sox_effects.py | 4 +- test/test_transforms.py | 6 +- test/torchscript_consistency_impl.py | 4 +- third_party/CMakeLists.txt | 80 ++++ third_party/build_codec_helper.sh | 13 + third_party/patch/libmad.patch | 86 +++++ torchaudio/backend/sox_io_backend.py | 134 +++++++ torchaudio/backend/utils.py | 6 + torchaudio/csrc/register.cpp | 59 ++- torchaudio/csrc/sox.cpp | 33 -- torchaudio/csrc/sox.h | 7 - torchaudio/csrc/sox_effects.cpp | 54 +++ torchaudio/csrc/sox_effects.h | 18 + torchaudio/csrc/sox_io.cpp | 170 +++++++++ torchaudio/csrc/sox_io.h | 41 ++ torchaudio/csrc/sox_utils.cpp | 245 ++++++++++++ torchaudio/csrc/sox_utils.h | 100 +++++ torchaudio/csrc/typedefs.cpp | 23 -- torchaudio/csrc/typedefs.h | 23 -- torchaudio/extension/extension.py | 29 -- torchaudio/functional.py | 7 +- torchaudio/models/_wavernn.py | 350 ++++++++++++++---- torchaudio/sox_effects/__init__.py | 2 + torchaudio/sox_effects/sox_effects.py | 54 +-- 67 files changed, 3049 insertions(+), 873 deletions(-) delete mode 100755 build_tools/setup_helpers/build_third_party.sh delete mode 100644 build_tools/setup_helpers/build_third_party_helper.sh delete mode 100644 test/assets/CommonVoice/cv-corpus-4-2019-12-10/tt/clips/common_voice_tt_00000000.mp3 create mode 100644 test/assets/CommonVoice/cv-corpus-4-2019-12-10/tt/clips/common_voice_tt_00000000.wav delete mode 100644 test/assets/dtmf_30s_stereo.mp3 create mode 100644 test/assets/io/96k_0_1ch.opus create mode 100644 test/assets/io/96k_0_2ch.opus create mode 100644 test/assets/io/96k_10_1ch.opus create mode 100644 test/assets/io/96k_10_2ch.opus create mode 100644 test/assets/io/96k_5_1ch.opus create mode 100644 test/assets/io/96k_5_2ch.opus create mode 100644 test/assets/io/generate_opus.py delete mode 100644 test/common_utils.py create mode 100644 test/common_utils/__init__.py create mode 100644 test/common_utils/backend_utils.py create mode 100644 test/common_utils/case_utils.py create mode 100644 test/common_utils/data_utils.py create mode 100644 test/common_utils/parameterized_utils.py create mode 100644 test/common_utils/sox_utils.py create mode 100644 test/common_utils/wav_utils.py create mode 100644 test/sox_io_backend/__init__.py create mode 100644 test/sox_io_backend/common.py create mode 100644 test/sox_io_backend/test_info.py create mode 100644 test/sox_io_backend/test_load.py create mode 100644 test/sox_io_backend/test_roundtrip.py create mode 100644 test/sox_io_backend/test_save.py create mode 100644 test/sox_io_backend/test_torchscript.py create mode 100644 third_party/CMakeLists.txt create mode 100755 third_party/build_codec_helper.sh create mode 100644 third_party/patch/libmad.patch create mode 100644 torchaudio/backend/sox_io_backend.py create mode 100644 torchaudio/csrc/sox_effects.cpp create mode 100644 torchaudio/csrc/sox_effects.h create mode 100644 torchaudio/csrc/sox_io.cpp create mode 100644 torchaudio/csrc/sox_io.h create mode 100644 torchaudio/csrc/sox_utils.cpp create mode 100644 torchaudio/csrc/sox_utils.h delete mode 100644 torchaudio/csrc/typedefs.cpp delete mode 100644 torchaudio/csrc/typedefs.h diff --git a/README.md b/README.md index 94f993ddaa..290bb73543 100644 --- a/README.md +++ b/README.md @@ -113,8 +113,8 @@ python setup.py install MACOSX_DEPLOYMENT_TARGET=10.9 CC=clang CXX=clang++ python setup.py install ``` -Alternatively, the build process can build SoX (and codecs such as libmad, lame and flac) statically and torchaudio can link them, by setting environment variable `BUILD_SOX=1`. -The build process will fetch and build SoX, liblame, libmad, flac before building extension. +Alternatively, the build process can build libsox and some optional codecs statically and torchaudio can link them, by setting environment variable `BUILD_SOX=1`. +The build process will fetch and build libmad, lame, flac, vorbis, opus, and libsox before building extension. This process requires `cmake` and `pkg-config`. ```bash # Linux diff --git a/build_tools/setup_helpers/build_third_party.sh b/build_tools/setup_helpers/build_third_party.sh deleted file mode 100755 index 9577776cc9..0000000000 --- a/build_tools/setup_helpers/build_third_party.sh +++ /dev/null @@ -1,50 +0,0 @@ -#!/bin/bash -# Build third party libraries (SoX, lame, libmad, and flac) -# Usage: ./build_thid_parth.sh [prefix] [download_only?=false] - -set -e - -this_dir="$( cd "$( dirname "${BASH_SOURCE[0]}" )" >/dev/null 2>&1 && pwd )" -root_dir="${this_dir}/../.." - -prefix="${1:-}" -if [ -z "${prefix}" ]; then - prefix="${root_dir}" -fi -download_only="${2:-false}" - -tp_dir="${prefix}/third_party" -tmp_dir="${tp_dir}/tmp" -build_dir="${tp_dir}/build" - -mkdir -p "${tmp_dir}" "${build_dir}" - -. "${this_dir}/build_third_party_helper.sh" - -if ! found_lame "${build_dir}" ; then - get_lame "${tmp_dir}" - if [ "${download_only}" = "false" ]; then - build_lame "${tmp_dir}" "${build_dir}" - fi -fi - -if ! found_flac "${build_dir}" ; then - get_flac "${tmp_dir}" - if [ "${download_only}" = "false" ]; then - build_flac "${tmp_dir}" "${build_dir}" - fi -fi - -if ! found_mad "${build_dir}" ; then - get_mad "${tmp_dir}" - if [ "${download_only}" = "false" ]; then - build_mad "${tmp_dir}" "${build_dir}" - fi -fi - -if ! found_sox "${build_dir}" ; then - get_sox "${tmp_dir}" - if [ "${download_only}" = "false" ]; then - build_sox "${tmp_dir}" "${build_dir}" - fi -fi diff --git a/build_tools/setup_helpers/build_third_party_helper.sh b/build_tools/setup_helpers/build_third_party_helper.sh deleted file mode 100644 index 7cca812409..0000000000 --- a/build_tools/setup_helpers/build_third_party_helper.sh +++ /dev/null @@ -1,217 +0,0 @@ -#!/usr/bin/env bash - -set -euo pipefail - -# Global options -CURL_OPTS="-L --retry 10 --connect-timeout 5 --max-time 180" -MAKE_OPTS="-j" -CONFIG_OPTS="" - -if [ -z ${DEBUG+x} ]; then - CURL_OPTS="${CURL_OPTS} --silent --show-error" - MAKE_OPTS="${MAKE_OPTS} --quiet" - CONFIG_OPTS="${CONFIG_OPTS} --quiet" -fi - -all_found() { - dir="$1" - shift - while [ "$#" -gt 0 ]; do - if [ ! -f "${dir}/$1" ]; then - return 1 - fi - shift - done -} - - -found_lame() { - all_found "$1" 'include/lame/lame.h' 'lib/libmp3lame.a' -} - -found_flac() { - all_found "$1" \ - 'include/FLAC/format.h' \ - 'include/FLAC/stream_decoder.h' \ - 'include/FLAC/export.h' \ - 'include/FLAC/ordinals.h' \ - 'include/FLAC/all.h' \ - 'include/FLAC/assert.h' \ - 'include/FLAC/callback.h' \ - 'include/FLAC/metadata.h' \ - 'include/FLAC/stream_encoder.h' \ - 'include/FLAC++/export.h' \ - 'include/FLAC++/decoder.h' \ - 'include/FLAC++/all.h' \ - 'include/FLAC++/metadata.h' \ - 'include/FLAC++/encoder.h' \ - 'lib/libFLAC++.a' \ - 'lib/libFLAC.a' -} - -found_mad() { - all_found "$1" 'include/mad.h' 'lib/libmad.a' -} - -found_sox() { - all_found "$1" 'include/sox.h' 'lib/libsox.a' -} - -LAME="lame-3.99.5" -LAME_ARCHIVE="${LAME}.tar.gz" - -get_lame() { - work_dir="$1" - url="https://downloads.sourceforge.net/project/lame/lame/3.99/${LAME_ARCHIVE}" - ( - cd "${work_dir}" - if [ ! -d "${LAME}" ]; then - if [ ! -f "${LAME_ARCHIVE}" ]; then - printf "Fetching liblame from %s\n" "${url}" - curl $CURL_OPTS -O "${url}" - fi - fi - ) -} - -build_lame() { - work_dir="$1" - install_dir="$2" - ( - cd "${work_dir}" - if [ ! -d "${LAME}" ]; then - tar xfp "${LAME_ARCHIVE}" - fi - cd "${LAME}" - # build statically - printf "Building liblame\n" - if [ ! -f Makefile ]; then - ./configure ${CONFIG_OPTS} \ - --disable-shared --enable-static --prefix="${install_dir}" CFLAGS=-fPIC CXXFLAGS=-fPIC \ - --with-pic --disable-debug --disable-dependency-tracking --enable-nasm - fi - make ${MAKE_OPTS} > make.log 2>&1 - make ${MAKE_OPTS} install - ) -} - -FLAC="flac-1.3.2" -FLAC_ARCHIVE="${FLAC}.tar.xz" - -get_flac() { - work_dir="$1" - url="https://downloads.sourceforge.net/project/flac/flac-src/${FLAC_ARCHIVE}" - ( - cd "${work_dir}" - if [ ! -d "${FLAC}" ]; then - if [ ! -f "${FLAC_ARCHIVE}" ]; then - printf "Fetching flac from %s\n" "${url}" - curl $CURL_OPTS -O "${url}" - fi - fi - ) -} - -build_flac() { - work_dir="$1" - install_dir="$2" - ( - cd "${work_dir}" - if [ ! -d "${FLAC}" ]; then - tar xfp "${FLAC_ARCHIVE}" - fi - cd "${FLAC}" - # build statically - printf "Building flac\n" - if [ ! -f Makefile ]; then - ./configure ${CONFIG_OPTS} \ - --disable-shared --enable-static --prefix="${install_dir}" CFLAGS=-fPIC CXXFLAGS=-fPIC \ - --with-pic --disable-debug --disable-dependency-tracking - fi - make ${MAKE_OPTS} > make.log 2>&1 - make ${MAKE_OPTS} install - ) -} - -LIBMAD="libmad-0.15.1b" -LIBMAD_ARCHIVE="${LIBMAD}.tar.gz" - -get_mad() { - work_dir="$1" - url="https://downloads.sourceforge.net/project/mad/libmad/0.15.1b/${LIBMAD_ARCHIVE}" - ( - cd "${work_dir}" - if [ ! -d "${LIBMAD}" ]; then - if [ ! -f "${LIBMAD_ARCHIVE}" ]; then - printf "Fetching mad from %s\n" "${url}" - curl $CURL_OPTS -O "${url}" - fi - fi - ) -} - -build_mad() { - work_dir="$1" - install_dir="$2" - ( - cd "${work_dir}" - if [ ! -d "${LIBMAD}" ]; then - tar xfp "${LIBMAD_ARCHIVE}" - fi - cd "${LIBMAD}" - # build statically - printf "Building mad\n" - if [ ! -f Makefile ]; then - # See https://stackoverflow.com/a/12864879/23845 - sed -i.bak 's/-march=i486//' configure - ./configure ${CONFIG_OPTS} \ - --disable-shared --enable-static --prefix="${install_dir}" CFLAGS=-fPIC CXXFLAGS=-fPIC \ - --with-pic --disable-debug --disable-dependency-tracking - fi - make ${MAKE_OPTS} > make.log 2>&1 - make ${MAKE_OPTS} install - ) -} - -SOX="sox-14.4.2" -SOX_ARCHIVE="${SOX}.tar.bz2" - -get_sox() { - work_dir="$1" - url="https://downloads.sourceforge.net/project/sox/sox/14.4.2/${SOX_ARCHIVE}" - ( - cd "${work_dir}" - if [ ! -d "${SOX}" ]; then - if [ ! -f "${SOX_ARCHIVE}" ]; then - printf "Fetching SoX from %s\n" "${url}" - curl $CURL_OPTS -O "${url}" - fi - fi - ) -} - -build_sox() { - work_dir="$1" - install_dir="$2" - ( - cd "${work_dir}" - if [ ! -d "${SOX}" ]; then - tar xfp "${SOX_ARCHIVE}" - fi - cd "${SOX}" - # build statically - printf "Building SoX\n" - if [ ! -f Makefile ]; then - # --without-png makes OS X build less hazardous; somehow the build - # finds png and enables it. We don't want it; we'd need to package - # it statically if we do. - ./configure ${CONFIG_OPTS} --disable-shared --enable-static --prefix="${install_dir}" \ - LDFLAGS="-L${install_dir}/lib" CPPFLAGS="-I${install_dir}/include" \ - --with-lame --with-flac --with-mad --without-alsa --without-coreaudio \ - --without-png --without-oggvorbis --without-oss --without-sndfile \ - CFLAGS=-fPIC CXXFLAGS=-fPIC --with-pic --disable-debug --disable-dependency-tracking - fi - make ${MAKE_OPTS} > make.log 2>&1 - make ${MAKE_OPTS} install - ) -} diff --git a/build_tools/setup_helpers/extension.py b/build_tools/setup_helpers/extension.py index dcf61ab259..b9fb30e114 100644 --- a/build_tools/setup_helpers/extension.py +++ b/build_tools/setup_helpers/extension.py @@ -17,7 +17,7 @@ _ROOT_DIR = _THIS_DIR.parent.parent.resolve() _CSRC_DIR = _ROOT_DIR / 'torchaudio' / 'csrc' _TP_BASE_DIR = _ROOT_DIR / 'third_party' -_TP_INSTALL_DIR = _TP_BASE_DIR / 'build' +_TP_INSTALL_DIR = _TP_BASE_DIR / 'install' def _get_build_sox(): @@ -76,8 +76,20 @@ def _get_extra_objects(): # NOTE: The order of the library listed bellow matters. # # (the most important thing is that dependencies come after a library - # e.g., sox comes first) - libs = ['libsox.a', 'libmad.a', 'libFLAC.a', 'libmp3lame.a'] + # e.g., sox comes first, flac/vorbis comes before ogg, and + # vorbisenc/vorbisfile comes before vorbis + libs = [ + 'libsox.a', + 'libmad.a', + 'libFLAC.a', + 'libmp3lame.a', + 'libopusfile.a', + 'libopus.a', + 'libvorbisenc.a', + 'libvorbisfile.a', + 'libvorbis.a', + 'libogg.a', + ] for lib in libs: objs.append(str(_TP_INSTALL_DIR / 'lib' / lib)) return objs @@ -87,15 +99,19 @@ def _get_libraries(): return [] if _BUILD_SOX else ['sox'] -def _build_codecs(): +def _build_third_party(): + build_dir = str(_TP_BASE_DIR / 'build') + os.makedirs(build_dir, exist_ok=True) subprocess.run( - args=[str(_THIS_DIR / 'build_third_party.sh')], + args=['cmake', '..'], + cwd=build_dir, + check=True, + ) + subprocess.run( + args=['cmake', '--build', '.'], + cwd=build_dir, check=True, ) - - -def _configure_third_party(): - _build_codecs() _EXT_NAME = 'torchaudio._torchaudio' @@ -120,5 +136,5 @@ def get_ext_modules(debug=False): class BuildExtension(TorchBuildExtension): def build_extension(self, ext): if ext.name == _EXT_NAME and _BUILD_SOX: - _configure_third_party() + _build_third_party() super().build_extension(ext) diff --git a/packaging/build_conda.sh b/packaging/build_conda.sh index 3e011d312f..628eaf0bf8 100755 --- a/packaging/build_conda.sh +++ b/packaging/build_conda.sh @@ -6,7 +6,7 @@ script_dir="$( cd "$( dirname "${BASH_SOURCE[0]}" )" >/dev/null 2>&1 && pwd )" export BUILD_TYPE="conda" export NO_CUDA_PACKAGE=1 -setup_env 0.6.0 +setup_env 0.7.0 export SOURCE_ROOT_DIR="$PWD" setup_conda_pytorch_constraint conda build $CONDA_CHANNEL_FLAGS --no-anaconda-upload --python "$PYTHON_VERSION" packaging/torchaudio diff --git a/packaging/build_wheel.sh b/packaging/build_wheel.sh index d08196cb20..3b25c00cd2 100755 --- a/packaging/build_wheel.sh +++ b/packaging/build_wheel.sh @@ -6,7 +6,7 @@ script_dir="$( cd "$( dirname "${BASH_SOURCE[0]}" )" >/dev/null 2>&1 && pwd )" export BUILD_TYPE="wheel" export NO_CUDA_PACKAGE=1 -setup_env 0.6.0 +setup_env 0.7.0 setup_wheel_python pip_install numpy future setup_pip_pytorch_version diff --git a/packaging/pkg_helpers.bash b/packaging/pkg_helpers.bash index 4030128a98..3ec49a0269 100644 --- a/packaging/pkg_helpers.bash +++ b/packaging/pkg_helpers.bash @@ -171,6 +171,7 @@ setup_pip_pytorch_version() { else pip_install "torch==$PYTORCH_VERSION$PYTORCH_VERSION_SUFFIX" \ -f https://download.pytorch.org/whl/torch_stable.html \ + -f https://download.pytorch.org/whl/test/torch_test.html \ -f https://download.pytorch.org/whl/nightly/torch_nightly.html fi } @@ -184,7 +185,7 @@ setup_conda_pytorch_constraint() { export CONDA_CHANNEL_FLAGS="-c pytorch-nightly" export PYTORCH_VERSION="$(conda search --json 'pytorch[channel=pytorch-nightly]' | python -c "import sys, json, re; print(re.sub(r'\\+.*$', '', json.load(sys.stdin)['pytorch'][-1]['version']))")" else - export CONDA_CHANNEL_FLAGS="-c pytorch -c pytorch-nightly" + export CONDA_CHANNEL_FLAGS="-c pytorch -c pytorch-test -c pytorch-nightly" fi if [[ "$CU_VERSION" == cpu ]]; then export CONDA_PYTORCH_BUILD_CONSTRAINT="- pytorch==$PYTORCH_VERSION${PYTORCH_VERSION_SUFFIX}" diff --git a/setup.py b/setup.py index 5cf1ad680a..aab59b4d8a 100644 --- a/setup.py +++ b/setup.py @@ -12,7 +12,7 @@ # Creating the version file -version = '0.6.0a0' +version = '0.7.0a0' sha = 'Unknown' try: diff --git a/test/README.md b/test/README.md index 35a926c120..304bfa9c8e 100644 --- a/test/README.md +++ b/test/README.md @@ -41,6 +41,58 @@ The following test modules are defined for corresponding `torchaudio` module/fun - [assets/kaldi](./assets/kaldi): Contains Kaldi format matrix files used in [./test_compliance_kaldi.py](./test_compliance_kaldi.py). - [compliance](./compliance): Scripts used to generate above Kaldi matrix files. +### Waveforms for Testing Purposes + +When testing transforms we often need waveforms of specific type (ex: pure tone, noise, or voice), with specific bitrate (ex. 8 or 16 kHz) and number of channels (ex. mono, stereo). Below are some tips on how to construct waveforms and guidance around existing audio files. + +#### Load a Waveform from a File + +```python +filepath = common_utils.get_asset_path('filename.wav') +waveform, sample_rate = common_utils.load_wav(filepath) +``` + +*Note: Should you choose to contribute an audio file, please leave a comment in the issue or pull request, mentioning content source and licensing information. WAV files are preferred. Other formats should be used only when there is no alternative. (i.e. dataset implementation comes with hardcoded non-wav extension).* + +#### Pure Tone + +Code: + +```python +waveform = common_utils.get_sinusoid( + frequency=300, + sample_rate=16000, + duration=1, # seconds + n_channels=1, + dtype="float32", + device="cpu", +) +``` + +#### Noise + +Code: + +```python +tensor = common_utils.get_whitenoise() +``` + +Files: + +* `steam-train-whistle-daniel_simon.wav` + +#### Voice + +Files: + +* `CommonVoice/cv-corpus-4-2019-12-10/tt/clips/common_voice_tt_00000000.wav` +* `LibriSpeech/dev-clean/1272/128104/1272-128104-0000.flac` +* `LJSpeech-1.1/wavs/LJ001-0001.wav` +* `SpeechCommands/speech_commands_v0.02/go/0a9f9af7_nohash_0.wav` +* `VCTK-Corpus/wav48/p224/p224_002.wav` +* `waves_yesno/0_1_0_1_0_1_1_0.wav` +* `vad-go-stereo-44100.wav` +* `vad-go-mono-32000.wav` ## Adding test diff --git a/test/assets/CommonVoice/cv-corpus-4-2019-12-10/tt/clips/common_voice_tt_00000000.mp3 b/test/assets/CommonVoice/cv-corpus-4-2019-12-10/tt/clips/common_voice_tt_00000000.mp3 deleted file mode 100644 index d6fe9f44b90bb0e03d7b3ebfb8f46858f888bc3a..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 57136 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 diff --git a/test/assets/CommonVoice/cv-corpus-4-2019-12-10/tt/clips/common_voice_tt_00000000.wav b/test/assets/CommonVoice/cv-corpus-4-2019-12-10/tt/clips/common_voice_tt_00000000.wav new file mode 100644 index 0000000000000000000000000000000000000000..8f9d80d7e152b418703d0421f8ea5e0b710d6a89 GIT binary patch literal 80700 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 literal 0 HcmV?d00001 diff --git a/test/assets/CommonVoice/cv-corpus-4-2019-12-10/tt/train.tsv b/test/assets/CommonVoice/cv-corpus-4-2019-12-10/tt/train.tsv index 2b677dbf7f..a5244b01f2 100644 --- a/test/assets/CommonVoice/cv-corpus-4-2019-12-10/tt/train.tsv +++ b/test/assets/CommonVoice/cv-corpus-4-2019-12-10/tt/train.tsv @@ -1,3 +1,3 @@ client_id path sentence up_votes down_votes age gender accent -00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 common_voice_tt_00000000.mp3 test. 1 0 thirties female -00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001 common_voice_tt_00000000.mp3 test. 1 0 thirties female +00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 common_voice_tt_00000000.wav test. 1 0 thirties female +00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001 common_voice_tt_00000000.wav test. 1 0 thirties female diff --git a/test/assets/dtmf_30s_stereo.mp3 b/test/assets/dtmf_30s_stereo.mp3 deleted file mode 100644 index 6c97835ec0dedc5273f1aeee4d5d4bdd7c541b41..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 228984 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%0Dpm;`O%JVx#`VwGdAP%kJv+INes^| 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�o}ou>L#n&!)STAN?mwDlk$4QPHK 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 diff --git a/test/assets/io/96k_0_1ch.opus b/test/assets/io/96k_0_1ch.opus new file mode 100644 index 0000000000000000000000000000000000000000..df95474ddb67499f9223537f0081c689b0be654a GIT binary patch literal 8259 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 literal 0 HcmV?d00001 diff --git a/test/assets/io/96k_0_2ch.opus b/test/assets/io/96k_0_2ch.opus new file mode 100644 index 0000000000000000000000000000000000000000..b8837e81e26b579d984f2b871523322d4e8b5399 GIT binary patch literal 6740 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 LtBkx?x;Fd|2;dDu literal 0 HcmV?d00001 diff --git a/test/assets/io/96k_10_1ch.opus b/test/assets/io/96k_10_1ch.opus new file mode 100644 index 0000000000000000000000000000000000000000..56b170d380376604f308a28cb2ca92ed1f1481cc GIT binary patch literal 15033 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 literal 0 HcmV?d00001 diff --git a/test/assets/io/96k_5_2ch.opus b/test/assets/io/96k_5_2ch.opus new file mode 100644 index 0000000000000000000000000000000000000000..007bc813cea92c6555cde19b2ff0f8e779a59614 GIT binary patch literal 10618 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 literal 0 HcmV?d00001 diff --git a/test/assets/io/generate_opus.py b/test/assets/io/generate_opus.py new file mode 100644 index 0000000000..e6b99c471c --- /dev/null +++ b/test/assets/io/generate_opus.py @@ -0,0 +1,50 @@ +"""Generate opus file for testing load functions""" + +import argparse +import subprocess + +import scipy.io.wavfile +import torch + + +def _parse_args(): + parser = argparse.ArgumentParser( + description='Generate opus files for test' + ) + parser.add_argument('--num-channels', required=True, type=int) + parser.add_argument('--compression-level', required=True, type=int, choices=list(range(11))) + parser.add_argument('--bitrate', default='96k') + return parser.parse_args() + + +def convert_to_opus( + src_path, dst_path, + *, bitrate, compression_level): + """Convert audio file with `ffmpeg` command.""" + command = ['ffmpeg', '-y', '-i', src_path, '-c:a', 'libopus', '-b:a', bitrate] + if compression_level is not None: + command += ['-compression_level', str(compression_level)] + command += [dst_path] + print(' '.join(command)) + subprocess.run(command, check=True) + + +def _generate(num_channels, compression_level, bitrate): + org_path = 'original.wav' + ops_path = f'{bitrate}_{compression_level}_{num_channels}ch.opus' + + # Note: ffmpeg forces sample rate 48k Hz for opus https://stackoverflow.com/a/39186779 + # 1. generate original wav + data = torch.linspace(-32768, 32767, 32768, dtype=torch.int16).repeat([num_channels, 1]).t() + scipy.io.wavfile.write(org_path, 48000, data.numpy()) + # 2. convert to opus + convert_to_opus(org_path, ops_path, bitrate=bitrate, compression_level=compression_level) + + +def _main(): + args = _parse_args() + _generate(args.num_channels, args.compression_level, args.bitrate) + + +if __name__ == '__main__': + _main() diff --git a/test/common_utils.py b/test/common_utils.py deleted file mode 100644 index fe045d9db8..0000000000 --- a/test/common_utils.py +++ /dev/null @@ -1,171 +0,0 @@ -import os -import tempfile -import unittest -from typing import Union -from shutil import copytree - -import torch -from torch.testing._internal.common_utils import TestCase as PytorchTestCase -import torchaudio - -_TEST_DIR_PATH = os.path.dirname(os.path.realpath(__file__)) -BACKENDS = torchaudio.list_audio_backends() - - -def get_asset_path(*paths): - """Return full path of a test asset""" - return os.path.join(_TEST_DIR_PATH, 'assets', *paths) - - -def create_temp_assets_dir(): - """ - Creates a temporary directory and moves all files from test/assets there. - Returns a Tuple[string, TemporaryDirectory] which is the folder path - and object. - """ - tmp_dir = tempfile.TemporaryDirectory() - copytree(os.path.join(_TEST_DIR_PATH, "assets"), - os.path.join(tmp_dir.name, "assets")) - return tmp_dir.name, tmp_dir - - -def random_float_tensor(seed, size, a=22695477, c=1, m=2 ** 32): - """ Generates random tensors given a seed and size - https://en.wikipedia.org/wiki/Linear_congruential_generator - X_{n + 1} = (a * X_n + c) % m - Using Borland C/C++ values - - The tensor will have values between [0,1) - Inputs: - seed (int): an int - size (Tuple[int]): the size of the output tensor - a (int): the multiplier constant to the generator - c (int): the additive constant to the generator - m (int): the modulus constant to the generator - """ - num_elements = 1 - for s in size: - num_elements *= s - - arr = [(a * seed + c) % m] - for i in range(num_elements - 1): - arr.append((a * arr[i] + c) % m) - - return torch.tensor(arr).float().view(size) / m - - -def filter_backends_with_mp3(backends): - # Filter out backends that do not support mp3 - test_filepath = get_asset_path('steam-train-whistle-daniel_simon.mp3') - - def supports_mp3(backend): - torchaudio.set_audio_backend(backend) - try: - torchaudio.load(test_filepath) - return True - except (RuntimeError, ImportError): - return False - - return [backend for backend in backends if supports_mp3(backend)] - - -BACKENDS_MP3 = filter_backends_with_mp3(BACKENDS) - - -def set_audio_backend(backend): - """Allow additional backend value, 'default'""" - if backend == 'default': - if 'sox' in BACKENDS: - be = 'sox' - elif 'soundfile' in BACKENDS: - be = 'soundfile' - else: - raise unittest.SkipTest('No default backend available') - else: - be = backend - - torchaudio.set_audio_backend(be) - - -class TestBaseMixin: - """Mixin to provide consistent way to define device/dtype/backend aware TestCase""" - dtype = None - device = None - backend = None - - def setUp(self): - super().setUp() - set_audio_backend(self.backend) - - -class TorchaudioTestCase(TestBaseMixin, PytorchTestCase): - pass - - -skipIfNoSoxBackend = unittest.skipIf('sox' not in BACKENDS, 'Sox backend not available') -skipIfNoCuda = unittest.skipIf(not torch.cuda.is_available(), reason='CUDA not available') - - -def get_whitenoise( - *, - sample_rate: int = 16000, - duration: float = 1, # seconds - n_channels: int = 1, - seed: int = 0, - dtype: Union[str, torch.dtype] = "float32", - device: Union[str, torch.device] = "cpu", -): - """Generate pseudo audio data with whitenoise - - Args: - sample_rate: Sampling rate - duration: Length of the resulting Tensor in seconds. - n_channels: Number of channels - seed: Seed value used for random number generation. - Note that this function does not modify global random generator state. - dtype: Torch dtype - device: device - Returns: - Tensor: shape of (n_channels, sample_rate * duration) - """ - if isinstance(dtype, str): - dtype = getattr(torch, dtype) - shape = [n_channels, sample_rate * duration] - # According to the doc, folking rng on all CUDA devices is slow when there are many CUDA devices, - # so we only folk on CPU, generate values and move the data to the given device - with torch.random.fork_rng([]): - torch.random.manual_seed(seed) - tensor = torch.randn(shape, dtype=dtype, device='cpu') - tensor /= 2.0 - tensor.clamp_(-1.0, 1.0) - return tensor.to(device=device) - - -def get_sinusoid( - *, - frequency: float = 300, - sample_rate: int = 16000, - duration: float = 1, # seconds - n_channels: int = 1, - dtype: Union[str, torch.dtype] = "float32", - device: Union[str, torch.device] = "cpu", -): - """Generate pseudo audio data with sine wave. - - Args: - frequency: Frequency of sine wave - sample_rate: Sampling rate - duration: Length of the resulting Tensor in seconds. - n_channels: Number of channels - dtype: Torch dtype - device: device - - Returns: - Tensor: shape of (n_channels, sample_rate * duration) - """ - if isinstance(dtype, str): - dtype = getattr(torch, dtype) - pie2 = 2 * 3.141592653589793 - end = pie2 * frequency * duration - theta = torch.linspace(0, end, sample_rate * duration, dtype=dtype, device=device) - return torch.sin(theta, out=None).repeat([n_channels, 1]) diff --git a/test/common_utils/__init__.py b/test/common_utils/__init__.py new file mode 100644 index 0000000000..841cd26713 --- /dev/null +++ b/test/common_utils/__init__.py @@ -0,0 +1,31 @@ +from .data_utils import ( + get_asset_path, + get_whitenoise, + get_sinusoid, +) +from .backend_utils import ( + set_audio_backend, + BACKENDS, + BACKENDS_MP3, +) +from .case_utils import ( + TempDirMixin, + TestBaseMixin, + PytorchTestCase, + TorchaudioTestCase, + skipIfNoCuda, + skipIfNoExec, + skipIfNoModule, + skipIfNoExtension, + skipIfNoSoxBackend, +) +from .wav_utils import ( + get_wav_data, + normalize_wav, + load_wav, + save_wav, +) +from .parameterized_utils import ( + load_params, +) +from . import sox_utils diff --git a/test/common_utils/backend_utils.py b/test/common_utils/backend_utils.py new file mode 100644 index 0000000000..158fde87ed --- /dev/null +++ b/test/common_utils/backend_utils.py @@ -0,0 +1,41 @@ +import unittest + +import torchaudio + +from .import data_utils + + +BACKENDS = torchaudio.list_audio_backends() + + +def _filter_backends_with_mp3(backends): + # Filter out backends that do not support mp3 + test_filepath = data_utils.get_asset_path('steam-train-whistle-daniel_simon.mp3') + + def supports_mp3(backend): + torchaudio.set_audio_backend(backend) + try: + torchaudio.load(test_filepath) + return True + except (RuntimeError, ImportError): + return False + + return [backend for backend in backends if supports_mp3(backend)] + + +BACKENDS_MP3 = _filter_backends_with_mp3(BACKENDS) + + +def set_audio_backend(backend): + """Allow additional backend value, 'default'""" + if backend == 'default': + if 'sox' in BACKENDS: + be = 'sox' + elif 'soundfile' in BACKENDS: + be = 'soundfile' + else: + raise unittest.SkipTest('No default backend available') + else: + be = backend + + torchaudio.set_audio_backend(be) diff --git a/test/common_utils/case_utils.py b/test/common_utils/case_utils.py new file mode 100644 index 0000000000..f3b0c343a6 --- /dev/null +++ b/test/common_utils/case_utils.py @@ -0,0 +1,75 @@ +import shutil +import os.path +import tempfile +import unittest + +import torch +from torch.testing._internal.common_utils import TestCase as PytorchTestCase +import torchaudio +from torchaudio._internal.module_utils import is_module_available + +from .backend_utils import set_audio_backend + + +class TempDirMixin: + """Mixin to provide easy access to temp dir""" + temp_dir_ = None + base_temp_dir = None + temp_dir = None + + @classmethod + def setUpClass(cls): + super().setUpClass() + # If TORCHAUDIO_TEST_TEMP_DIR is set, use it instead of temporary directory. + # this is handy for debugging. + key = 'TORCHAUDIO_TEST_TEMP_DIR' + if key in os.environ: + cls.base_temp_dir = os.environ[key] + else: + cls.temp_dir_ = tempfile.TemporaryDirectory() + cls.base_temp_dir = cls.temp_dir_.name + + @classmethod + def tearDownClass(cls): + super().tearDownClass() + if isinstance(cls.temp_dir_, tempfile.TemporaryDirectory): + cls.temp_dir_.cleanup() + + def setUp(self): + super().setUp() + self.temp_dir = os.path.join(self.base_temp_dir, self.id()) + + def get_temp_path(self, *paths): + path = os.path.join(self.temp_dir, *paths) + os.makedirs(os.path.dirname(path), exist_ok=True) + return path + + +class TestBaseMixin: + """Mixin to provide consistent way to define device/dtype/backend aware TestCase""" + dtype = None + device = None + backend = None + + def setUp(self): + super().setUp() + set_audio_backend(self.backend) + + +class TorchaudioTestCase(TestBaseMixin, PytorchTestCase): + pass + + +def skipIfNoExec(cmd): + return unittest.skipIf(shutil.which(cmd) is None, f'`{cmd}` is not available') + + +def skipIfNoModule(module, display_name=None): + display_name = display_name or module + return unittest.skipIf(not is_module_available(module), f'"{display_name}" is not available') + + +skipIfNoSoxBackend = unittest.skipIf( + 'sox' not in torchaudio.list_audio_backends(), 'Sox backend not available') +skipIfNoCuda = unittest.skipIf(not torch.cuda.is_available(), reason='CUDA not available') +skipIfNoExtension = skipIfNoModule('torchaudio._torchaudio', 'torchaudio C++ extension') diff --git a/test/common_utils/data_utils.py b/test/common_utils/data_utils.py new file mode 100644 index 0000000000..b948ce334a --- /dev/null +++ b/test/common_utils/data_utils.py @@ -0,0 +1,94 @@ +import os.path +from typing import Union + +import torch + + +_TEST_DIR_PATH = os.path.realpath( + os.path.join(os.path.dirname(__file__), '..')) + + +def get_asset_path(*paths): + """Return full path of a test asset""" + return os.path.join(_TEST_DIR_PATH, 'assets', *paths) + + +def get_whitenoise( + *, + sample_rate: int = 16000, + duration: float = 1, # seconds + n_channels: int = 1, + seed: int = 0, + dtype: Union[str, torch.dtype] = "float32", + device: Union[str, torch.device] = "cpu", + channels_first=True, + scale_factor: float = 1, +): + """Generate pseudo audio data with whitenoise + Args: + sample_rate: Sampling rate + duration: Length of the resulting Tensor in seconds. + n_channels: Number of channels + seed: Seed value used for random number generation. + Note that this function does not modify global random generator state. + dtype: Torch dtype + device: device + channels_first: whether first dimension is n_channels + scale_factor: scale the Tensor before clamping and quantization + Returns: + Tensor: shape of (n_channels, sample_rate * duration) + """ + if isinstance(dtype, str): + dtype = getattr(torch, dtype) + if dtype not in [torch.float32, torch.int32, torch.int16, torch.uint8]: + raise NotImplementedError(f'dtype {dtype} is not supported.') + # According to the doc, folking rng on all CUDA devices is slow when there are many CUDA devices, + # so we only folk on CPU, generate values and move the data to the given device + with torch.random.fork_rng([]): + torch.random.manual_seed(seed) + tensor = torch.randn([sample_rate * duration], dtype=torch.float32, device='cpu') + tensor /= 2.0 + tensor *= scale_factor + tensor.clamp_(-1.0, 1.0) + if dtype == torch.int32: + tensor *= (tensor > 0) * 2147483647 + (tensor < 0) * 2147483648 + if dtype == torch.int16: + tensor *= (tensor > 0) * 32767 + (tensor < 0) * 32768 + if dtype == torch.uint8: + tensor *= (tensor > 0) * 127 + (tensor < 0) * 128 + tensor += 128 + tensor = tensor.to(dtype) + tensor = tensor.repeat([n_channels, 1]) + if not channels_first: + tensor = tensor.t() + return tensor.to(device=device) + + +def get_sinusoid( + *, + frequency: float = 300, + sample_rate: int = 16000, + duration: float = 1, # seconds + n_channels: int = 1, + dtype: Union[str, torch.dtype] = "float32", + device: Union[str, torch.device] = "cpu", +): + """Generate pseudo audio data with sine wave. + + Args: + frequency: Frequency of sine wave + sample_rate: Sampling rate + duration: Length of the resulting Tensor in seconds. + n_channels: Number of channels + dtype: Torch dtype + device: device + + Returns: + Tensor: shape of (n_channels, sample_rate * duration) + """ + if isinstance(dtype, str): + dtype = getattr(torch, dtype) + pie2 = 2 * 3.141592653589793 + end = pie2 * frequency * duration + theta = torch.linspace(0, end, sample_rate * duration, dtype=dtype, device=device) + return torch.sin(theta, out=None).repeat([n_channels, 1]) diff --git a/test/common_utils/parameterized_utils.py b/test/common_utils/parameterized_utils.py new file mode 100644 index 0000000000..24404a6edd --- /dev/null +++ b/test/common_utils/parameterized_utils.py @@ -0,0 +1,10 @@ +import json + +from parameterized import param + +from .data_utils import get_asset_path + + +def load_params(*paths): + with open(get_asset_path(*paths), 'r') as file: + return [param(json.loads(line)) for line in file] diff --git a/test/common_utils/sox_utils.py b/test/common_utils/sox_utils.py new file mode 100644 index 0000000000..cd1c247b72 --- /dev/null +++ b/test/common_utils/sox_utils.py @@ -0,0 +1,79 @@ +import subprocess + + +def get_encoding(dtype): + encodings = { + 'float32': 'floating-point', + 'int32': 'signed-integer', + 'int16': 'signed-integer', + 'uint8': 'unsigned-integer', + } + return encodings[dtype] + + +def get_bit_depth(dtype): + bit_depths = { + 'float32': 32, + 'int32': 32, + 'int16': 16, + 'uint8': 8, + } + return bit_depths[dtype] + + +def gen_audio_file( + path, sample_rate, num_channels, + *, encoding=None, bit_depth=None, compression=None, attenuation=None, duration=1, +): + """Generate synthetic audio file with `sox` command.""" + if path.endswith('.wav'): + raise RuntimeError( + 'Use get_wav_data and save_wav to generate wav file for accurate result.') + command = [ + 'sox', + '-V3', # verbose + '-R', + # -R is supposed to be repeatable, though the implementation looks suspicious + # and not setting the seed to a fixed value. + # https://fossies.org/dox/sox-14.4.2/sox_8c_source.html + # search "sox_globals.repeatable" + ] + if bit_depth is not None: + command += ['--bits', str(bit_depth)] + command += [ + '--rate', str(sample_rate), + '--null', # no input + '--channels', str(num_channels), + ] + if compression is not None: + command += ['--compression', str(compression)] + if bit_depth is not None: + command += ['--bits', str(bit_depth)] + if encoding is not None: + command += ['--encoding', str(encoding)] + command += [ + str(path), + 'synth', str(duration), # synthesizes for the given duration [sec] + 'sawtooth', '1', + # saw tooth covers the both ends of value range, which is a good property for test. + # similar to linspace(-1., 1.) + # this introduces bigger boundary effect than sine when converted to mp3 + ] + if attenuation is not None: + command += ['vol', f'-{attenuation}dB'] + print(' '.join(command)) + subprocess.run(command, check=True) + + +def convert_audio_file( + src_path, dst_path, + *, bit_depth=None, compression=None): + """Convert audio file with `sox` command.""" + command = ['sox', '-V3', '-R', str(src_path)] + if bit_depth is not None: + command += ['--bits', str(bit_depth)] + if compression is not None: + command += ['--compression', str(compression)] + command += [dst_path] + print(' '.join(command)) + subprocess.run(command, check=True) diff --git a/test/common_utils/wav_utils.py b/test/common_utils/wav_utils.py new file mode 100644 index 0000000000..bc122ec6cb --- /dev/null +++ b/test/common_utils/wav_utils.py @@ -0,0 +1,86 @@ +from typing import Optional + +import torch +import scipy.io.wavfile + + +def normalize_wav(tensor: torch.Tensor) -> torch.Tensor: + if tensor.dtype == torch.float32: + pass + elif tensor.dtype == torch.int32: + tensor = tensor.to(torch.float32) + tensor[tensor > 0] /= 2147483647. + tensor[tensor < 0] /= 2147483648. + elif tensor.dtype == torch.int16: + tensor = tensor.to(torch.float32) + tensor[tensor > 0] /= 32767. + tensor[tensor < 0] /= 32768. + elif tensor.dtype == torch.uint8: + tensor = tensor.to(torch.float32) - 128 + tensor[tensor > 0] /= 127. + tensor[tensor < 0] /= 128. + return tensor + + +def get_wav_data( + dtype: str, + num_channels: int, + *, + num_frames: Optional[int] = None, + normalize: bool = True, + channels_first: bool = True, +): + """Generate linear signal of the given dtype and num_channels + + Data range is + [-1.0, 1.0] for float32, + [-2147483648, 2147483647] for int32 + [-32768, 32767] for int16 + [0, 255] for uint8 + + num_frames allow to change the linear interpolation parameter. + Default values are 256 for uint8, else 1 << 16. + 1 << 16 as default is so that int16 value range is completely covered. + """ + dtype_ = getattr(torch, dtype) + + if num_frames is None: + if dtype == 'uint8': + num_frames = 256 + else: + num_frames = 1 << 16 + + if dtype == 'uint8': + base = torch.linspace(0, 255, num_frames, dtype=dtype_) + if dtype == 'float32': + base = torch.linspace(-1., 1., num_frames, dtype=dtype_) + if dtype == 'int32': + base = torch.linspace(-2147483648, 2147483647, num_frames, dtype=dtype_) + if dtype == 'int16': + base = torch.linspace(-32768, 32767, num_frames, dtype=dtype_) + data = base.repeat([num_channels, 1]) + if not channels_first: + data = data.transpose(1, 0) + if normalize: + data = normalize_wav(data) + return data + + +def load_wav(path: str, normalize=True, channels_first=True) -> torch.Tensor: + """Load wav file without torchaudio""" + sample_rate, data = scipy.io.wavfile.read(path) + data = torch.from_numpy(data.copy()) + if data.ndim == 1: + data = data.unsqueeze(1) + if normalize: + data = normalize_wav(data) + if channels_first: + data = data.transpose(1, 0) + return data, sample_rate + + +def save_wav(path, data, sample_rate, channels_first=True): + """Save wav file without torchaudio""" + if channels_first: + data = data.transpose(1, 0) + scipy.io.wavfile.write(path, sample_rate, data.numpy()) diff --git a/test/functional_cpu_test.py b/test/functional_cpu_test.py index 470d6ab770..ab5fdaed95 100644 --- a/test/functional_cpu_test.py +++ b/test/functional_cpu_test.py @@ -10,6 +10,31 @@ from .functional_impl import Lfilter +def random_float_tensor(seed, size, a=22695477, c=1, m=2 ** 32): + """ Generates random tensors given a seed and size + https://en.wikipedia.org/wiki/Linear_congruential_generator + X_{n + 1} = (a * X_n + c) % m + Using Borland C/C++ values + + The tensor will have values between [0,1) + Inputs: + seed (int): an int + size (Tuple[int]): the size of the output tensor + a (int): the multiplier constant to the generator + c (int): the additive constant to the generator + m (int): the modulus constant to the generator + """ + num_elements = 1 + for s in size: + num_elements *= s + + arr = [(a * seed + c) % m] + for i in range(num_elements - 1): + arr.append((a * arr[i] + c) % m) + + return torch.tensor(arr).float().view(size) / m + + class TestLFilterFloat32(Lfilter, common_utils.PytorchTestCase): dtype = torch.float32 device = torch.device('cpu') @@ -49,7 +74,7 @@ def _test_istft_is_inverse_of_stft(kwargs): for data_size in [(2, 20), (3, 15), (4, 10)]: for i in range(100): - sound = common_utils.random_float_tensor(i, data_size) + sound = random_float_tensor(i, data_size) stft = torch.stft(sound, **kwargs) estimate = torchaudio.functional.istft(stft, length=sound.size(1), **kwargs) @@ -211,8 +236,8 @@ def test_istft_of_sine(self): def _test_linearity_of_istft(self, data_size, kwargs, atol=1e-6, rtol=1e-8): for i in range(self.number_of_trials): - tensor1 = common_utils.random_float_tensor(i, data_size) - tensor2 = common_utils.random_float_tensor(i * 2, data_size) + tensor1 = random_float_tensor(i, data_size) + tensor2 = random_float_tensor(i * 2, data_size) a, b = torch.rand(2) istft1 = torchaudio.functional.istft(tensor1, **kwargs) istft2 = torchaudio.functional.istft(tensor2, **kwargs) @@ -274,8 +299,6 @@ def test_linearity_of_istft4(self): class TestDetectPitchFrequency(common_utils.TorchaudioTestCase): - backend = 'default' - def test_pitch(self): test_filepath_100 = common_utils.get_asset_path("100Hz_44100Hz_16bit_05sec.wav") test_filepath_440 = common_utils.get_asset_path("440Hz_44100Hz_16bit_05sec.wav") @@ -287,7 +310,7 @@ def test_pitch(self): ] for filename, freq_ref in tests: - waveform, sample_rate = torchaudio.load(filename) + waveform, sample_rate = common_utils.load_wav(filename) freq = torchaudio.functional.detect_pitch_frequency(waveform, sample_rate) diff --git a/test/kaldi_compatibility_impl.py b/test/kaldi_compatibility_impl.py index ec58a3fa44..7e51620f63 100644 --- a/test/kaldi_compatibility_impl.py +++ b/test/kaldi_compatibility_impl.py @@ -1,20 +1,19 @@ """Test suites for checking numerical compatibility against Kaldi""" -import json -import shutil -import unittest import subprocess import kaldi_io import torch import torchaudio.functional as F import torchaudio.compliance.kaldi +from parameterized import parameterized -from . import common_utils -from parameterized import parameterized, param - - -def _not_available(cmd): - return shutil.which(cmd) is None +from .common_utils import ( + TestBaseMixin, + load_params, + skipIfNoExec, + get_asset_path, + load_wav +) def _convert_args(**kwargs): @@ -49,19 +48,12 @@ def _run_kaldi(command, input_type, input_value): return torch.from_numpy(result.copy()) # copy supresses some torch warning -def _load_params(path): - with open(path, 'r') as file: - return [param(json.loads(line)) for line in file] - - -class Kaldi(common_utils.TestBaseMixin): - backend = 'sox' - +class Kaldi(TestBaseMixin): def assert_equal(self, output, *, expected, rtol=None, atol=None): expected = expected.to(dtype=self.dtype, device=self.device) self.assertEqual(output, expected, rtol=rtol, atol=atol) - @unittest.skipIf(_not_available('apply-cmvn-sliding'), '`apply-cmvn-sliding` not available') + @skipIfNoExec('apply-cmvn-sliding') def test_sliding_window_cmn(self): """sliding_window_cmn should be numerically compatible with apply-cmvn-sliding""" kwargs = { @@ -77,34 +69,34 @@ def test_sliding_window_cmn(self): kaldi_result = _run_kaldi(command, 'ark', tensor) self.assert_equal(result, expected=kaldi_result) - @parameterized.expand(_load_params(common_utils.get_asset_path('kaldi_test_fbank_args.json'))) - @unittest.skipIf(_not_available('compute-fbank-feats'), '`compute-fbank-feats` not available') + @parameterized.expand(load_params('kaldi_test_fbank_args.json')) + @skipIfNoExec('compute-fbank-feats') def test_fbank(self, kwargs): """fbank should be numerically compatible with compute-fbank-feats""" - wave_file = common_utils.get_asset_path('kaldi_file.wav') - waveform = torchaudio.load_wav(wave_file)[0].to(dtype=self.dtype, device=self.device) + wave_file = get_asset_path('kaldi_file.wav') + waveform = load_wav(wave_file, normalize=False)[0].to(dtype=self.dtype, device=self.device) result = torchaudio.compliance.kaldi.fbank(waveform, **kwargs) command = ['compute-fbank-feats'] + _convert_args(**kwargs) + ['scp:-', 'ark:-'] kaldi_result = _run_kaldi(command, 'scp', wave_file) self.assert_equal(result, expected=kaldi_result, rtol=1e-4, atol=1e-8) - @parameterized.expand(_load_params(common_utils.get_asset_path('kaldi_test_spectrogram_args.json'))) - @unittest.skipIf(_not_available('compute-spectrogram-feats'), '`compute-spectrogram-feats` not available') + @parameterized.expand(load_params('kaldi_test_spectrogram_args.json')) + @skipIfNoExec('compute-spectrogram-feats') def test_spectrogram(self, kwargs): """spectrogram should be numerically compatible with compute-spectrogram-feats""" - wave_file = common_utils.get_asset_path('kaldi_file.wav') - waveform = torchaudio.load_wav(wave_file)[0].to(dtype=self.dtype, device=self.device) + wave_file = get_asset_path('kaldi_file.wav') + waveform = load_wav(wave_file, normalize=False)[0].to(dtype=self.dtype, device=self.device) result = torchaudio.compliance.kaldi.spectrogram(waveform, **kwargs) command = ['compute-spectrogram-feats'] + _convert_args(**kwargs) + ['scp:-', 'ark:-'] kaldi_result = _run_kaldi(command, 'scp', wave_file) self.assert_equal(result, expected=kaldi_result, rtol=1e-4, atol=1e-8) - @parameterized.expand(_load_params(common_utils.get_asset_path('kaldi_test_mfcc_args.json'))) - @unittest.skipIf(_not_available('compute-mfcc-feats'), '`compute-mfcc-feats` not available') + @parameterized.expand(load_params('kaldi_test_mfcc_args.json')) + @skipIfNoExec('compute-mfcc-feats') def test_mfcc(self, kwargs): """mfcc should be numerically compatible with compute-mfcc-feats""" - wave_file = common_utils.get_asset_path('kaldi_file.wav') - waveform = torchaudio.load_wav(wave_file)[0].to(dtype=self.dtype, device=self.device) + wave_file = get_asset_path('kaldi_file.wav') + waveform = load_wav(wave_file, normalize=False)[0].to(dtype=self.dtype, device=self.device) result = torchaudio.compliance.kaldi.mfcc(waveform, **kwargs) command = ['compute-mfcc-feats'] + _convert_args(**kwargs) + ['scp:-', 'ark:-'] kaldi_result = _run_kaldi(command, 'scp', wave_file) diff --git a/test/sox_io_backend/__init__.py b/test/sox_io_backend/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/test/sox_io_backend/common.py b/test/sox_io_backend/common.py new file mode 100644 index 0000000000..eb85937236 --- /dev/null +++ b/test/sox_io_backend/common.py @@ -0,0 +1,2 @@ +def name_func(func, _, params): + return f'{func.__name__}_{"_".join(str(arg) for arg in params.args)}' diff --git a/test/sox_io_backend/test_info.py b/test/sox_io_backend/test_info.py new file mode 100644 index 0000000000..da5207a7e5 --- /dev/null +++ b/test/sox_io_backend/test_info.py @@ -0,0 +1,125 @@ +import itertools +from parameterized import parameterized + +from torchaudio.backend import sox_io_backend + +from ..common_utils import ( + TempDirMixin, + PytorchTestCase, + skipIfNoExec, + skipIfNoExtension, + get_asset_path, + get_wav_data, + save_wav, + sox_utils, +) +from .common import ( + name_func, +) + + +@skipIfNoExec('sox') +@skipIfNoExtension +class TestInfo(TempDirMixin, PytorchTestCase): + @parameterized.expand(list(itertools.product( + ['float32', 'int32', 'int16', 'uint8'], + [8000, 16000], + [1, 2], + )), name_func=name_func) + def test_wav(self, dtype, sample_rate, num_channels): + """`sox_io_backend.info` can check wav file correctly""" + duration = 1 + path = self.get_temp_path('data.wav') + data = get_wav_data(dtype, num_channels, normalize=False, num_frames=duration * sample_rate) + save_wav(path, data, sample_rate) + info = sox_io_backend.info(path) + assert info.sample_rate == sample_rate + assert info.num_frames == sample_rate * duration + assert info.num_channels == num_channels + + @parameterized.expand(list(itertools.product( + ['float32', 'int32', 'int16', 'uint8'], + [8000, 16000], + [4, 8, 16, 32], + )), name_func=name_func) + def test_wav_multiple_channels(self, dtype, sample_rate, num_channels): + """`sox_io_backend.info` can check wav file with channels more than 2 correctly""" + duration = 1 + path = self.get_temp_path('data.wav') + data = get_wav_data(dtype, num_channels, normalize=False, num_frames=duration * sample_rate) + save_wav(path, data, sample_rate) + info = sox_io_backend.info(path) + assert info.sample_rate == sample_rate + assert info.num_frames == sample_rate * duration + assert info.num_channels == num_channels + + @parameterized.expand(list(itertools.product( + [8000, 16000], + [1, 2], + [96, 128, 160, 192, 224, 256, 320], + )), name_func=name_func) + def test_mp3(self, sample_rate, num_channels, bit_rate): + """`sox_io_backend.info` can check mp3 file correctly""" + duration = 1 + path = self.get_temp_path('data.mp3') + sox_utils.gen_audio_file( + path, sample_rate, num_channels, + compression=bit_rate, duration=duration, + ) + info = sox_io_backend.info(path) + assert info.sample_rate == sample_rate + # mp3 does not preserve the number of samples + # assert info.num_frames == sample_rate * duration + assert info.num_channels == num_channels + + @parameterized.expand(list(itertools.product( + [8000, 16000], + [1, 2], + list(range(9)), + )), name_func=name_func) + def test_flac(self, sample_rate, num_channels, compression_level): + """`sox_io_backend.info` can check flac file correctly""" + duration = 1 + path = self.get_temp_path('data.flac') + sox_utils.gen_audio_file( + path, sample_rate, num_channels, + compression=compression_level, duration=duration, + ) + info = sox_io_backend.info(path) + assert info.sample_rate == sample_rate + assert info.num_frames == sample_rate * duration + assert info.num_channels == num_channels + + @parameterized.expand(list(itertools.product( + [8000, 16000], + [1, 2], + [-1, 0, 1, 2, 3, 3.6, 5, 10], + )), name_func=name_func) + def test_vorbis(self, sample_rate, num_channels, quality_level): + """`sox_io_backend.info` can check vorbis file correctly""" + duration = 1 + path = self.get_temp_path('data.vorbis') + sox_utils.gen_audio_file( + path, sample_rate, num_channels, + compression=quality_level, duration=duration, + ) + info = sox_io_backend.info(path) + assert info.sample_rate == sample_rate + assert info.num_frames == sample_rate * duration + assert info.num_channels == num_channels + + +@skipIfNoExtension +class TestInfoOpus(PytorchTestCase): + @parameterized.expand(list(itertools.product( + ['96k'], + [1, 2], + [0, 5, 10], + )), name_func=name_func) + def test_opus(self, bitrate, num_channels, compression_level): + """`sox_io_backend.info` can check opus file correcty""" + path = get_asset_path('io', f'{bitrate}_{compression_level}_{num_channels}ch.opus') + info = sox_io_backend.info(path) + assert info.sample_rate == 48000 + assert info.num_frames == 32768 + assert info.num_channels == num_channels diff --git a/test/sox_io_backend/test_load.py b/test/sox_io_backend/test_load.py new file mode 100644 index 0000000000..8366a01f83 --- /dev/null +++ b/test/sox_io_backend/test_load.py @@ -0,0 +1,263 @@ +import itertools + +from torchaudio.backend import sox_io_backend +from parameterized import parameterized + +from ..common_utils import ( + TempDirMixin, + PytorchTestCase, + skipIfNoExec, + skipIfNoExtension, + get_asset_path, + get_wav_data, + load_wav, + save_wav, + sox_utils, +) +from .common import ( + name_func, +) + + +class LoadTestBase(TempDirMixin, PytorchTestCase): + def assert_wav(self, dtype, sample_rate, num_channels, normalize, duration): + """`sox_io_backend.load` can load wav format correctly. + + Wav data loaded with sox_io backend should match those with scipy + """ + path = self.get_temp_path('reference.wav') + data = get_wav_data(dtype, num_channels, normalize=normalize, num_frames=duration * sample_rate) + save_wav(path, data, sample_rate) + expected = load_wav(path, normalize=normalize)[0] + data, sr = sox_io_backend.load(path, normalize=normalize) + assert sr == sample_rate + self.assertEqual(data, expected) + + def assert_mp3(self, sample_rate, num_channels, bit_rate, duration): + """`sox_io_backend.load` can load mp3 format. + + mp3 encoding introduces delay and boundary effects so + we create reference wav file from mp3 + + x + | + | 1. Generate mp3 with Sox + | + v 2. Convert to wav with Sox + mp3 ------------------------------> wav + | | + | 3. Load with torchaudio | 4. Load with scipy + | | + v v + tensor ----------> x <----------- tensor + 5. Compare + + Underlying assumptions are; + i. Conversion of mp3 to wav with Sox preserves data. + ii. Loading wav file with scipy is correct. + + By combining i & ii, step 2. and 4. allows to load reference mp3 data + without using torchaudio + """ + path = self.get_temp_path('1.original.mp3') + ref_path = self.get_temp_path('2.reference.wav') + + # 1. Generate mp3 with sox + sox_utils.gen_audio_file( + path, sample_rate, num_channels, + compression=bit_rate, duration=duration) + # 2. Convert to wav with sox + sox_utils.convert_audio_file(path, ref_path) + # 3. Load mp3 with torchaudio + data, sr = sox_io_backend.load(path) + # 4. Load wav with scipy + data_ref = load_wav(ref_path)[0] + # 5. Compare + assert sr == sample_rate + self.assertEqual(data, data_ref, atol=3e-03, rtol=1.3e-06) + + def assert_flac(self, sample_rate, num_channels, compression_level, duration): + """`sox_io_backend.load` can load flac format. + + This test takes the same strategy as mp3 to compare the result + """ + path = self.get_temp_path('1.original.flac') + ref_path = self.get_temp_path('2.reference.wav') + + # 1. Generate flac with sox + sox_utils.gen_audio_file( + path, sample_rate, num_channels, + compression=compression_level, bit_depth=16, duration=duration) + # 2. Convert to wav with sox + sox_utils.convert_audio_file(path, ref_path) + # 3. Load flac with torchaudio + data, sr = sox_io_backend.load(path) + # 4. Load wav with scipy + data_ref = load_wav(ref_path)[0] + # 5. Compare + assert sr == sample_rate + self.assertEqual(data, data_ref, atol=4e-05, rtol=1.3e-06) + + def assert_vorbis(self, sample_rate, num_channels, quality_level, duration): + """`sox_io_backend.load` can load vorbis format. + + This test takes the same strategy as mp3 to compare the result + """ + path = self.get_temp_path('1.original.vorbis') + ref_path = self.get_temp_path('2.reference.wav') + + # 1. Generate vorbis with sox + sox_utils.gen_audio_file( + path, sample_rate, num_channels, + compression=quality_level, bit_depth=16, duration=duration) + # 2. Convert to wav with sox + sox_utils.convert_audio_file(path, ref_path) + # 3. Load vorbis with torchaudio + data, sr = sox_io_backend.load(path) + # 4. Load wav with scipy + data_ref = load_wav(ref_path)[0] + # 5. Compare + assert sr == sample_rate + self.assertEqual(data, data_ref, atol=4e-05, rtol=1.3e-06) + + +@skipIfNoExec('sox') +@skipIfNoExtension +class TestLoad(LoadTestBase): + """Test the correctness of `sox_io_backend.load` for various formats""" + @parameterized.expand(list(itertools.product( + ['float32', 'int32', 'int16', 'uint8'], + [8000, 16000], + [1, 2], + [False, True], + )), name_func=name_func) + def test_wav(self, dtype, sample_rate, num_channels, normalize): + """`sox_io_backend.load` can load wav format correctly.""" + self.assert_wav(dtype, sample_rate, num_channels, normalize, duration=1) + + @parameterized.expand(list(itertools.product( + ['int16'], + [16000], + [2], + [False], + )), name_func=name_func) + def test_wav_large(self, dtype, sample_rate, num_channels, normalize): + """`sox_io_backend.load` can load large wav file correctly.""" + two_hours = 2 * 60 * 60 + self.assert_wav(dtype, sample_rate, num_channels, normalize, two_hours) + + @parameterized.expand(list(itertools.product( + ['float32', 'int32', 'int16', 'uint8'], + [4, 8, 16, 32], + )), name_func=name_func) + def test_multiple_channels(self, dtype, num_channels): + """`sox_io_backend.load` can load wav file with more than 2 channels.""" + sample_rate = 8000 + normalize = False + self.assert_wav(dtype, sample_rate, num_channels, normalize, duration=1) + + @parameterized.expand(list(itertools.product( + [8000, 16000, 44100], + [1, 2], + [96, 128, 160, 192, 224, 256, 320], + )), name_func=name_func) + def test_mp3(self, sample_rate, num_channels, bit_rate): + """`sox_io_backend.load` can load mp3 format correctly.""" + self.assert_mp3(sample_rate, num_channels, bit_rate, duration=1) + + @parameterized.expand(list(itertools.product( + [16000], + [2], + [128], + )), name_func=name_func) + def test_mp3_large(self, sample_rate, num_channels, bit_rate): + """`sox_io_backend.load` can load large mp3 file correctly.""" + two_hours = 2 * 60 * 60 + self.assert_mp3(sample_rate, num_channels, bit_rate, two_hours) + + @parameterized.expand(list(itertools.product( + [8000, 16000], + [1, 2], + list(range(9)), + )), name_func=name_func) + def test_flac(self, sample_rate, num_channels, compression_level): + """`sox_io_backend.load` can load flac format correctly.""" + self.assert_flac(sample_rate, num_channels, compression_level, duration=1) + + @parameterized.expand(list(itertools.product( + [16000], + [2], + [0], + )), name_func=name_func) + def test_flac_large(self, sample_rate, num_channels, compression_level): + """`sox_io_backend.load` can load large flac file correctly.""" + two_hours = 2 * 60 * 60 + self.assert_flac(sample_rate, num_channels, compression_level, two_hours) + + @parameterized.expand(list(itertools.product( + [8000, 16000], + [1, 2], + [-1, 0, 1, 2, 3, 3.6, 5, 10], + )), name_func=name_func) + def test_vorbis(self, sample_rate, num_channels, quality_level): + """`sox_io_backend.load` can load vorbis format correctly.""" + self.assert_vorbis(sample_rate, num_channels, quality_level, duration=1) + + @parameterized.expand(list(itertools.product( + [16000], + [2], + [10], + )), name_func=name_func) + def test_vorbis_large(self, sample_rate, num_channels, quality_level): + """`sox_io_backend.load` can load large vorbis file correctly.""" + two_hours = 2 * 60 * 60 + self.assert_vorbis(sample_rate, num_channels, quality_level, two_hours) + + @parameterized.expand(list(itertools.product( + ['96k'], + [1, 2], + [0, 5, 10], + )), name_func=name_func) + def test_opus(self, bitrate, num_channels, compression_level): + """`sox_io_backend.load` can load opus file correctly.""" + ops_path = get_asset_path('io', f'{bitrate}_{compression_level}_{num_channels}ch.opus') + wav_path = self.get_temp_path(f'{bitrate}_{compression_level}_{num_channels}ch.opus.wav') + sox_utils.convert_audio_file(ops_path, wav_path) + + expected, sample_rate = load_wav(wav_path) + found, sr = sox_io_backend.load(ops_path) + + assert sample_rate == sr + self.assertEqual(expected, found) + + +@skipIfNoExec('sox') +@skipIfNoExtension +class TestLoadParams(TempDirMixin, PytorchTestCase): + """Test the correctness of frame parameters of `sox_io_backend.load`""" + original = None + path = None + + def setUp(self): + super().setUp() + sample_rate = 8000 + self.original = get_wav_data('float32', num_channels=2) + self.path = self.get_temp_path('test.wave') + save_wav(self.path, self.original, sample_rate) + + @parameterized.expand(list(itertools.product( + [0, 1, 10, 100, 1000], + [-1, 1, 10, 100, 1000], + )), name_func=name_func) + def test_frame(self, frame_offset, num_frames): + """num_frames and frame_offset correctly specify the region of data""" + found, _ = sox_io_backend.load(self.path, frame_offset, num_frames) + frame_end = None if num_frames == -1 else frame_offset + num_frames + self.assertEqual(found, self.original[:, frame_offset:frame_end]) + + @parameterized.expand([(True, ), (False, )], name_func=name_func) + def test_channels_first(self, channels_first): + """channels_first swaps axes""" + found, _ = sox_io_backend.load(self.path, channels_first=channels_first) + expected = self.original if channels_first else self.original.transpose(1, 0) + self.assertEqual(found, expected) diff --git a/test/sox_io_backend/test_roundtrip.py b/test/sox_io_backend/test_roundtrip.py new file mode 100644 index 0000000000..2a051bebd5 --- /dev/null +++ b/test/sox_io_backend/test_roundtrip.py @@ -0,0 +1,52 @@ +import itertools + +from torchaudio.backend import sox_io_backend +from parameterized import parameterized + +from ..common_utils import ( + TempDirMixin, + PytorchTestCase, + skipIfNoExec, + skipIfNoExtension, + get_wav_data, +) +from .common import ( + name_func, +) + + +@skipIfNoExec('sox') +@skipIfNoExtension +class TestRoundTripIO(TempDirMixin, PytorchTestCase): + """save/load round trip should not degrade data for lossless formats""" + @parameterized.expand(list(itertools.product( + ['float32', 'int32', 'int16', 'uint8'], + [8000, 16000], + [1, 2], + )), name_func=name_func) + def test_wav(self, dtype, sample_rate, num_channels): + """save/load round trip should not degrade data for wav formats""" + original = get_wav_data(dtype, num_channels, normalize=False) + data = original + for i in range(10): + path = self.get_temp_path(f'{i}.wav') + sox_io_backend.save(path, data, sample_rate) + data, sr = sox_io_backend.load(path, normalize=False) + assert sr == sample_rate + self.assertEqual(original, data) + + @parameterized.expand(list(itertools.product( + [8000, 16000], + [1, 2], + list(range(9)), + )), name_func=name_func) + def test_flac(self, sample_rate, num_channels, compression_level): + """save/load round trip should not degrade data for flac formats""" + original = get_wav_data('float32', num_channels) + data = original + for i in range(10): + path = self.get_temp_path(f'{i}.flac') + sox_io_backend.save(path, data, sample_rate, compression=compression_level) + data, sr = sox_io_backend.load(path) + assert sr == sample_rate + self.assertEqual(original, data) diff --git a/test/sox_io_backend/test_save.py b/test/sox_io_backend/test_save.py new file mode 100644 index 0000000000..53588c456b --- /dev/null +++ b/test/sox_io_backend/test_save.py @@ -0,0 +1,304 @@ +import itertools + +from torchaudio.backend import sox_io_backend +from parameterized import parameterized + +from ..common_utils import ( + TempDirMixin, + PytorchTestCase, + skipIfNoExec, + skipIfNoExtension, + get_wav_data, + load_wav, + save_wav, + sox_utils, +) +from .common import ( + name_func, +) + + +class SaveTestBase(TempDirMixin, PytorchTestCase): + def assert_wav(self, dtype, sample_rate, num_channels, num_frames): + """`sox_io_backend.save` can save wav format.""" + path = self.get_temp_path('data.wav') + expected = get_wav_data(dtype, num_channels, num_frames=num_frames) + sox_io_backend.save(path, expected, sample_rate) + found, sr = load_wav(path) + assert sample_rate == sr + self.assertEqual(found, expected) + + def assert_mp3(self, sample_rate, num_channels, bit_rate, duration): + """`sox_io_backend.save` can save mp3 format. + + mp3 encoding introduces delay and boundary effects so + we convert the resulting mp3 to wav and compare the results there + + | + | 1. Generate original wav file with SciPy + | + v + -------------- wav ---------------- + | | + | 2.1. load with scipy | 3.1. Convert to mp3 with Sox + | then save with torchaudio | + v v + mp3 mp3 + | | + | 2.2. Convert to wav with Sox | 3.2. Convert to wav with Sox + | | + v v + wav wav + | | + | 2.3. load with scipy | 3.3. load with scipy + | | + v v + tensor -------> compare <--------- tensor + + """ + src_path = self.get_temp_path('1.reference.wav') + mp3_path = self.get_temp_path('2.1.torchaudio.mp3') + wav_path = self.get_temp_path('2.2.torchaudio.wav') + mp3_path_sox = self.get_temp_path('3.1.sox.mp3') + wav_path_sox = self.get_temp_path('3.2.sox.wav') + + # 1. Generate original wav + data = get_wav_data('float32', num_channels, normalize=True, num_frames=duration * sample_rate) + save_wav(src_path, data, sample_rate) + # 2.1. Convert the original wav to mp3 with torchaudio + sox_io_backend.save( + mp3_path, load_wav(src_path)[0], sample_rate, compression=bit_rate) + # 2.2. Convert the mp3 to wav with Sox + sox_utils.convert_audio_file(mp3_path, wav_path) + # 2.3. Load + found = load_wav(wav_path)[0] + + # 3.1. Convert the original wav to mp3 with SoX + sox_utils.convert_audio_file(src_path, mp3_path_sox, compression=bit_rate) + # 3.2. Convert the mp3 to wav with Sox + sox_utils.convert_audio_file(mp3_path_sox, wav_path_sox) + # 3.3. Load + expected = load_wav(wav_path_sox)[0] + + self.assertEqual(found, expected) + + def assert_flac(self, sample_rate, num_channels, compression_level, duration): + """`sox_io_backend.save` can save flac format. + + This test takes the same strategy as mp3 to compare the result + """ + src_path = self.get_temp_path('1.reference.wav') + flc_path = self.get_temp_path('2.1.torchaudio.flac') + wav_path = self.get_temp_path('2.2.torchaudio.wav') + flc_path_sox = self.get_temp_path('3.1.sox.flac') + wav_path_sox = self.get_temp_path('3.2.sox.wav') + + # 1. Generate original wav + data = get_wav_data('float32', num_channels, normalize=True, num_frames=duration * sample_rate) + save_wav(src_path, data, sample_rate) + # 2.1. Convert the original wav to flac with torchaudio + sox_io_backend.save( + flc_path, load_wav(src_path)[0], sample_rate, compression=compression_level) + # 2.2. Convert the flac to wav with Sox + # converting to 32 bit because flac file has 24 bit depth which scipy cannot handle. + sox_utils.convert_audio_file(flc_path, wav_path, bit_depth=32) + # 2.3. Load + found = load_wav(wav_path)[0] + + # 3.1. Convert the original wav to flac with SoX + sox_utils.convert_audio_file(src_path, flc_path_sox, compression=compression_level) + # 3.2. Convert the flac to wav with Sox + # converting to 32 bit because flac file has 24 bit depth which scipy cannot handle. + sox_utils.convert_audio_file(flc_path_sox, wav_path_sox, bit_depth=32) + # 3.3. Load + expected = load_wav(wav_path_sox)[0] + + self.assertEqual(found, expected) + + def _assert_vorbis(self, sample_rate, num_channels, quality_level, duration): + """`sox_io_backend.save` can save vorbis format. + + This test takes the same strategy as mp3 to compare the result + """ + src_path = self.get_temp_path('1.reference.wav') + vbs_path = self.get_temp_path('2.1.torchaudio.vorbis') + wav_path = self.get_temp_path('2.2.torchaudio.wav') + vbs_path_sox = self.get_temp_path('3.1.sox.vorbis') + wav_path_sox = self.get_temp_path('3.2.sox.wav') + + # 1. Generate original wav + data = get_wav_data('int16', num_channels, normalize=False, num_frames=duration * sample_rate) + save_wav(src_path, data, sample_rate) + # 2.1. Convert the original wav to vorbis with torchaudio + sox_io_backend.save( + vbs_path, load_wav(src_path)[0], sample_rate, compression=quality_level) + # 2.2. Convert the vorbis to wav with Sox + sox_utils.convert_audio_file(vbs_path, wav_path) + # 2.3. Load + found = load_wav(wav_path)[0] + + # 3.1. Convert the original wav to vorbis with SoX + sox_utils.convert_audio_file(src_path, vbs_path_sox, compression=quality_level) + # 3.2. Convert the vorbis to wav with Sox + sox_utils.convert_audio_file(vbs_path_sox, wav_path_sox) + # 3.3. Load + expected = load_wav(wav_path_sox)[0] + + # sox's vorbis encoding has some random boundary effect, which cause small number of + # samples yields higher descrepency than the others. + # so we allow small portions of data to be outside of absolute torelance. + # make sure to pass somewhat long duration + atol = 1.0e-4 + max_failure_allowed = 0.01 # this percent of samples are allowed to outside of atol. + failure_ratio = ((found - expected).abs() > atol).sum().item() / found.numel() + if failure_ratio > max_failure_allowed: + # it's failed and this will give a better error message. + self.assertEqual(found, expected, atol=atol, rtol=1.3e-6) + + def assert_vorbis(self, *args, **kwargs): + # sox's vorbis encoding has some randomness, so we run tests multiple time + max_retry = 5 + error = None + for _ in range(max_retry): + try: + self._assert_vorbis(*args, **kwargs) + break + except AssertionError as e: + error = e + else: + raise error + + +@skipIfNoExec('sox') +@skipIfNoExtension +class TestSave(SaveTestBase): + @parameterized.expand(list(itertools.product( + ['float32', 'int32', 'int16', 'uint8'], + [8000, 16000], + [1, 2], + )), name_func=name_func) + def test_wav(self, dtype, sample_rate, num_channels): + """`sox_io_backend.save` can save wav format.""" + self.assert_wav(dtype, sample_rate, num_channels, num_frames=None) + + @parameterized.expand(list(itertools.product( + ['float32'], + [16000], + [2], + )), name_func=name_func) + def test_wav_large(self, dtype, sample_rate, num_channels): + """`sox_io_backend.save` can save large wav file.""" + two_hours = 2 * 60 * 60 * sample_rate + self.assert_wav(dtype, sample_rate, num_channels, num_frames=two_hours) + + @parameterized.expand(list(itertools.product( + ['float32', 'int32', 'int16', 'uint8'], + [4, 8, 16, 32], + )), name_func=name_func) + def test_multiple_channels(self, dtype, num_channels): + """`sox_io_backend.save` can save wav with more than 2 channels.""" + sample_rate = 8000 + self.assert_wav(dtype, sample_rate, num_channels, num_frames=None) + + @parameterized.expand(list(itertools.product( + [8000, 16000], + [1, 2], + [-4.2, -0.2, 0, 0.2, 96, 128, 160, 192, 224, 256, 320], + )), name_func=name_func) + def test_mp3(self, sample_rate, num_channels, bit_rate): + """`sox_io_backend.save` can save mp3 format.""" + self.assert_mp3(sample_rate, num_channels, bit_rate, duration=1) + + @parameterized.expand(list(itertools.product( + [16000], + [2], + [128], + )), name_func=name_func) + def test_mp3_large(self, sample_rate, num_channels, bit_rate): + """`sox_io_backend.save` can save large mp3 file.""" + two_hours = 2 * 60 * 60 + self.assert_mp3(sample_rate, num_channels, bit_rate, duration=two_hours) + + @parameterized.expand(list(itertools.product( + [8000, 16000], + [1, 2], + list(range(9)), + )), name_func=name_func) + def test_flac(self, sample_rate, num_channels, compression_level): + """`sox_io_backend.save` can save flac format.""" + self.assert_flac(sample_rate, num_channels, compression_level, duration=1) + + @parameterized.expand(list(itertools.product( + [16000], + [2], + [0], + )), name_func=name_func) + def test_flac_large(self, sample_rate, num_channels, compression_level): + """`sox_io_backend.save` can save large flac file.""" + two_hours = 2 * 60 * 60 + self.assert_flac(sample_rate, num_channels, compression_level, duration=two_hours) + + @parameterized.expand(list(itertools.product( + [8000, 16000], + [1, 2], + [-1, 0, 1, 2, 3, 3.6, 5, 10], + )), name_func=name_func) + def test_vorbis(self, sample_rate, num_channels, quality_level): + """`sox_io_backend.save` can save vorbis format.""" + self.assert_vorbis(sample_rate, num_channels, quality_level, duration=20) + + # note: torchaudio can load large vorbis file, but cannot save large volbis file + # the following test causes Segmentation fault + # + ''' + @parameterized.expand(list(itertools.product( + [16000], + [2], + [10], + )), name_func=name_func) + def test_vorbis_large(self, sample_rate, num_channels, quality_level): + """`sox_io_backend.save` can save large vorbis file correctly.""" + two_hours = 2 * 60 * 60 + self.assert_vorbis(sample_rate, num_channels, quality_level, two_hours) + ''' + + +@skipIfNoExec('sox') +@skipIfNoExtension +class TestSaveParams(TempDirMixin, PytorchTestCase): + """Test the correctness of optional parameters of `sox_io_backend.save`""" + @parameterized.expand([(True, ), (False, )], name_func=name_func) + def test_channels_first(self, channels_first): + """channels_first swaps axes""" + path = self.get_temp_path('data.wav') + data = get_wav_data('int32', 2, channels_first=channels_first) + sox_io_backend.save( + path, data, 8000, channels_first=channels_first) + found = load_wav(path)[0] + expected = data if channels_first else data.transpose(1, 0) + self.assertEqual(found, expected) + + @parameterized.expand([ + 'float32', 'int32', 'int16', 'uint8' + ], name_func=name_func) + def test_noncontiguous(self, dtype): + """Noncontiguous tensors are saved correctly""" + path = self.get_temp_path('data.wav') + expected = get_wav_data(dtype, 4)[::2, ::2] + assert not expected.is_contiguous() + sox_io_backend.save(path, expected, 8000) + found = load_wav(path)[0] + self.assertEqual(found, expected) + + @parameterized.expand([ + 'float32', 'int32', 'int16', 'uint8', + ]) + def test_tensor_preserve(self, dtype): + """save function should not alter Tensor""" + path = self.get_temp_path('data.wav') + expected = get_wav_data(dtype, 4)[::2, ::2] + + data = expected.clone() + sox_io_backend.save(path, data, 8000) + + self.assertEqual(data, expected) diff --git a/test/sox_io_backend/test_torchscript.py b/test/sox_io_backend/test_torchscript.py new file mode 100644 index 0000000000..9a30aab0d2 --- /dev/null +++ b/test/sox_io_backend/test_torchscript.py @@ -0,0 +1,149 @@ +import itertools +from typing import Optional + +import torch +import torchaudio +from parameterized import parameterized + +from ..common_utils import ( + TempDirMixin, + TorchaudioTestCase, + skipIfNoExec, + skipIfNoExtension, + get_wav_data, + save_wav, + load_wav, + sox_utils, +) +from .common import ( + name_func, +) + + +def py_info_func(filepath: str) -> torchaudio.backend.sox_io_backend.AudioMetaData: + return torchaudio.info(filepath) + + +def py_load_func(filepath: str, normalize: bool, channels_first: bool): + return torchaudio.load( + filepath, normalize=normalize, channels_first=channels_first) + + +def py_save_func( + filepath: str, + tensor: torch.Tensor, + sample_rate: int, + channels_first: bool = True, + compression: Optional[float] = None, +): + torchaudio.save(filepath, tensor, sample_rate, channels_first, compression) + + +@skipIfNoExec('sox') +@skipIfNoExtension +class SoxIO(TempDirMixin, TorchaudioTestCase): + """TorchScript-ability Test suite for `sox_io_backend`""" + backend = 'sox_io' + + @parameterized.expand(list(itertools.product( + ['float32', 'int32', 'int16', 'uint8'], + [8000, 16000], + [1, 2], + )), name_func=name_func) + def test_info_wav(self, dtype, sample_rate, num_channels): + """`sox_io_backend.info` is torchscript-able and returns the same result""" + audio_path = self.get_temp_path(f'{dtype}_{sample_rate}_{num_channels}.wav') + data = get_wav_data(dtype, num_channels, normalize=False, num_frames=1 * sample_rate) + save_wav(audio_path, data, sample_rate) + + script_path = self.get_temp_path('info_func.zip') + torch.jit.script(py_info_func).save(script_path) + ts_info_func = torch.jit.load(script_path) + + py_info = py_info_func(audio_path) + ts_info = ts_info_func(audio_path) + + assert py_info.sample_rate == ts_info.sample_rate + assert py_info.num_frames == ts_info.num_frames + assert py_info.num_channels == ts_info.num_channels + + @parameterized.expand(list(itertools.product( + ['float32', 'int32', 'int16', 'uint8'], + [8000, 16000], + [1, 2], + [False, True], + [False, True], + )), name_func=name_func) + def test_load_wav(self, dtype, sample_rate, num_channels, normalize, channels_first): + """`sox_io_backend.load` is torchscript-able and returns the same result""" + audio_path = self.get_temp_path(f'test_load_{dtype}_{sample_rate}_{num_channels}_{normalize}.wav') + data = get_wav_data(dtype, num_channels, normalize=False, num_frames=1 * sample_rate) + save_wav(audio_path, data, sample_rate) + + script_path = self.get_temp_path('load_func.zip') + torch.jit.script(py_load_func).save(script_path) + ts_load_func = torch.jit.load(script_path) + + py_data, py_sr = py_load_func( + audio_path, normalize=normalize, channels_first=channels_first) + ts_data, ts_sr = ts_load_func( + audio_path, normalize=normalize, channels_first=channels_first) + + self.assertEqual(py_sr, ts_sr) + self.assertEqual(py_data, ts_data) + + @parameterized.expand(list(itertools.product( + ['float32', 'int32', 'int16', 'uint8'], + [8000, 16000], + [1, 2], + )), name_func=name_func) + def test_save_wav(self, dtype, sample_rate, num_channels): + script_path = self.get_temp_path('save_func.zip') + torch.jit.script(py_save_func).save(script_path) + ts_save_func = torch.jit.load(script_path) + + expected = get_wav_data(dtype, num_channels) + py_path = self.get_temp_path(f'test_save_py_{dtype}_{sample_rate}_{num_channels}.wav') + ts_path = self.get_temp_path(f'test_save_ts_{dtype}_{sample_rate}_{num_channels}.wav') + + py_save_func(py_path, expected, sample_rate, True, None) + ts_save_func(ts_path, expected, sample_rate, True, None) + + py_data, py_sr = load_wav(py_path) + ts_data, ts_sr = load_wav(ts_path) + + self.assertEqual(sample_rate, py_sr) + self.assertEqual(sample_rate, ts_sr) + self.assertEqual(expected, py_data) + self.assertEqual(expected, ts_data) + + @parameterized.expand(list(itertools.product( + [8000, 16000], + [1, 2], + list(range(9)), + )), name_func=name_func) + def test_save_flac(self, sample_rate, num_channels, compression_level): + script_path = self.get_temp_path('save_func.zip') + torch.jit.script(py_save_func).save(script_path) + ts_save_func = torch.jit.load(script_path) + + expected = get_wav_data('float32', num_channels) + py_path = self.get_temp_path(f'test_save_py_{sample_rate}_{num_channels}_{compression_level}.flac') + ts_path = self.get_temp_path(f'test_save_ts_{sample_rate}_{num_channels}_{compression_level}.flac') + + py_save_func(py_path, expected, sample_rate, True, compression_level) + ts_save_func(ts_path, expected, sample_rate, True, compression_level) + + # converting to 32 bit because flac file has 24 bit depth which scipy cannot handle. + py_path_wav = f'{py_path}.wav' + ts_path_wav = f'{ts_path}.wav' + sox_utils.convert_audio_file(py_path, py_path_wav, bit_depth=32) + sox_utils.convert_audio_file(ts_path, ts_path_wav, bit_depth=32) + + py_data, py_sr = load_wav(py_path_wav, normalize=True) + ts_data, ts_sr = load_wav(ts_path_wav, normalize=True) + + self.assertEqual(sample_rate, py_sr) + self.assertEqual(sample_rate, ts_sr) + self.assertEqual(expected, py_data) + self.assertEqual(expected, ts_data) diff --git a/test/test_backend.py b/test/test_backend.py index 1e8f9e4fd6..6b67cb2898 100644 --- a/test/test_backend.py +++ b/test/test_backend.py @@ -1,7 +1,4 @@ -import unittest - import torchaudio -from torchaudio._internal.module_utils import is_module_available from . import common_utils @@ -28,15 +25,19 @@ class TestBackendSwitch_NoBackend(BackendSwitchMixin, common_utils.TorchaudioTes backend_module = torchaudio.backend.no_backend -@unittest.skipIf( - not is_module_available('torchaudio._torchaudio'), - 'torchaudio C++ extension not available') +@common_utils.skipIfNoExtension class TestBackendSwitch_SoX(BackendSwitchMixin, common_utils.TorchaudioTestCase): backend = 'sox' backend_module = torchaudio.backend.sox_backend -@unittest.skipIf(not is_module_available('soundfile'), '"soundfile" not available') +@common_utils.skipIfNoExtension +class TestBackendSwitch_SoXIO(BackendSwitchMixin, common_utils.TorchaudioTestCase): + backend = 'sox_io' + backend_module = torchaudio.backend.sox_io_backend + + +@common_utils.skipIfNoModule('soundfile') class TestBackendSwitch_soundfile(BackendSwitchMixin, common_utils.TorchaudioTestCase): backend = 'soundfile' backend_module = torchaudio.backend.soundfile_backend diff --git a/test/test_datasets.py b/test/test_datasets.py index 3ac7fae8ac..c3b0c917da 100644 --- a/test/test_datasets.py +++ b/test/test_datasets.py @@ -46,9 +46,8 @@ def test_cmuarctic(self): data[0] -@common_utils.skipIfNoSoxBackend class TestCommonVoice(common_utils.TorchaudioTestCase): - backend = 'sox' + backend = 'default' path = common_utils.get_asset_path() def test_commonvoice(self): diff --git a/test/test_io.py b/test/test_io.py index f58f66ed11..2c8aece85e 100644 --- a/test/test_io.py +++ b/test/test_io.py @@ -1,11 +1,24 @@ import os import math +import shutil +import tempfile import unittest import torch import torchaudio -from .common_utils import BACKENDS, BACKENDS_MP3, create_temp_assets_dir +from .common_utils import BACKENDS, BACKENDS_MP3, get_asset_path + + +def create_temp_assets_dir(): + """ + Creates a temporary directory and moves all files from test/assets there. + Returns a Tuple[string, TemporaryDirectory] which is the folder path + and object. + """ + tmp_dir = tempfile.TemporaryDirectory() + shutil.copytree(get_asset_path(), os.path.join(tmp_dir.name, "assets")) + return tmp_dir.name, tmp_dir class Test_LoadSave(unittest.TestCase): @@ -17,11 +30,15 @@ class Test_LoadSave(unittest.TestCase): def test_1_save(self): for backend in BACKENDS_MP3: + if backend == 'sox_io': + continue with self.subTest(): torchaudio.set_audio_backend(backend) self._test_1_save(self.test_filepath, False) for backend in BACKENDS: + if backend == 'sox_io': + continue with self.subTest(): torchaudio.set_audio_backend(backend) self._test_1_save(self.test_filepath_wav, True) @@ -68,6 +85,8 @@ def _test_1_save(self, test_filepath, normalization): def test_1_save_sine(self): for backend in BACKENDS: + if backend == 'sox_io': + continue with self.subTest(): torchaudio.set_audio_backend(backend) self._test_1_save_sine() @@ -101,11 +120,15 @@ def _test_1_save_sine(self): def test_2_load(self): for backend in BACKENDS_MP3: + if backend == 'sox_io': + continue with self.subTest(): torchaudio.set_audio_backend(backend) self._test_2_load(self.test_filepath, 278756) for backend in BACKENDS: + if backend == 'sox_io': + continue with self.subTest(): torchaudio.set_audio_backend(backend) self._test_2_load(self.test_filepath_wav, 276858) @@ -142,6 +165,8 @@ def _test_2_load(self, test_filepath, length): def test_2_load_nonormalization(self): for backend in BACKENDS_MP3: + if backend == 'sox_io': + continue with self.subTest(): torchaudio.set_audio_backend(backend) self._test_2_load_nonormalization(self.test_filepath, 278756) @@ -159,6 +184,8 @@ def _test_2_load_nonormalization(self, test_filepath, length): def test_3_load_and_save_is_identity(self): for backend in BACKENDS: + if backend == 'sox_io': + continue with self.subTest(): torchaudio.set_audio_backend(backend) self._test_3_load_and_save_is_identity() @@ -197,6 +224,8 @@ def _test_3_load_and_save_is_identity_across_backend(self, backend1, backend2): def test_4_load_partial(self): for backend in BACKENDS_MP3: + if backend == 'sox_io': + continue with self.subTest(): torchaudio.set_audio_backend(backend) self._test_4_load_partial() @@ -239,6 +268,8 @@ def _test_4_load_partial(self): def test_5_get_info(self): for backend in BACKENDS: + if backend == 'sox_io': + continue with self.subTest(): torchaudio.set_audio_backend(backend) self._test_5_get_info() diff --git a/test/test_librosa_compatibility.py b/test/test_librosa_compatibility.py index 62e9d3ca88..aa933535e8 100644 --- a/test/test_librosa_compatibility.py +++ b/test/test_librosa_compatibility.py @@ -160,7 +160,8 @@ class TestTransforms(common_utils.TorchaudioTestCase): """Test suite for functions in `transforms` module.""" def assert_compatibilities(self, n_fft, hop_length, power, n_mels, n_mfcc, sample_rate): common_utils.set_audio_backend('default') - sound, sample_rate = _load_audio_asset('sinewave.wav') + path = common_utils.get_asset_path('sinewave.wav') + sound, sample_rate = common_utils.load_wav(path) sound_librosa = sound.cpu().numpy().squeeze() # (64000) # test core spectrogram @@ -300,9 +301,9 @@ def test_InverseMelScale(self): hop_length = n_fft // 4 # Prepare mel spectrogram input. We use torchaudio to compute one. - common_utils.set_audio_backend('default') - sound, sample_rate = _load_audio_asset( - 'steam-train-whistle-daniel_simon.wav', offset=2**10, num_frames=2**14) + path = common_utils.get_asset_path('steam-train-whistle-daniel_simon.wav') + sound, sample_rate = common_utils.load_wav(path) + sound = sound[:, 2**10:2**10 + 2**14] sound = sound.mean(dim=0, keepdim=True) spec_orig = F.spectrogram( sound, pad=0, window=torch.hann_window(n_fft), n_fft=n_fft, diff --git a/test/test_models.py b/test/test_models.py index 7bd3f3819d..c54a57cebd 100644 --- a/test/test_models.py +++ b/test/test_models.py @@ -1,8 +1,10 @@ import torch -from torchaudio.models import Wav2Letter, _MelResNet +from torchaudio.models import Wav2Letter, _MelResNet, _UpsampleNetwork, _WaveRNN +from . import common_utils -class TestWav2Letter: + +class TestWav2Letter(common_utils.TorchaudioTestCase): def test_waveform(self): batch_size = 2 @@ -31,21 +33,110 @@ def test_mfcc(self): assert out.size() == (batch_size, num_classes, 2) -class TestMelResNet: +class TestMelResNet(common_utils.TorchaudioTestCase): def test_waveform(self): + """Validate the output dimensions of a _MelResNet block. + """ - batch_size = 2 - num_features = 200 - input_dims = 100 - output_dims = 128 - res_blocks = 10 - hidden_dims = 128 - pad = 2 + n_batch = 2 + n_time = 200 + n_freq = 100 + n_output = 128 + n_res_block = 10 + n_hidden = 128 + kernel_size = 5 - model = _MelResNet(res_blocks, input_dims, hidden_dims, output_dims, pad) + model = _MelResNet(n_res_block, n_freq, n_hidden, n_output, kernel_size) - x = torch.rand(batch_size, input_dims, num_features) + x = torch.rand(n_batch, n_freq, n_time) out = model(x) - assert out.size() == (batch_size, output_dims, num_features - pad * 2) + assert out.size() == (n_batch, n_output, n_time - kernel_size + 1) + + +class TestUpsampleNetwork(common_utils.TorchaudioTestCase): + + def test_waveform(self): + """Validate the output dimensions of a _UpsampleNetwork block. + """ + + upsample_scales = [5, 5, 8] + n_batch = 2 + n_time = 200 + n_freq = 100 + n_output = 256 + n_res_block = 10 + n_hidden = 128 + kernel_size = 5 + + total_scale = 1 + for upsample_scale in upsample_scales: + total_scale *= upsample_scale + + model = _UpsampleNetwork(upsample_scales, n_res_block, n_freq, n_hidden, n_output, kernel_size) + + x = torch.rand(n_batch, n_freq, n_time) + out1, out2 = model(x) + + assert out1.size() == (n_batch, n_freq, total_scale * (n_time - kernel_size + 1)) + assert out2.size() == (n_batch, n_output, total_scale * (n_time - kernel_size + 1)) + + +class TestWaveRNN(common_utils.TorchaudioTestCase): + + def test_waveform(self): + """Validate the output dimensions of a _WaveRNN model in waveform mode. + """ + + upsample_scales = [5, 5, 8] + n_rnn = 512 + n_fc = 512 + n_bits = 9 + sample_rate = 24000 + hop_length = 200 + n_batch = 2 + n_time = 200 + n_freq = 100 + n_output = 256 + n_res_block = 10 + n_hidden = 128 + kernel_size = 5 + mode = 'waveform' + + model = _WaveRNN(upsample_scales, n_bits, sample_rate, hop_length, n_res_block, + n_rnn, n_fc, kernel_size, n_freq, n_hidden, n_output, mode) + + x = torch.rand(n_batch, 1, hop_length * (n_time - kernel_size + 1)) + mels = torch.rand(n_batch, 1, n_freq, n_time) + out = model(x, mels) + + assert out.size() == (n_batch, 1, hop_length * (n_time - kernel_size + 1), 2 ** n_bits) + + def test_mol(self): + """Validate the output dimensions of a _WaveRNN model in mol mode. + """ + + upsample_scales = [5, 5, 8] + n_rnn = 512 + n_fc = 512 + n_bits = 9 + sample_rate = 24000 + hop_length = 200 + n_batch = 2 + n_time = 200 + n_freq = 100 + n_output = 256 + n_res_block = 10 + n_hidden = 128 + kernel_size = 5 + mode = 'mol' + + model = _WaveRNN(upsample_scales, n_bits, sample_rate, hop_length, n_res_block, + n_rnn, n_fc, kernel_size, n_freq, n_hidden, n_output, mode) + + x = torch.rand(n_batch, 1, hop_length * (n_time - kernel_size + 1)) + mels = torch.rand(n_batch, 1, n_freq, n_time) + out = model(x, mels) + + assert out.size() == (n_batch, 1, hop_length * (n_time - kernel_size + 1), 30) diff --git a/test/test_sox_compatibility.py b/test/test_sox_compatibility.py index 23d58a3fb1..a5d9f8633c 100644 --- a/test/test_sox_compatibility.py +++ b/test/test_sox_compatibility.py @@ -9,12 +9,30 @@ @common_utils.skipIfNoSoxBackend -class TestFunctionalFiltering(common_utils.TorchaudioTestCase): +class TestFunctionalFiltering(common_utils.TempDirMixin, common_utils.TorchaudioTestCase): backend = 'sox' + def setUp(self): + # 1. Create int16 signal to save as PCM wav + # 2. Write to temp file + # 3. Load temp file into tensor to reuse in downstream tests + # Prefer to use common_utils.load_wav() but this implementation does + # not match torchaudio.load and errors on downstream tests + super().setUp() + + self.NOISE_SAMPLE_RATE = 44100 # N.B. 44.1 kHz required by SoX deemph effect + noise_waveform_as_int = common_utils.get_whitenoise( + sample_rate=self.NOISE_SAMPLE_RATE, duration=5, dtype=torch.int16, scale_factor=0.9, + ) + self.noise_filepath = self.get_temp_path("whitenoise.wav") + common_utils.save_wav( + self.noise_filepath, noise_waveform_as_int, self.NOISE_SAMPLE_RATE + ) + self.noise_waveform, _ = torchaudio.load(self.noise_filepath, normalization=True) + def test_gain(self): test_filepath = common_utils.get_asset_path('steam-train-whistle-daniel_simon.wav') - waveform, _ = torchaudio.load(test_filepath) + waveform, _ = common_utils.load_wav(test_filepath) waveform_gain = F.gain(waveform, 3) self.assertTrue(waveform_gain.abs().max().item(), 1.) @@ -28,7 +46,7 @@ def test_gain(self): def test_dither(self): test_filepath = common_utils.get_asset_path('steam-train-whistle-daniel_simon.wav') - waveform, _ = torchaudio.load(test_filepath) + waveform, _ = common_utils.load_wav(test_filepath) waveform_dithered = F.dither(waveform) waveform_dithered_noiseshaped = F.dither(waveform, noise_shaping=True) @@ -48,7 +66,7 @@ def test_dither(self): def test_vctk_transform_pipeline(self): test_filepath_vctk = common_utils.get_asset_path('VCTK-Corpus', 'wav48', 'p224', 'p224_002.wav') - wf_vctk, sr_vctk = torchaudio.load(test_filepath_vctk) + wf_vctk, sr_vctk = common_utils.load_wav(test_filepath_vctk) # rate sample = T.Resample(sr_vctk, 16000, resampling_method='sinc_interpolation') @@ -71,17 +89,14 @@ def test_lowpass(self): """ Test biquad lowpass filter, compare to SoX implementation """ - cutoff_freq = 3000 - noise_filepath = common_utils.get_asset_path('whitenoise.wav') E = torchaudio.sox_effects.SoxEffectsChain() - E.set_input_file(noise_filepath) + E.set_input_file(self.noise_filepath) E.append_effect_to_chain("lowpass", [cutoff_freq]) sox_output_waveform, sr = E.sox_build_flow_effects() - waveform, sample_rate = torchaudio.load(noise_filepath, normalization=True) - output_waveform = F.lowpass_biquad(waveform, sample_rate, cutoff_freq) + output_waveform = F.lowpass_biquad(self.noise_waveform, self.NOISE_SAMPLE_RATE, cutoff_freq) self.assertEqual(output_waveform, sox_output_waveform, atol=1e-4, rtol=1e-5) @@ -89,37 +104,30 @@ def test_highpass(self): """ Test biquad highpass filter, compare to SoX implementation """ - cutoff_freq = 2000 - noise_filepath = common_utils.get_asset_path('whitenoise.wav') E = torchaudio.sox_effects.SoxEffectsChain() - E.set_input_file(noise_filepath) + E.set_input_file(self.noise_filepath) E.append_effect_to_chain("highpass", [cutoff_freq]) sox_output_waveform, sr = E.sox_build_flow_effects() - waveform, sample_rate = torchaudio.load(noise_filepath, normalization=True) - output_waveform = F.highpass_biquad(waveform, sample_rate, cutoff_freq) + output_waveform = F.highpass_biquad(self.noise_waveform, self.NOISE_SAMPLE_RATE, cutoff_freq) - # TBD - this fails at the 1e-4 level, debug why - self.assertEqual(output_waveform, sox_output_waveform, atol=1e-3, rtol=1e-5) + self.assertEqual(output_waveform, sox_output_waveform, atol=1.5e-3, rtol=1e-5) def test_allpass(self): """ Test biquad allpass filter, compare to SoX implementation """ - central_freq = 1000 q = 0.707 - noise_filepath = common_utils.get_asset_path('whitenoise.wav') E = torchaudio.sox_effects.SoxEffectsChain() - E.set_input_file(noise_filepath) + E.set_input_file(self.noise_filepath) E.append_effect_to_chain("allpass", [central_freq, str(q) + 'q']) sox_output_waveform, sr = E.sox_build_flow_effects() - waveform, sample_rate = torchaudio.load(noise_filepath, normalization=True) - output_waveform = F.allpass_biquad(waveform, sample_rate, central_freq, q) + output_waveform = F.allpass_biquad(self.noise_waveform, self.NOISE_SAMPLE_RATE, central_freq, q) self.assertEqual(output_waveform, sox_output_waveform, atol=1e-4, rtol=1e-5) @@ -127,19 +135,17 @@ def test_bandpass_with_csg(self): """ Test biquad bandpass filter, compare to SoX implementation """ - central_freq = 1000 q = 0.707 const_skirt_gain = True - noise_filepath = common_utils.get_asset_path('whitenoise.wav') E = torchaudio.sox_effects.SoxEffectsChain() - E.set_input_file(noise_filepath) + E.set_input_file(self.noise_filepath) E.append_effect_to_chain("bandpass", ["-c", central_freq, str(q) + 'q']) sox_output_waveform, sr = E.sox_build_flow_effects() - waveform, sample_rate = torchaudio.load(noise_filepath, normalization=True) - output_waveform = F.bandpass_biquad(waveform, sample_rate, central_freq, q, const_skirt_gain) + output_waveform = F.bandpass_biquad(self.noise_waveform, self.NOISE_SAMPLE_RATE, + central_freq, q, const_skirt_gain) self.assertEqual(output_waveform, sox_output_waveform, atol=1e-4, rtol=1e-5) @@ -147,19 +153,17 @@ def test_bandpass_without_csg(self): """ Test biquad bandpass filter, compare to SoX implementation """ - central_freq = 1000 q = 0.707 const_skirt_gain = False - noise_filepath = common_utils.get_asset_path('whitenoise.wav') E = torchaudio.sox_effects.SoxEffectsChain() - E.set_input_file(noise_filepath) + E.set_input_file(self.noise_filepath) E.append_effect_to_chain("bandpass", [central_freq, str(q) + 'q']) sox_output_waveform, sr = E.sox_build_flow_effects() - waveform, sample_rate = torchaudio.load(noise_filepath, normalization=True) - output_waveform = F.bandpass_biquad(waveform, sample_rate, central_freq, q, const_skirt_gain) + output_waveform = F.bandpass_biquad(self.noise_waveform, self.NOISE_SAMPLE_RATE, + central_freq, q, const_skirt_gain) self.assertEqual(output_waveform, sox_output_waveform, atol=1e-4, rtol=1e-5) @@ -167,18 +171,16 @@ def test_bandreject(self): """ Test biquad bandreject filter, compare to SoX implementation """ - central_freq = 1000 q = 0.707 - noise_filepath = common_utils.get_asset_path('whitenoise.wav') E = torchaudio.sox_effects.SoxEffectsChain() - E.set_input_file(noise_filepath) + E.set_input_file(self.noise_filepath) E.append_effect_to_chain("bandreject", [central_freq, str(q) + 'q']) sox_output_waveform, sr = E.sox_build_flow_effects() - waveform, sample_rate = torchaudio.load(noise_filepath, normalization=True) - output_waveform = F.bandreject_biquad(waveform, sample_rate, central_freq, q) + output_waveform = F.bandreject_biquad(self.noise_waveform, self.NOISE_SAMPLE_RATE, + central_freq, q) self.assertEqual(output_waveform, sox_output_waveform, atol=1e-4, rtol=1e-5) @@ -186,19 +188,16 @@ def test_band_with_noise(self): """ Test biquad band filter with noise mode, compare to SoX implementation """ - central_freq = 1000 q = 0.707 noise = True - noise_filepath = common_utils.get_asset_path('whitenoise.wav') E = torchaudio.sox_effects.SoxEffectsChain() - E.set_input_file(noise_filepath) + E.set_input_file(self.noise_filepath) E.append_effect_to_chain("band", ["-n", central_freq, str(q) + 'q']) sox_output_waveform, sr = E.sox_build_flow_effects() - waveform, sample_rate = torchaudio.load(noise_filepath, normalization=True) - output_waveform = F.band_biquad(waveform, sample_rate, central_freq, q, noise) + output_waveform = F.band_biquad(self.noise_waveform, self.NOISE_SAMPLE_RATE, central_freq, q, noise) self.assertEqual(output_waveform, sox_output_waveform, atol=1e-4, rtol=1e-5) @@ -211,14 +210,12 @@ def test_band_without_noise(self): q = 0.707 noise = False - noise_filepath = common_utils.get_asset_path('whitenoise.wav') E = torchaudio.sox_effects.SoxEffectsChain() - E.set_input_file(noise_filepath) + E.set_input_file(self.noise_filepath) E.append_effect_to_chain("band", [central_freq, str(q) + 'q']) sox_output_waveform, sr = E.sox_build_flow_effects() - waveform, sample_rate = torchaudio.load(noise_filepath, normalization=True) - output_waveform = F.band_biquad(waveform, sample_rate, central_freq, q, noise) + output_waveform = F.band_biquad(self.noise_waveform, self.NOISE_SAMPLE_RATE, central_freq, q, noise) self.assertEqual(output_waveform, sox_output_waveform, atol=1e-4, rtol=1e-5) @@ -231,14 +228,12 @@ def test_treble(self): q = 0.707 gain = 40 - noise_filepath = common_utils.get_asset_path('whitenoise.wav') E = torchaudio.sox_effects.SoxEffectsChain() - E.set_input_file(noise_filepath) + E.set_input_file(self.noise_filepath) E.append_effect_to_chain("treble", [gain, central_freq, str(q) + 'q']) sox_output_waveform, sr = E.sox_build_flow_effects() - waveform, sample_rate = torchaudio.load(noise_filepath, normalization=True) - output_waveform = F.treble_biquad(waveform, sample_rate, gain, central_freq, q) + output_waveform = F.treble_biquad(self.noise_waveform, self.NOISE_SAMPLE_RATE, gain, central_freq, q) self.assertEqual(output_waveform, sox_output_waveform, atol=1e-4, rtol=1e-5) @@ -251,14 +246,12 @@ def test_bass(self): q = 0.707 gain = 40 - noise_filepath = common_utils.get_asset_path('whitenoise.wav') E = torchaudio.sox_effects.SoxEffectsChain() - E.set_input_file(noise_filepath) + E.set_input_file(self.noise_filepath) E.append_effect_to_chain("bass", [gain, central_freq, str(q) + 'q']) sox_output_waveform, sr = E.sox_build_flow_effects() - waveform, sample_rate = torchaudio.load(noise_filepath, normalization=True) - output_waveform = F.bass_biquad(waveform, sample_rate, gain, central_freq, q) + output_waveform = F.bass_biquad(self.noise_waveform, self.NOISE_SAMPLE_RATE, gain, central_freq, q) self.assertEqual(output_waveform, sox_output_waveform, atol=1.5e-4, rtol=1e-5) @@ -266,15 +259,12 @@ def test_deemph(self): """ Test biquad deemph filter, compare to SoX implementation """ - - noise_filepath = common_utils.get_asset_path('whitenoise.wav') E = torchaudio.sox_effects.SoxEffectsChain() - E.set_input_file(noise_filepath) + E.set_input_file(self.noise_filepath) E.append_effect_to_chain("deemph") sox_output_waveform, sr = E.sox_build_flow_effects() - waveform, sample_rate = torchaudio.load(noise_filepath, normalization=True) - output_waveform = F.deemph_biquad(waveform, sample_rate) + output_waveform = F.deemph_biquad(self.noise_waveform, self.NOISE_SAMPLE_RATE) self.assertEqual(output_waveform, sox_output_waveform, atol=1e-4, rtol=1e-5) @@ -282,15 +272,12 @@ def test_riaa(self): """ Test biquad riaa filter, compare to SoX implementation """ - - noise_filepath = common_utils.get_asset_path('whitenoise.wav') E = torchaudio.sox_effects.SoxEffectsChain() - E.set_input_file(noise_filepath) + E.set_input_file(self.noise_filepath) E.append_effect_to_chain("riaa") sox_output_waveform, sr = E.sox_build_flow_effects() - waveform, sample_rate = torchaudio.load(noise_filepath, normalization=True) - output_waveform = F.riaa_biquad(waveform, sample_rate) + output_waveform = F.riaa_biquad(self.noise_waveform, self.NOISE_SAMPLE_RATE) self.assertEqual(output_waveform, sox_output_waveform, atol=1e-4, rtol=1e-5) @@ -299,14 +286,13 @@ def test_contrast(self): Test contrast effect, compare to SoX implementation """ enhancement_amount = 80. - noise_filepath = common_utils.get_asset_path('whitenoise.wav') + E = torchaudio.sox_effects.SoxEffectsChain() - E.set_input_file(noise_filepath) + E.set_input_file(self.noise_filepath) E.append_effect_to_chain("contrast", [enhancement_amount]) sox_output_waveform, sr = E.sox_build_flow_effects() - waveform, sample_rate = torchaudio.load(noise_filepath, normalization=True) - output_waveform = F.contrast(waveform, enhancement_amount) + output_waveform = F.contrast(self.noise_waveform, enhancement_amount) self.assertEqual(output_waveform, sox_output_waveform, atol=1e-4, rtol=1e-5) @@ -316,14 +302,13 @@ def test_dcshift_with_limiter(self): """ shift = 0.5 limiter_gain = 0.05 - noise_filepath = common_utils.get_asset_path('whitenoise.wav') + E = torchaudio.sox_effects.SoxEffectsChain() - E.set_input_file(noise_filepath) + E.set_input_file(self.noise_filepath) E.append_effect_to_chain("dcshift", [shift, limiter_gain]) sox_output_waveform, sr = E.sox_build_flow_effects() - waveform, _ = torchaudio.load(noise_filepath, normalization=True) - output_waveform = F.dcshift(waveform, shift, limiter_gain) + output_waveform = F.dcshift(self.noise_waveform, shift, limiter_gain) self.assertEqual(output_waveform, sox_output_waveform, atol=1e-4, rtol=1e-5) @@ -332,14 +317,13 @@ def test_dcshift_without_limiter(self): Test dcshift effect, compare to SoX implementation """ shift = 0.6 - noise_filepath = common_utils.get_asset_path('whitenoise.wav') + E = torchaudio.sox_effects.SoxEffectsChain() - E.set_input_file(noise_filepath) + E.set_input_file(self.noise_filepath) E.append_effect_to_chain("dcshift", [shift]) sox_output_waveform, sr = E.sox_build_flow_effects() - waveform, _ = torchaudio.load(noise_filepath, normalization=True) - output_waveform = F.dcshift(waveform, shift) + output_waveform = F.dcshift(self.noise_waveform, shift) self.assertEqual(output_waveform, sox_output_waveform, atol=1e-4, rtol=1e-5) @@ -349,14 +333,13 @@ def test_overdrive(self): """ gain = 30 colour = 40 - noise_filepath = common_utils.get_asset_path('whitenoise.wav') + E = torchaudio.sox_effects.SoxEffectsChain() - E.set_input_file(noise_filepath) + E.set_input_file(self.noise_filepath) E.append_effect_to_chain("overdrive", [gain, colour]) sox_output_waveform, sr = E.sox_build_flow_effects() - waveform, _ = torchaudio.load(noise_filepath, normalization=True) - output_waveform = F.overdrive(waveform, gain, colour) + output_waveform = F.overdrive(self.noise_waveform, gain, colour) self.assertEqual(output_waveform, sox_output_waveform, atol=1e-4, rtol=1e-5) @@ -369,14 +352,14 @@ def test_phaser_sine(self): delay_ms = 2.0 decay = 0.4 speed = 0.5 - noise_filepath = common_utils.get_asset_path('whitenoise.wav') + E = torchaudio.sox_effects.SoxEffectsChain() - E.set_input_file(noise_filepath) + E.set_input_file(self.noise_filepath) E.append_effect_to_chain("phaser", [gain_in, gain_out, delay_ms, decay, speed, "-s"]) sox_output_waveform, sr = E.sox_build_flow_effects() - waveform, sample_rate = torchaudio.load(noise_filepath, normalization=True) - output_waveform = F.phaser(waveform, sample_rate, gain_in, gain_out, delay_ms, decay, speed, sinusoidal=True) + output_waveform = F.phaser(self.noise_waveform, self.NOISE_SAMPLE_RATE, + gain_in, gain_out, delay_ms, decay, speed, sinusoidal=True) self.assertEqual(output_waveform, sox_output_waveform, atol=1e-4, rtol=1e-5) @@ -389,14 +372,14 @@ def test_phaser_triangle(self): delay_ms = 2.0 decay = 0.4 speed = 0.5 - noise_filepath = common_utils.get_asset_path('whitenoise.wav') + E = torchaudio.sox_effects.SoxEffectsChain() - E.set_input_file(noise_filepath) + E.set_input_file(self.noise_filepath) E.append_effect_to_chain("phaser", [gain_in, gain_out, delay_ms, decay, speed, "-t"]) sox_output_waveform, sr = E.sox_build_flow_effects() - waveform, sample_rate = torchaudio.load(noise_filepath, normalization=True) - output_waveform = F.phaser(waveform, sample_rate, gain_in, gain_out, delay_ms, decay, speed, sinusoidal=False) + output_waveform = F.phaser(self.noise_waveform, self.NOISE_SAMPLE_RATE, + gain_in, gain_out, delay_ms, decay, speed, sinusoidal=False) self.assertEqual(output_waveform, sox_output_waveform, atol=1e-4, rtol=1e-5) @@ -410,15 +393,14 @@ def test_flanger_triangle_linear(self): width = 0.9 speed = 0.5 phase = 30 - noise_filepath = common_utils.get_asset_path('whitenoise.wav') + E = torchaudio.sox_effects.SoxEffectsChain() - E.set_input_file(noise_filepath) + E.set_input_file(self.noise_filepath) E.append_effect_to_chain("flanger", [delay, depth, regen, width, speed, "triangle", phase, "linear"]) sox_output_waveform, sr = E.sox_build_flow_effects() - waveform, sample_rate = torchaudio.load(noise_filepath, normalization=True) - output_waveform = F.flanger(waveform, sample_rate, delay, depth, regen, width, speed, phase, - modulation='triangular', interpolation='linear') + output_waveform = F.flanger(self.noise_waveform, self.NOISE_SAMPLE_RATE, delay, depth, regen, + width, speed, phase, modulation='triangular', interpolation='linear') torch.testing.assert_allclose(output_waveform, sox_output_waveform, atol=1e-4, rtol=1e-5) @@ -432,15 +414,14 @@ def test_flanger_triangle_quad(self): width = 0.4 speed = 0.5 phase = 40 - noise_filepath = common_utils.get_asset_path('whitenoise.wav') + E = torchaudio.sox_effects.SoxEffectsChain() - E.set_input_file(noise_filepath) + E.set_input_file(self.noise_filepath) E.append_effect_to_chain("flanger", [delay, depth, regen, width, speed, "triangle", phase, "quadratic"]) sox_output_waveform, sr = E.sox_build_flow_effects() - waveform, sample_rate = torchaudio.load(noise_filepath, normalization=True) - output_waveform = F.flanger(waveform, sample_rate, delay, depth, regen, width, speed, phase, - modulation='triangular', interpolation='quadratic') + output_waveform = F.flanger(self.noise_waveform, self.NOISE_SAMPLE_RATE, delay, depth, + regen, width, speed, phase, modulation='triangular', interpolation='quadratic') torch.testing.assert_allclose(output_waveform, sox_output_waveform, atol=1e-4, rtol=1e-5) @@ -454,15 +435,14 @@ def test_flanger_sine_linear(self): width = 0.23 speed = 1.3 phase = 60 - noise_filepath = common_utils.get_asset_path('whitenoise.wav') + E = torchaudio.sox_effects.SoxEffectsChain() - E.set_input_file(noise_filepath) + E.set_input_file(self.noise_filepath) E.append_effect_to_chain("flanger", [delay, depth, regen, width, speed, "sine", phase, "linear"]) sox_output_waveform, sr = E.sox_build_flow_effects() - waveform, sample_rate = torchaudio.load(noise_filepath, normalization=True) - output_waveform = F.flanger(waveform, sample_rate, delay, depth, regen, width, speed, phase, - modulation='sinusoidal', interpolation='linear') + output_waveform = F.flanger(self.noise_waveform, self.NOISE_SAMPLE_RATE, delay, depth, + regen, width, speed, phase, modulation='sinusoidal', interpolation='linear') torch.testing.assert_allclose(output_waveform, sox_output_waveform, atol=1e-4, rtol=1e-5) @@ -476,15 +456,14 @@ def test_flanger_sine_quad(self): width = 0.23 speed = 1.3 phase = 25 - noise_filepath = common_utils.get_asset_path('whitenoise.wav') + E = torchaudio.sox_effects.SoxEffectsChain() - E.set_input_file(noise_filepath) + E.set_input_file(self.noise_filepath) E.append_effect_to_chain("flanger", [delay, depth, regen, width, speed, "sine", phase, "quadratic"]) sox_output_waveform, sr = E.sox_build_flow_effects() - waveform, sample_rate = torchaudio.load(noise_filepath, normalization=True) - output_waveform = F.flanger(waveform, sample_rate, delay, depth, regen, width, speed, phase, - modulation='sinusoidal', interpolation='quadratic') + output_waveform = F.flanger(self.noise_waveform, self.NOISE_SAMPLE_RATE, delay, depth, + regen, width, speed, phase, modulation='sinusoidal', interpolation='quadratic') torch.testing.assert_allclose(output_waveform, sox_output_waveform, atol=1e-4, rtol=1e-5) @@ -497,21 +476,17 @@ def test_equalizer(self): q = 0.707 gain = 1 - noise_filepath = common_utils.get_asset_path('whitenoise.wav') E = torchaudio.sox_effects.SoxEffectsChain() - E.set_input_file(noise_filepath) + E.set_input_file(self.noise_filepath) E.append_effect_to_chain("equalizer", [center_freq, q, gain]) sox_output_waveform, sr = E.sox_build_flow_effects() - waveform, sample_rate = torchaudio.load(noise_filepath, normalization=True) - output_waveform = F.equalizer_biquad(waveform, sample_rate, center_freq, gain, q) + output_waveform = F.equalizer_biquad(self.noise_waveform, self.NOISE_SAMPLE_RATE, center_freq, gain, q) self.assertEqual(output_waveform, sox_output_waveform, atol=1e-4, rtol=1e-5) def test_perf_biquad_filtering(self): - fn_sine = common_utils.get_asset_path('whitenoise.wav') - b0 = 0.4 b1 = 0.2 b2 = 0.9 @@ -521,13 +496,12 @@ def test_perf_biquad_filtering(self): # SoX method E = torchaudio.sox_effects.SoxEffectsChain() - E.set_input_file(fn_sine) + E.set_input_file(self.noise_filepath) E.append_effect_to_chain("biquad", [b0, b1, b2, a0, a1, a2]) waveform_sox_out, _ = E.sox_build_flow_effects() - waveform, _ = torchaudio.load(fn_sine, normalization=True) waveform_lfilter_out = F.lfilter( - waveform, torch.tensor([a0, a1, a2]), torch.tensor([b0, b1, b2]) + self.noise_waveform, torch.tensor([a0, a1, a2]), torch.tensor([b0, b1, b2]) ) self.assertEqual(waveform_lfilter_out, waveform_sox_out, atol=1e-4, rtol=1e-5) diff --git a/test/test_sox_effects.py b/test/test_sox_effects.py index 68440db8d2..6b12d7cd06 100644 --- a/test/test_sox_effects.py +++ b/test/test_sox_effects.py @@ -1,3 +1,4 @@ +import sys import math import unittest @@ -11,7 +12,7 @@ class Test_SoxEffectsChain(common_utils.TorchaudioTestCase): backend = 'sox' - test_filepath = common_utils.get_asset_path("steam-train-whistle-daniel_simon.mp3") + test_filepath = common_utils.get_asset_path("steam-train-whistle-daniel_simon.wav") def test_single_channel(self): fn_sine = common_utils.get_asset_path("sinewave.wav") @@ -34,6 +35,7 @@ def test_rate_channels(self): self.assertEqual(sr, target_rate) self.assertEqual(x.size(0), target_channels) + @unittest.skipIf(sys.platform == 'darwin', 'This test is known to fail on macOS') def test_lowpass_speed(self): speed = .8 si, _ = torchaudio.info(self.test_filepath) diff --git a/test/test_transforms.py b/test/test_transforms.py index af2b834fdb..6df9562bc8 100644 --- a/test/test_transforms.py +++ b/test/test_transforms.py @@ -45,7 +45,7 @@ def test_mu_law_companding(self): def test_AmplitudeToDB(self): filepath = common_utils.get_asset_path('steam-train-whistle-daniel_simon.wav') - waveform, sample_rate = torchaudio.load(filepath) + waveform = common_utils.load_wav(filepath)[0] mag_to_db_transform = transforms.AmplitudeToDB('magnitude', 80.) power_to_db_transform = transforms.AmplitudeToDB('power', 80.) @@ -115,7 +115,7 @@ def test_mel2(self): self.assertTrue(mel_transform2.mel_scale.fb.sum(1).ge(0.).all()) # check on multi-channel audio filepath = common_utils.get_asset_path('steam-train-whistle-daniel_simon.wav') - x_stereo, sr_stereo = torchaudio.load(filepath) # (2, 278756), 44100 + x_stereo = common_utils.load_wav(filepath)[0] # (2, 278756), 44100 spectrogram_stereo = s2db(mel_transform(x_stereo)) # (2, 128, 1394) self.assertTrue(spectrogram_stereo.dim() == 3) self.assertTrue(spectrogram_stereo.size(0) == 2) @@ -166,7 +166,7 @@ def test_mfcc(self): def test_resample_size(self): input_path = common_utils.get_asset_path('sinewave.wav') - waveform, sample_rate = torchaudio.load(input_path) + waveform, sample_rate = common_utils.load_wav(input_path) upsample_rate = sample_rate * 2 downsample_rate = sample_rate // 2 diff --git a/test/torchscript_consistency_impl.py b/test/torchscript_consistency_impl.py index 2527cd5fbf..76444dc18a 100644 --- a/test/torchscript_consistency_impl.py +++ b/test/torchscript_consistency_impl.py @@ -2,7 +2,6 @@ import unittest import torch -import torchaudio import torchaudio.functional as F import torchaudio.transforms as T @@ -616,6 +615,5 @@ def test_SlidingWindowCmn(self): def test_Vad(self): filepath = common_utils.get_asset_path("vad-go-mono-32000.wav") - common_utils.set_audio_backend('default') - waveform, sample_rate = torchaudio.load(filepath) + waveform, sample_rate = common_utils.load_wav(filepath) self._assert_consistency(T.Vad(sample_rate=sample_rate), waveform) diff --git a/third_party/CMakeLists.txt b/third_party/CMakeLists.txt new file mode 100644 index 0000000000..c4be4cb7b0 --- /dev/null +++ b/third_party/CMakeLists.txt @@ -0,0 +1,80 @@ +cmake_minimum_required(VERSION 3.1) + +project(torchaudio_third_parties) +include(ExternalProject) + +set(INSTALL_DIR ${CMAKE_CURRENT_SOURCE_DIR}/install) +set(ARCHIVE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/archives) +set(COMMON_ARGS --quiet --disable-shared --enable-static --prefix=${INSTALL_DIR} --with-pic --disable-dependency-tracking --disable-debug --disable-examples --disable-doc) + +ExternalProject_Add(libmad + PREFIX ${CMAKE_CURRENT_SOURCE_DIR} + DOWNLOAD_DIR ${ARCHIVE_DIR} + URL https://downloads.sourceforge.net/project/mad/libmad/0.15.1b/libmad-0.15.1b.tar.gz + URL_HASH SHA256=bbfac3ed6bfbc2823d3775ebb931087371e142bb0e9bb1bee51a76a6e0078690 + PATCH_COMMAND patch < ${CMAKE_CURRENT_SOURCE_DIR}/patch/libmad.patch + CONFIGURE_COMMAND ${CMAKE_CURRENT_SOURCE_DIR}/src/libmad/configure ${COMMON_ARGS} +) + +ExternalProject_Add(libmp3lame + PREFIX ${CMAKE_CURRENT_SOURCE_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 + CONFIGURE_COMMAND ${CMAKE_CURRENT_SOURCE_DIR}/src/libmp3lame/configure ${COMMON_ARGS} --enable-nasm +) + +ExternalProject_Add(libogg + PREFIX ${CMAKE_CURRENT_SOURCE_DIR} + DOWNLOAD_DIR ${ARCHIVE_DIR} + URL https://ftp.osuosl.org/pub/xiph/releases/ogg/libogg-1.3.3.tar.gz + URL_HASH SHA256=c2e8a485110b97550f453226ec644ebac6cb29d1caef2902c007edab4308d985 + CONFIGURE_COMMAND ${CMAKE_CURRENT_SOURCE_DIR}/src/libogg/configure ${COMMON_ARGS} +) + +ExternalProject_Add(libflac + PREFIX ${CMAKE_CURRENT_SOURCE_DIR} + DEPENDS libogg + DOWNLOAD_DIR ${ARCHIVE_DIR} + URL https://ftp.osuosl.org/pub/xiph/releases/flac/flac-1.3.2.tar.xz + URL_HASH SHA256=91cfc3ed61dc40f47f050a109b08610667d73477af6ef36dcad31c31a4a8d53f + CONFIGURE_COMMAND ${CMAKE_CURRENT_SOURCE_DIR}/build_codec_helper.sh ${CMAKE_CURRENT_SOURCE_DIR}/src/libflac/configure ${COMMON_ARGS} --with-ogg +) + +ExternalProject_Add(libvorbis + PREFIX ${CMAKE_CURRENT_SOURCE_DIR} + DEPENDS libogg + DOWNLOAD_DIR ${ARCHIVE_DIR} + URL https://ftp.osuosl.org/pub/xiph/releases/vorbis/libvorbis-1.3.6.tar.gz + URL_HASH SHA256=6ed40e0241089a42c48604dc00e362beee00036af2d8b3f46338031c9e0351cb + CONFIGURE_COMMAND ${CMAKE_CURRENT_SOURCE_DIR}/build_codec_helper.sh ${CMAKE_CURRENT_SOURCE_DIR}/src/libvorbis/configure ${COMMON_ARGS} --with-ogg +) + +ExternalProject_Add(libopus + PREFIX ${CMAKE_CURRENT_SOURCE_DIR} + DEPENDS libogg + DOWNLOAD_DIR ${ARCHIVE_DIR} + URL https://ftp.osuosl.org/pub/xiph/releases/opus/opus-1.3.1.tar.gz + URL_HASH SHA256=65b58e1e25b2a114157014736a3d9dfeaad8d41be1c8179866f144a2fb44ff9d + CONFIGURE_COMMAND ${CMAKE_CURRENT_SOURCE_DIR}/build_codec_helper.sh ${CMAKE_CURRENT_SOURCE_DIR}/src/libopus/configure ${COMMON_ARGS} --with-ogg +) + +ExternalProject_Add(opusfile + PREFIX ${CMAKE_CURRENT_SOURCE_DIR} + DEPENDS libopus + DOWNLOAD_DIR ${ARCHIVE_DIR} + STAMP_DIR ${CMAKE_CURRENT_SOURCE_DIR}/src/opusfile-stamp + SOURCE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/src/opusfile + URL https://ftp.osuosl.org/pub/xiph/releases/opus/opusfile-0.12.tar.gz + URL_HASH SHA256=118d8601c12dd6a44f52423e68ca9083cc9f2bfe72da7a8c1acb22a80ae3550b + CONFIGURE_COMMAND ${CMAKE_CURRENT_SOURCE_DIR}/build_codec_helper.sh ${CMAKE_CURRENT_SOURCE_DIR}/src/opusfile/configure ${COMMON_ARGS} --disable-http +) + +ExternalProject_Add(libsox + PREFIX ${CMAKE_CURRENT_SOURCE_DIR} + DEPENDS libogg libflac libvorbis opusfile libmp3lame libmad + 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 + CONFIGURE_COMMAND ${CMAKE_CURRENT_SOURCE_DIR}/build_codec_helper.sh ${CMAKE_CURRENT_SOURCE_DIR}/src/libsox/configure ${COMMON_ARGS} --with-lame --with-flac --with-mad --with-oggvorbis --without-alsa --without-coreaudio --without-png --without-oss --without-sndfile --with-opus +) diff --git a/third_party/build_codec_helper.sh b/third_party/build_codec_helper.sh new file mode 100755 index 0000000000..e7f2614781 --- /dev/null +++ b/third_party/build_codec_helper.sh @@ -0,0 +1,13 @@ +#!/usr/bin/env bash +# Helper script for building codecs depending on libogg, such as libopus and opus. +# It is difficult to set environment variable inside of ExternalProject_Add, +# so this script sets necessary environment variables before running the given command + +this_dir="$( cd "$( dirname "${BASH_SOURCE[0]}" )" >/dev/null 2>&1 && pwd )" +install_dir="${this_dir}/install" + +export PKG_CONFIG_PATH="${install_dir}/lib/pkgconfig" +export LDFLAGS="-L${install_dir}/lib ${LDFLAGS}" +export CPPFLAGS="-I${install_dir}/include ${CPPFLAGS}" + +$@ diff --git a/third_party/patch/libmad.patch b/third_party/patch/libmad.patch new file mode 100644 index 0000000000..a805787831 --- /dev/null +++ b/third_party/patch/libmad.patch @@ -0,0 +1,86 @@ +See the followings for the origin of this patch +http://www.linuxfromscratch.org/blfs/view/svn/multimedia/libmad.html +http://www.linuxfromscratch.org/patches/blfs/svn/libmad-0.15.1b-fixes-1.patch +--- src/libmad/configure 2004-02-05 09:34:07.000000000 +0000 ++++ src/libmad/configure.new 2020-06-30 21:10:28.528018931 +0000 +@@ -19083,71 +19083,7 @@ + + if test "$GCC" = yes + then +- if test -z "$arch" +- then +- case "$host" in +- i386-*) ;; +- i?86-*) arch="-march=i486" ;; +- arm*-empeg-*) arch="-march=armv4 -mtune=strongarm1100" ;; +- armv4*-*) arch="-march=armv4 -mtune=strongarm" ;; +- powerpc-*) ;; +- mips*-agenda-*) arch="-mcpu=vr4100" ;; +- mips*-luxsonor-*) arch="-mips1 -mcpu=r3000 -Wa,-m4010" ;; +- esac +- fi +- +- case "$optimize" in +- -O|"-O "*) +- optimize="-O" +- optimize="$optimize -fforce-mem" +- optimize="$optimize -fforce-addr" +- : #x optimize="$optimize -finline-functions" +- : #- optimize="$optimize -fstrength-reduce" +- optimize="$optimize -fthread-jumps" +- optimize="$optimize -fcse-follow-jumps" +- optimize="$optimize -fcse-skip-blocks" +- : #x optimize="$optimize -frerun-cse-after-loop" +- : #x optimize="$optimize -frerun-loop-opt" +- : #x optimize="$optimize -fgcse" +- optimize="$optimize -fexpensive-optimizations" +- optimize="$optimize -fregmove" +- : #* optimize="$optimize -fdelayed-branch" +- : #x optimize="$optimize -fschedule-insns" +- optimize="$optimize -fschedule-insns2" +- : #? optimize="$optimize -ffunction-sections" +- : #? optimize="$optimize -fcaller-saves" +- : #> optimize="$optimize -funroll-loops" +- : #> optimize="$optimize -funroll-all-loops" +- : #x optimize="$optimize -fmove-all-movables" +- : #x optimize="$optimize -freduce-all-givs" +- : #? optimize="$optimize -fstrict-aliasing" +- : #* optimize="$optimize -fstructure-noalias" +- +- case "$host" in +- arm*-*) +- optimize="$optimize -fstrength-reduce" +- ;; +- mips*-*) +- optimize="$optimize -fstrength-reduce" +- optimize="$optimize -finline-functions" +- ;; +- i?86-*) +- optimize="$optimize -fstrength-reduce" +- ;; +- powerpc-apple-*) +- # this triggers an internal compiler error with gcc2 +- : #optimize="$optimize -fstrength-reduce" +- +- # this is really only beneficial with gcc3 +- : #optimize="$optimize -finline-functions" +- ;; +- *) +- # this sometimes provokes bugs in gcc 2.95.2 +- : #optimize="$optimize -fstrength-reduce" +- ;; +- esac +- ;; +- esac ++ optimize="-O2" + fi + + case "$host" in +@@ -21497,6 +21433,7 @@ + then + case "$host" in + i?86-*) FPM="INTEL" ;; ++ x86_64*) FPM="64BIT" ;; + arm*-*) FPM="ARM" ;; + mips*-*) FPM="MIPS" ;; + sparc*-*) FPM="SPARC" ;; diff --git a/torchaudio/backend/sox_io_backend.py b/torchaudio/backend/sox_io_backend.py new file mode 100644 index 0000000000..4664f733c6 --- /dev/null +++ b/torchaudio/backend/sox_io_backend.py @@ -0,0 +1,134 @@ +from typing import Tuple, Optional + +import torch +from torchaudio._internal import ( + module_utils as _mod_utils, +) + + +class AudioMetaData: + def __init__(self, sample_rate: int, num_frames: int, num_channels: int): + self.sample_rate = sample_rate + self.num_frames = num_frames + self.num_channels = num_channels + + +@_mod_utils.requires_module('torchaudio._torchaudio') +def info(filepath: str) -> AudioMetaData: + """Get signal information of an audio file.""" + sinfo = torch.ops.torchaudio.sox_io_get_info(filepath) + return AudioMetaData(sinfo.get_sample_rate(), sinfo.get_num_frames(), sinfo.get_num_channels()) + + +@_mod_utils.requires_module('torchaudio._torchaudio') +def load( + filepath: str, + frame_offset: int = 0, + num_frames: int = -1, + normalize: bool = True, + channels_first: bool = True, +) -> Tuple[torch.Tensor, int]: + """Load audio data from file. + + This function can handle all the codecs that underlying libsox can handle, however note the + followings. + + Note: + This function is tested on the following formats; + - WAV + - 32-bit floating-point + - 32-bit signed integer + - 16-bit signed integer + - 8-bit unsigned integer + - MP3 + - FLAC + - OGG/VORBIS + + By default, this function returns Tensor with ``float32`` dtype and the shape of ``[channel, time]``. + The samples are normalized to fit in the range of ``[-1.0, 1.0]``. + + When the input format is WAV with integer type, such as 32-bit signed integer, 16-bit + signed integer and 8-bit unsigned integer (24-bit signed integer is not supported), + by providing ``normalize=False``, this function can return integer Tensor, where the samples + are expressed within the whole range of the corresponding dtype, that is, ``int32`` tensor + for 32-bit signed PCM, ``int16`` for 16-bit signed PCM and ``uint8`` for 8-bit unsigned PCM. + + ``normalize`` parameter has no effect on 32-bit floating-point WAV and other formats, such as + flac and mp3. For these formats, this function always returns ``float32`` Tensor with values + normalized to ``[-1.0, 1.0]``. + + Args: + filepath: Path to audio file + frame_offset: Number of frames to skip before start reading data. + num_frames: Maximum number of frames to read. -1 reads all the remaining samples, starting + from ``frame_offset``. This function may return the less number of frames if there is + not enough frames in the given file. + normalize: When ``True``, this function always return ``float32``, and sample values are + normalized to ``[-1.0, 1.0]``. If input file is integer WAV, giving ``False`` will change + the resulting Tensor type to integer type. This argument has no effect for formats other + than integer WAV type. + channels_first: When True, the returned Tensor has dimension ``[channel, time]``. + Otherwise, the returned Tensor's dimension is ``[time, channel]``. + + Returns: + torch.Tensor: If the input file has integer wav format and normalization is off, then it has + integer type, else ``float32`` type. If ``channels_first=True``, it has + ``[channel, time]`` else ``[time, channel]``. + """ + signal = torch.ops.torchaudio.sox_io_load_audio_file( + filepath, frame_offset, num_frames, normalize, channels_first) + return signal.get_tensor(), signal.get_sample_rate() + + +@_mod_utils.requires_module('torchaudio._torchaudio') +def save( + filepath: str, + tensor: torch.Tensor, + sample_rate: int, + channels_first: bool = True, + compression: Optional[float] = None, +): + """Save audio data to file. + + Supported formats are; + - WAV + - 32-bit floating-point + - 32-bit signed integer + - 16-bit signed integer + - 8-bit unsigned integer + - MP3 + - FLAC + - OGG/VORBIS + + Args: + filepath: Path to save file. + tensor: Audio data to save. must be 2D tensor. + sample_rate: sampling rate + channels_first: If True, the given tensor is interpreted as ``[channel, time]``. + compression: Used for formats other than WAV. This corresponds to ``-C`` option + of ``sox`` command. + See the detail at http://sox.sourceforge.net/soxformat.html. + - MP3: Either bitrate [kbps] with quality factor, such as ``128.2`` or + VBR encoding with quality factor such as ``-4.2``. Default: ``-4.5`` + - FLAC: compression level. Whole number from ``0`` to ``8``. + ``8`` is default and highest compression. + - OGG/VORBIS: number from -1 to 10; -1 is the highest compression and lowest + quality. Default: ``3``. + """ + if compression is None: + ext = str(filepath)[-3:].lower() + if ext == 'wav': + compression = 0. + elif ext == 'mp3': + compression = -4.5 + elif ext == 'flac': + compression = 8. + elif ext in ['ogg', 'vorbis']: + compression = 3. + else: + raise RuntimeError(f'Unsupported file type: "{ext}"') + signal = torch.classes.torchaudio.TensorSignal(tensor, sample_rate, channels_first) + torch.ops.torchaudio.sox_io_save_audio_file(filepath, signal, compression) + + +load_wav = load diff --git a/torchaudio/backend/utils.py b/torchaudio/backend/utils.py index d537f01daf..cb53b3e02f 100644 --- a/torchaudio/backend/utils.py +++ b/torchaudio/backend/utils.py @@ -7,6 +7,7 @@ from . import ( no_backend, sox_backend, + sox_io_backend, soundfile_backend, ) @@ -24,6 +25,7 @@ def list_audio_backends() -> List[str]: backends.append('soundfile') if is_module_available('torchaudio._torchaudio'): backends.append('sox') + backends.append('sox_io') return backends @@ -43,6 +45,8 @@ def set_audio_backend(backend: Optional[str]) -> None: module = no_backend elif backend == 'sox': module = sox_backend + elif backend == 'sox_io': + module = sox_io_backend elif backend == 'soundfile': module = soundfile_backend else: @@ -69,6 +73,8 @@ def get_audio_backend() -> Optional[str]: return None if torchaudio.load == sox_backend.load: return 'sox' + if torchaudio.load == sox_io_backend.load: + return 'sox_io' if torchaudio.load == soundfile_backend.load: return 'soundfile' raise ValueError('Unknown backend.') diff --git a/torchaudio/csrc/register.cpp b/torchaudio/csrc/register.cpp index 81b1a84c96..3c03232941 100644 --- a/torchaudio/csrc/register.cpp +++ b/torchaudio/csrc/register.cpp @@ -1,17 +1,64 @@ #ifndef TORCHAUDIO_REGISTER_H #define TORCHAUDIO_REGISTER_H -#include +#include +#include +#include namespace torchaudio { namespace { +//////////////////////////////////////////////////////////////////////////////// +// sox_utils.h +//////////////////////////////////////////////////////////////////////////////// +static auto registerTensorSignal = + torch::class_("torchaudio", "TensorSignal") + .def(torch::init()) + .def("get_tensor", &sox_utils::TensorSignal::getTensor) + .def("get_sample_rate", &sox_utils::TensorSignal::getSampleRate) + .def("get_channels_first", &sox_utils::TensorSignal::getChannelsFirst); + +//////////////////////////////////////////////////////////////////////////////// +// sox_io.h +//////////////////////////////////////////////////////////////////////////////// static auto registerSignalInfo = - torch::class_("torchaudio", "SignalInfo") - .def(torch::init()) - .def("get_sample_rate", &SignalInfo::getSampleRate) - .def("get_num_channels", &SignalInfo::getNumChannels) - .def("get_num_samples", &SignalInfo::getNumSamples); + torch::class_("torchaudio", "SignalInfo") + .def("get_sample_rate", &sox_io::SignalInfo::getSampleRate) + .def("get_num_channels", &sox_io::SignalInfo::getNumChannels) + .def("get_num_frames", &sox_io::SignalInfo::getNumFrames); + +static auto registerGetInfo = torch::RegisterOperators().op( + torch::RegisterOperators::options() + .schema( + "torchaudio::sox_io_get_info(str path) -> __torch__.torch.classes.torchaudio.SignalInfo info") + .catchAllKernel()); + +static auto registerLoadAudioFile = torch::RegisterOperators().op( + torch::RegisterOperators::options() + .schema( + "torchaudio::sox_io_load_audio_file(str path, int frame_offset, int num_frames, bool normalize, bool channels_first) -> __torch__.torch.classes.torchaudio.TensorSignal signal") + .catchAllKernel< + decltype(sox_io::load_audio_file), + &sox_io::load_audio_file>()); + +static auto registerSaveAudioFile = torch::RegisterOperators().op( + torch::RegisterOperators::options() + .schema( + "torchaudio::sox_io_save_audio_file(str path, __torch__.torch.classes.torchaudio.TensorSignal signal, float compression) -> ()") + .catchAllKernel< + decltype(sox_io::save_audio_file), + &sox_io::save_audio_file>()); + +//////////////////////////////////////////////////////////////////////////////// +// sox_effects.h +//////////////////////////////////////////////////////////////////////////////// +static auto registerSoxEffects = + torch::RegisterOperators( + "torchaudio::sox_effects_initialize_sox_effects", + &sox_effects::initialize_sox_effects) + .op("torchaudio::sox_effects_shutdown_sox_effects", + &sox_effects::shutdown_sox_effects) + .op("torchaudio::sox_effects_list_effects", &sox_effects::list_effects); } // namespace } // namespace torchaudio diff --git a/torchaudio/csrc/sox.cpp b/torchaudio/csrc/sox.cpp index 3ae81bef19..0f099946fd 100644 --- a/torchaudio/csrc/sox.cpp +++ b/torchaudio/csrc/sox.cpp @@ -82,17 +82,6 @@ std::tuple get_info( return std::make_tuple(fd->signal, fd->encoding); } -std::vector get_effect_names() { - sox_effect_fn_t const * fns = sox_get_effect_fns(); - std::vector sv; - for(int i = 0; fns[i]; ++i) { - const sox_effect_handler_t *eh = fns[i] (); - if(eh && eh->name) - sv.push_back(eh->name); - } - return sv; -} - int read_audio_file( const std::string& file_name, at::Tensor output, @@ -186,16 +175,6 @@ void write_audio_file( } } -int initialize_sox() { - /* Initialization for sox effects. Only initialize once */ - return sox_init(); -} - -int shutdown_sox() { - /* Shutdown for sox effects. Do not shutdown between multiple calls */ - return sox_quit(); -} - int build_flow_effects(const std::string& file_name, at::Tensor otensor, bool ch_first, @@ -489,20 +468,8 @@ PYBIND11_MODULE(_torchaudio, m) { "get_info", &torch::audio::get_info, "Gets information about an audio file"); - m.def( - "get_effect_names", - &torch::audio::get_effect_names, - "Gets the names of all available effects"); m.def( "build_flow_effects", &torch::audio::build_flow_effects, "build effects and flow chain into tensors"); - m.def( - "initialize_sox", - &torch::audio::initialize_sox, - "initialize sox for effects"); - m.def( - "shutdown_sox", - &torch::audio::shutdown_sox, - "shutdown sox for effects"); } diff --git a/torchaudio/csrc/sox.h b/torchaudio/csrc/sox.h index 8d851c9b21..8093f0732e 100644 --- a/torchaudio/csrc/sox.h +++ b/torchaudio/csrc/sox.h @@ -45,13 +45,6 @@ void write_audio_file( std::tuple get_info( const std::string& file_name); -// get names of all sox effects -std::vector get_effect_names(); - -// Initialize and Shutdown SoX effects chain. These functions should only be run once. -int initialize_sox(); -int shutdown_sox(); - // Struct for build_flow_effects function struct SoxEffect { SoxEffect() : ename(""), eopts({""}) { } diff --git a/torchaudio/csrc/sox_effects.cpp b/torchaudio/csrc/sox_effects.cpp new file mode 100644 index 0000000000..9a0c2ddc6f --- /dev/null +++ b/torchaudio/csrc/sox_effects.cpp @@ -0,0 +1,54 @@ +#include +#include + +using namespace torch::indexing; + +namespace torchaudio { +namespace sox_effects { + +namespace { + +enum SoxEffectsResourceState { NotInitialized, Initialized, ShutDown }; +SoxEffectsResourceState SOX_RESOURCE_STATE = NotInitialized; + +} // namespace + +void initialize_sox_effects() { + if (SOX_RESOURCE_STATE == ShutDown) { + throw std::runtime_error( + "SoX Effects has been shut down. Cannot initialize again."); + } + if (SOX_RESOURCE_STATE == NotInitialized) { + if (sox_init() != SOX_SUCCESS) { + throw std::runtime_error("Failed to initialize sox effects."); + }; + SOX_RESOURCE_STATE = Initialized; + } +}; + +void shutdown_sox_effects() { + if (SOX_RESOURCE_STATE == NotInitialized) { + throw std::runtime_error( + "SoX Effects is not initialized. Cannot shutdown."); + } + if (SOX_RESOURCE_STATE == Initialized) { + if (sox_quit() != SOX_SUCCESS) { + throw std::runtime_error("Failed to initialize sox effects."); + }; + SOX_RESOURCE_STATE = ShutDown; + } +} + +std::vector list_effects() { + std::vector names; + const sox_effect_fn_t* fns = sox_get_effect_fns(); + for (int i = 0; fns[i]; ++i) { + const sox_effect_handler_t* handler = fns[i](); + if (handler && handler->name) + names.push_back(handler->name); + } + return names; +} + +} // namespace sox_effects +} // namespace torchaudio diff --git a/torchaudio/csrc/sox_effects.h b/torchaudio/csrc/sox_effects.h new file mode 100644 index 0000000000..14bdbbfabc --- /dev/null +++ b/torchaudio/csrc/sox_effects.h @@ -0,0 +1,18 @@ +#ifndef TORCHAUDIO_SOX_EFFECTS_H +#define TORCHAUDIO_SOX_EFFECTS_H + +#include + +namespace torchaudio { +namespace sox_effects { + +void initialize_sox_effects(); + +void shutdown_sox_effects(); + +std::vector list_effects(); + +} // namespace sox_effects +} // namespace torchaudio + +#endif diff --git a/torchaudio/csrc/sox_io.cpp b/torchaudio/csrc/sox_io.cpp new file mode 100644 index 0000000000..5d308027bb --- /dev/null +++ b/torchaudio/csrc/sox_io.cpp @@ -0,0 +1,170 @@ +#include +#include +#include + +using namespace torch::indexing; +using namespace torchaudio::sox_utils; + +namespace torchaudio { +namespace sox_io { + +SignalInfo::SignalInfo( + const int64_t sample_rate_, + const int64_t num_channels_, + const int64_t num_frames_) + : sample_rate(sample_rate_), + num_channels(num_channels_), + num_frames(num_frames_){}; + +int64_t SignalInfo::getSampleRate() const { + return sample_rate; +} + +int64_t SignalInfo::getNumChannels() const { + return num_channels; +} + +int64_t SignalInfo::getNumFrames() const { + return num_frames; +} + +c10::intrusive_ptr get_info(const std::string& path) { + SoxFormat sf(sox_open_read( + path.c_str(), + /*signal=*/nullptr, + /*encoding=*/nullptr, + /*filetype=*/nullptr)); + + if (static_cast(sf) == nullptr) { + throw std::runtime_error("Error opening audio file"); + } + + return c10::make_intrusive( + static_cast(sf->signal.rate), + static_cast(sf->signal.channels), + static_cast(sf->signal.length / sf->signal.channels)); +} + +c10::intrusive_ptr load_audio_file( + const std::string& path, + const int64_t frame_offset, + const int64_t num_frames, + const bool normalize, + const bool channels_first) { + if (frame_offset < 0) { + throw std::runtime_error( + "Invalid argument: frame_offset must be non-negative."); + } + if (num_frames == 0 || num_frames < -1) { + throw std::runtime_error( + "Invalid argument: num_frames must be -1 or greater than 0."); + } + + SoxFormat sf(sox_open_read( + path.c_str(), + /*signal=*/nullptr, + /*encoding=*/nullptr, + /*filetype=*/nullptr)); + + validate_input_file(sf); + + const int64_t num_channels = sf->signal.channels; + const int64_t num_total_samples = sf->signal.length; + const int64_t sample_start = sf->signal.channels * frame_offset; + + if (sox_seek(sf, sample_start, 0) == SOX_EOF) { + throw std::runtime_error("Error reading audio file: offset past EOF."); + } + + const int64_t sample_end = [&]() { + if (num_frames == -1) + return num_total_samples; + const int64_t sample_end_ = num_channels * num_frames + sample_start; + if (num_total_samples < sample_end_) { + // For lossy encoding, it is difficult to predict exact size of buffer for + // reading the number of samples required. + // So we allocate buffer size of given `num_frames` and ask sox to read as + // much as possible. For lossless format, sox reads exact number of + // samples, but for lossy encoding, sox can end up reading less. (i.e. + // mp3) For the consistent behavior specification between lossy/lossless + // format, we allow users to provide `num_frames` value that exceeds #of + // available samples, and we adjust it here. + return num_total_samples; + } + return sample_end_; + }(); + + const int64_t max_samples = sample_end - sample_start; + + // Read samples into buffer + std::vector buffer; + buffer.reserve(max_samples); + const int64_t num_samples = sox_read(sf, buffer.data(), max_samples); + if (num_samples == 0) { + throw std::runtime_error( + "Error reading audio file: empty file or read operation failed."); + } + // NOTE: num_samples may be smaller than max_samples if the input + // format is compressed (i.e. mp3). + + // Convert to Tensor + auto tensor = convert_to_tensor( + buffer.data(), + num_samples, + num_channels, + get_dtype(sf->encoding.encoding, sf->signal.precision), + normalize, + channels_first); + + return c10::make_intrusive( + tensor, static_cast(sf->signal.rate), channels_first); +} + +void save_audio_file( + const std::string& file_name, + const c10::intrusive_ptr& signal, + const double compression) { + const auto tensor = signal->getTensor(); + const auto sample_rate = signal->getSampleRate(); + const auto channels_first = signal->getChannelsFirst(); + + validate_input_tensor(tensor); + + const auto filetype = get_filetype(file_name); + const auto signal_info = + get_signalinfo(tensor, sample_rate, channels_first, filetype); + const auto encoding_info = + get_encodinginfo(filetype, tensor.dtype(), compression); + + SoxFormat sf(sox_open_write( + file_name.c_str(), + &signal_info, + &encoding_info, + /*filetype=*/filetype.c_str(), + /*oob=*/nullptr, + /*overwrite_permitted=*/nullptr)); + + if (static_cast(sf) == nullptr) { + throw std::runtime_error("Error saving audio file: failed to open file."); + } + + auto tensor_ = tensor; + if (channels_first) { + tensor_ = tensor_.t(); + } + + const int64_t frames_per_chunk = 65536; + for (int64_t i = 0; i < tensor_.size(0); i += frames_per_chunk) { + auto chunk = tensor_.index({Slice(i, i + frames_per_chunk), Slice()}); + chunk = unnormalize_wav(chunk).contiguous(); + + const size_t numel = chunk.numel(); + if (sox_write(sf, chunk.data_ptr(), numel) != numel) { + throw std::runtime_error( + "Error saving audio file: failed to write the entier buffer."); + } + } +} + +} // namespace sox_io +} // namespace torchaudio diff --git a/torchaudio/csrc/sox_io.h b/torchaudio/csrc/sox_io.h new file mode 100644 index 0000000000..5288e911e8 --- /dev/null +++ b/torchaudio/csrc/sox_io.h @@ -0,0 +1,41 @@ +#ifndef TORCHAUDIO_SOX_IO_H +#define TORCHAUDIO_SOX_IO_H + +#include +#include + +namespace torchaudio { +namespace sox_io { + +struct SignalInfo : torch::CustomClassHolder { + int64_t sample_rate; + int64_t num_channels; + int64_t num_frames; + + SignalInfo( + const int64_t sample_rate_, + const int64_t num_channels_, + const int64_t num_frames_); + int64_t getSampleRate() const; + int64_t getNumChannels() const; + int64_t getNumFrames() const; +}; + +c10::intrusive_ptr get_info(const std::string& path); + +c10::intrusive_ptr load_audio_file( + const std::string& path, + const int64_t frame_offset = 0, + const int64_t num_frames = -1, + const bool normalize = true, + const bool channels_first = true); + +void save_audio_file( + const std::string& file_name, + const c10::intrusive_ptr& signal, + const double compression = 0.); + +} // namespace sox_io +} // namespace torchaudio + +#endif diff --git a/torchaudio/csrc/sox_utils.cpp b/torchaudio/csrc/sox_utils.cpp new file mode 100644 index 0000000000..c1fd8383a8 --- /dev/null +++ b/torchaudio/csrc/sox_utils.cpp @@ -0,0 +1,245 @@ +#include +#include +#include + +namespace torchaudio { +namespace sox_utils { + +TensorSignal::TensorSignal( + torch::Tensor tensor_, + int64_t sample_rate_, + bool channels_first_) + : tensor(tensor_), + sample_rate(sample_rate_), + channels_first(channels_first_){}; + +torch::Tensor TensorSignal::getTensor() const { + return tensor; +} +int64_t TensorSignal::getSampleRate() const { + return sample_rate; +} +bool TensorSignal::getChannelsFirst() const { + return channels_first; +} + +SoxFormat::SoxFormat(sox_format_t* fd) noexcept : fd_(fd) {} +SoxFormat::~SoxFormat() { + if (fd_ != nullptr) { + sox_close(fd_); + } +} +sox_format_t* SoxFormat::operator->() const noexcept { + return fd_; +} +SoxFormat::operator sox_format_t*() const noexcept { + return fd_; +} + +void validate_input_file(const SoxFormat& sf) { + if (static_cast(sf) == nullptr) { + throw std::runtime_error("Error loading audio file: failed to open file."); + } + if (sf->encoding.encoding == SOX_ENCODING_UNKNOWN) { + throw std::runtime_error("Error loading audio file: unknown encoding."); + } + if (sf->signal.length == 0) { + throw std::runtime_error("Error reading audio file: unkown length."); + } +} + +void validate_input_tensor(const torch::Tensor tensor) { + if (!tensor.device().is_cpu()) { + throw std::runtime_error("Input tensor has to be on CPU."); + } + + if (tensor.ndimension() != 2) { + throw std::runtime_error("Input tensor has to be 2D."); + } + + const auto dtype = tensor.dtype(); + if (!(dtype == torch::kFloat32 || dtype == torch::kInt32 || + dtype == torch::kInt16 || dtype == torch::kUInt8)) { + throw std::runtime_error( + "Input tensor has to be one of float32, int32, int16 or uint8 type."); + } +} + +caffe2::TypeMeta get_dtype( + const sox_encoding_t encoding, + const unsigned precision) { + const auto dtype = [&]() { + switch (encoding) { + case SOX_ENCODING_UNSIGNED: // 8-bit PCM WAV + return torch::kUInt8; + case SOX_ENCODING_SIGN2: // 16-bit or 32-bit PCM WAV + switch (precision) { + case 16: + return torch::kInt16; + case 32: + return torch::kInt32; + default: + throw std::runtime_error( + "Only 16 and 32 bits are supported for signed PCM."); + } + default: + // default to float32 for the other formats, including + // 32-bit flaoting-point WAV, + // MP3, + // FLAC, + // VORBIS etc... + return torch::kFloat32; + } + }(); + return c10::scalarTypeToTypeMeta(dtype); +} + +torch::Tensor convert_to_tensor( + sox_sample_t* buffer, + const int32_t num_samples, + const int32_t num_channels, + const caffe2::TypeMeta dtype, + const bool normalize, + const bool channels_first) { + auto t = torch::from_blob( + buffer, {num_samples / num_channels, num_channels}, torch::kInt32); + // Note: Tensor created from_blob does not own data but borrwos + // So make sure to create a new copy after processing samples. + if (normalize || dtype == torch::kFloat32) { + t = t.to(torch::kFloat32); + t *= (t > 0) / 2147483647. + (t < 0) / 2147483648.; + } else if (dtype == torch::kInt32) { + t = t.clone(); + } else if (dtype == torch::kInt16) { + t.floor_divide_(1 << 16); + t = t.to(torch::kInt16); + } else if (dtype == torch::kUInt8) { + t.floor_divide_(1 << 24); + t += 128; + t = t.to(torch::kUInt8); + } else { + throw std::runtime_error("Unsupported dtype."); + } + if (channels_first) { + t = t.transpose(1, 0); + } + return t.contiguous(); +} + +torch::Tensor unnormalize_wav(const torch::Tensor input_tensor) { + const auto dtype = input_tensor.dtype(); + auto tensor = input_tensor; + if (dtype == torch::kFloat32) { + double multi_pos = 2147483647.; + double multi_neg = -2147483648.; + auto mult = (tensor > 0) * multi_pos - (tensor < 0) * multi_neg; + tensor = tensor.to(torch::dtype(torch::kFloat64)); + tensor *= mult; + tensor.clamp_(multi_neg, multi_pos); + tensor = tensor.to(torch::dtype(torch::kInt32)); + } else if (dtype == torch::kInt32) { + // already denormalized + } else if (dtype == torch::kInt16) { + tensor = tensor.to(torch::dtype(torch::kInt32)); + tensor *= ((tensor != 0) * 65536); + } else if (dtype == torch::kUInt8) { + tensor = tensor.to(torch::dtype(torch::kInt32)); + tensor -= 128; + tensor *= 16777216; + } else { + throw std::runtime_error("Unexpected dtype."); + } + return tensor; +} + +const std::string get_filetype(const std::string path) { + std::string ext = path.substr(path.find_last_of(".") + 1); + std::transform(ext.begin(), ext.end(), ext.begin(), ::tolower); + return ext; +} + +sox_encoding_t get_encoding( + const std::string filetype, + const caffe2::TypeMeta dtype) { + if (filetype == "mp3") + return SOX_ENCODING_MP3; + if (filetype == "flac") + return SOX_ENCODING_FLAC; + if (filetype == "ogg" || filetype == "vorbis") + return SOX_ENCODING_VORBIS; + if (filetype == "wav") { + if (dtype == torch::kUInt8) + return SOX_ENCODING_UNSIGNED; + if (dtype == torch::kInt16) + return SOX_ENCODING_SIGN2; + if (dtype == torch::kInt32) + return SOX_ENCODING_SIGN2; + if (dtype == torch::kFloat32) + return SOX_ENCODING_FLOAT; + throw std::runtime_error("Unsupported dtype."); + } + throw std::runtime_error("Unsupported file type."); +} + +unsigned get_precision( + const std::string filetype, + const caffe2::TypeMeta dtype) { + if (filetype == "mp3") + return SOX_UNSPEC; + if (filetype == "flac") + return 24; + if (filetype == "ogg" || filetype == "vorbis") + return SOX_UNSPEC; + if (filetype == "wav") { + if (dtype == torch::kUInt8) + return 8; + if (dtype == torch::kInt16) + return 16; + if (dtype == torch::kInt32) + return 32; + if (dtype == torch::kFloat32) + return 32; + throw std::runtime_error("Unsupported dtype."); + } + throw std::runtime_error("Unsupported file type."); +} + +sox_signalinfo_t get_signalinfo( + const torch::Tensor& tensor, + const int64_t sample_rate, + const bool channels_first, + const std::string filetype) { + return sox_signalinfo_t{ + /*rate=*/static_cast(sample_rate), + /*channels=*/static_cast(tensor.size(channels_first ? 0 : 1)), + /*precision=*/get_precision(filetype, tensor.dtype()), + /*length=*/static_cast(tensor.numel())}; +} + +sox_encodinginfo_t get_encodinginfo( + const std::string filetype, + const caffe2::TypeMeta dtype, + const double compression) { + const double compression_ = [&]() { + if (filetype == "mp3") + return compression; + if (filetype == "flac") + return compression; + if (filetype == "ogg" || filetype == "vorbis") + return compression; + if (filetype == "wav") + return 0.; + throw std::runtime_error("Unsupported file type."); + }(); + + return sox_encodinginfo_t{/*encoding=*/get_encoding(filetype, dtype), + /*bits_per_sample=*/get_precision(filetype, dtype), + /*compression=*/compression_, + /*reverse_bytes=*/sox_option_default, + /*reverse_nibbles=*/sox_option_default, + /*reverse_bits=*/sox_option_default, + /*opposite_endian=*/sox_false}; +} + +} // namespace sox_utils +} // namespace torchaudio diff --git a/torchaudio/csrc/sox_utils.h b/torchaudio/csrc/sox_utils.h new file mode 100644 index 0000000000..665187c840 --- /dev/null +++ b/torchaudio/csrc/sox_utils.h @@ -0,0 +1,100 @@ +#ifndef TORCHAUDIO_SOX_UTILS_H +#define TORCHAUDIO_SOX_UTILS_H + +#include +#include + +namespace torchaudio { +namespace sox_utils { + +struct TensorSignal : torch::CustomClassHolder { + torch::Tensor tensor; + int64_t sample_rate; + bool channels_first; + + TensorSignal( + torch::Tensor tensor_, + int64_t sample_rate_, + bool channels_first_); + + torch::Tensor getTensor() const; + int64_t getSampleRate() const; + bool getChannelsFirst() const; +}; + +/// helper class to automatically close sox_format_t* +struct SoxFormat { + explicit SoxFormat(sox_format_t* fd) noexcept; + SoxFormat(const SoxFormat& other) = delete; + SoxFormat(SoxFormat&& other) = delete; + SoxFormat& operator=(const SoxFormat& other) = delete; + SoxFormat& operator=(SoxFormat&& other) = delete; + ~SoxFormat(); + sox_format_t* operator->() const noexcept; + operator sox_format_t*() const noexcept; + + private: + sox_format_t* fd_; +}; + +/// +/// Verify that input file is found, has known encoding, and not empty +void validate_input_file(const SoxFormat& sf); + +/// +/// Verify that input Tensor is 2D, CPU and either uin8, int16, int32 or float32 +void validate_input_tensor(const torch::Tensor); + +/// +/// Get target dtype for the given encoding and precision. +caffe2::TypeMeta get_dtype( + const sox_encoding_t encoding, + const unsigned precision); + +/// +/// Convert sox_sample_t buffer to uint8/int16/int32/float32 Tensor +/// NOTE: This function might modify the values in the input buffer to +/// reduce the number of memory copy. +/// @param buffer Pointer to buffer that contains audio data. +/// @param num_samples The number of samples to read. +/// @param num_channels The number of channels. Used to reshape the resulting +/// Tensor. +/// @param dtype Target dtype. Determines the output dtype and value range in +/// conjunction with normalization. +/// @param noramlize Perform normalization. Only effective when dtype is not +/// kFloat32. When effective, the output tensor is kFloat32 type and value range +/// is [-1.0, 1.0] +/// @param channels_first When True, output Tensor has shape of [num_channels, +/// num_frames]. +torch::Tensor convert_to_tensor( + sox_sample_t* buffer, + const int32_t num_samples, + const int32_t num_channels, + const caffe2::TypeMeta dtype, + const bool normalize, + const bool channels_first); + +/// +/// Convert float32/int32/int16/uint8 Tensor to int32 for Torch -> Sox +/// conversion. +torch::Tensor unnormalize_wav(const torch::Tensor); + +/// Extract extension from file path +const std::string get_filetype(const std::string path); + +/// Get sox_signalinfo_t for passing a torch::Tensor object. +sox_signalinfo_t get_signalinfo( + const torch::Tensor& tensor, + const int64_t sample_rate, + const bool channels_first, + const std::string filetype); + +/// Get sox_encofinginfo_t for saving audoi file +sox_encodinginfo_t get_encodinginfo( + const std::string filetype, + const caffe2::TypeMeta dtype, + const double compression); + +} // namespace sox_utils +} // namespace torchaudio +#endif diff --git a/torchaudio/csrc/typedefs.cpp b/torchaudio/csrc/typedefs.cpp deleted file mode 100644 index 7b81d665dc..0000000000 --- a/torchaudio/csrc/typedefs.cpp +++ /dev/null @@ -1,23 +0,0 @@ -#include - -namespace torchaudio { -SignalInfo::SignalInfo( - const int64_t sample_rate_, - const int64_t num_channels_, - const int64_t num_samples_) - : sample_rate(sample_rate_), - num_channels(num_channels_), - num_samples(num_samples_){}; - -int64_t SignalInfo::getSampleRate() const { - return sample_rate; -} - -int64_t SignalInfo::getNumChannels() const { - return num_channels; -} - -int64_t SignalInfo::getNumSamples() const { - return num_samples; -} -} // namespace torchaudio diff --git a/torchaudio/csrc/typedefs.h b/torchaudio/csrc/typedefs.h deleted file mode 100644 index 646ed09f3d..0000000000 --- a/torchaudio/csrc/typedefs.h +++ /dev/null @@ -1,23 +0,0 @@ -#ifndef TORCHAUDIO_TYPDEFS_H -#define TORCHAUDIO_TYPDEFS_H - -#include - -namespace torchaudio { -struct SignalInfo : torch::CustomClassHolder { - int64_t sample_rate; - int64_t num_channels; - int64_t num_samples; - - SignalInfo( - const int64_t sample_rate_, - const int64_t num_channels_, - const int64_t num_samples_); - int64_t getSampleRate() const; - int64_t getNumChannels() const; - int64_t getNumSamples() const; -}; - -} // namespace torchaudio - -#endif diff --git a/torchaudio/extension/extension.py b/torchaudio/extension/extension.py index 4a2ab82124..b01ba13e39 100644 --- a/torchaudio/extension/extension.py +++ b/torchaudio/extension/extension.py @@ -12,38 +12,9 @@ def _init_extension(): _init_script_module(ext) else: warnings.warn('torchaudio C++ extension is not available.') - _init_dummy_module() def _init_script_module(module): path = importlib.util.find_spec(module).origin torch.classes.load_library(path) torch.ops.load_library(path) - - -def _init_dummy_module(): - class SignalInfo: - """Data class for audio format information - - Used when torchaudio C++ extension is not available for annotating - sox_io backend functions so that torchaudio is still importable - without extension. - This class has to implement the same interface as C++ equivalent. - """ - def __init__(self, sample_rate: int, num_channels: int, num_samples: int): - self.sample_rate = sample_rate - self.num_channels = num_channels - self.num_samples = num_samples - - def get_sample_rate(self): - return self.sample_rate - - def get_num_channels(self): - return self.num_channels - - def get_num_samples(self): - return self.num_samples - - DummyModule = namedtuple('torchaudio', ['SignalInfo']) - module = DummyModule(SignalInfo) - setattr(torch.classes, 'torchaudio', module) diff --git a/torchaudio/functional.py b/torchaudio/functional.py index 28cb6a3fa2..78c8c594c9 100644 --- a/torchaudio/functional.py +++ b/torchaudio/functional.py @@ -485,9 +485,10 @@ def complex_norm( Returns: Tensor: Power of the normed input tensor. Shape of `(..., )` """ - if power == 1.0: - return torch.norm(complex_tensor, 2, -1) - return torch.norm(complex_tensor, 2, -1).pow(power) + + # Replace by torch.norm once issue is fixed + # https://github.com/pytorch/pytorch/issues/34279 + return complex_tensor.pow(2.).sum(-1).pow(0.5 * power) def angle( diff --git a/torchaudio/models/_wavernn.py b/torchaudio/models/_wavernn.py index 04155fb87c..cd2e89a10c 100644 --- a/torchaudio/models/_wavernn.py +++ b/torchaudio/models/_wavernn.py @@ -1,105 +1,331 @@ +from typing import List + +import torch from torch import Tensor from torch import nn -__all__ = ["_ResBlock", "_MelResNet"] +__all__ = ["_ResBlock", "_MelResNet", "_Stretch2d", "_UpsampleNetwork", "_WaveRNN"] class _ResBlock(nn.Module): - r"""This is a ResNet block layer. This layer is based on the paper "Deep Residual Learning - for Image Recognition". Kaiming He, Xiangyu Zhang, Shaoqing Ren, Jian Sun. CVPR, 2016. - It is a block used in WaveRNN. WaveRNN is based on the paper "Efficient Neural Audio Synthesis". - Nal Kalchbrenner, Erich Elsen, Karen Simonyan, Seb Noury, Norman Casagrande, Edward Lockhart, - Florian Stimberg, Aaron van den Oord, Sander Dieleman, Koray Kavukcuoglu. arXiv:1802.08435, 2018. + r"""ResNet block based on "Deep Residual Learning for Image Recognition" + + The paper link is https://arxiv.org/pdf/1512.03385.pdf. Args: - num_dims: the number of compute dimensions in the input (default=128). + n_freq: the number of bins in a spectrogram (default=128) - Examples:: - >>> resblock = _ResBlock(num_dims=128) - >>> input = torch.rand(10, 128, 512) - >>> output = resblock(input) + Examples + >>> resblock = _ResBlock() + >>> input = torch.rand(10, 128, 512) # a random spectrogram + >>> output = resblock(input) # shape: (10, 128, 512) """ - def __init__(self, num_dims: int = 128) -> None: + def __init__(self, n_freq: int = 128) -> None: super().__init__() self.resblock_model = nn.Sequential( - nn.Conv1d(in_channels=num_dims, out_channels=num_dims, kernel_size=1, bias=False), - nn.BatchNorm1d(num_dims), + nn.Conv1d(in_channels=n_freq, out_channels=n_freq, kernel_size=1, bias=False), + nn.BatchNorm1d(n_freq), nn.ReLU(inplace=True), - nn.Conv1d(in_channels=num_dims, out_channels=num_dims, kernel_size=1, bias=False), - nn.BatchNorm1d(num_dims) + nn.Conv1d(in_channels=n_freq, out_channels=n_freq, kernel_size=1, bias=False), + nn.BatchNorm1d(n_freq) ) - def forward(self, x: Tensor) -> Tensor: + def forward(self, specgram: Tensor) -> Tensor: r"""Pass the input through the _ResBlock layer. - Args: - x: the input sequence to the _ResBlock layer (required). + specgram (Tensor): the input sequence to the _ResBlock layer (n_batch, n_freq, n_time). - Shape: - - x: :math:`(N, S, T)`. - - output: :math:`(N, S, T)`. - where N is the batch size, S is the number of input sequence, - T is the length of input sequence. + Return: + Tensor shape: (n_batch, n_freq, n_time) """ - residual = x - return self.resblock_model(x) + residual + return self.resblock_model(specgram) + specgram class _MelResNet(nn.Module): - r"""This is a MelResNet layer based on a stack of ResBlocks. It is a block used in WaveRNN. - WaveRNN is based on the paper "Efficient Neural Audio Synthesis". Nal Kalchbrenner, Erich Elsen, - Karen Simonyan, Seb Noury, Norman Casagrande, Edward Lockhart, Florian Stimberg, Aaron van den Oord, - Sander Dieleman, Koray Kavukcuoglu. arXiv:1802.08435, 2018. + r"""MelResNet layer uses a stack of ResBlocks on spectrogram. Args: - res_blocks: the number of ResBlock in stack (default=10). - input_dims: the number of input sequence (default=100). - hidden_dims: the number of compute dimensions (default=128). - output_dims: the number of output sequence (default=128). - pad: the number of kernal size (pad * 2 + 1) in the first Conv1d layer (default=2). - - Examples:: - >>> melresnet = _MelResNet(res_blocks=10, input_dims=100, - hidden_dims=128, output_dims=128, pad=2) - >>> input = torch.rand(10, 100, 512) - >>> output = melresnet(input) + n_res_block: the number of ResBlock in stack (default=10) + n_freq: the number of bins in a spectrogram (default=128) + n_hidden: the number of hidden dimensions (default=128) + n_output: the number of output dimensions (default=128) + kernel_size: the number of kernel size in the first Conv1d layer (default=5) + + Examples + >>> melresnet = _MelResNet() + >>> input = torch.rand(10, 128, 512) # a random spectrogram + >>> output = melresnet(input) # shape: (10, 128, 508) """ - def __init__(self, res_blocks: int = 10, - input_dims: int = 100, - hidden_dims: int = 128, - output_dims: int = 128, - pad: int = 2) -> None: + def __init__(self, + n_res_block: int = 10, + n_freq: int = 128, + n_hidden: int = 128, + n_output: int = 128, + kernel_size: int = 5) -> None: super().__init__() - kernel_size = pad * 2 + 1 - ResBlocks = [] - - for i in range(res_blocks): - ResBlocks.append(_ResBlock(hidden_dims)) + ResBlocks = [_ResBlock(n_hidden) for _ in range(n_res_block)] self.melresnet_model = nn.Sequential( - nn.Conv1d(in_channels=input_dims, out_channels=hidden_dims, kernel_size=kernel_size, bias=False), - nn.BatchNorm1d(hidden_dims), + nn.Conv1d(in_channels=n_freq, out_channels=n_hidden, kernel_size=kernel_size, bias=False), + nn.BatchNorm1d(n_hidden), nn.ReLU(inplace=True), *ResBlocks, - nn.Conv1d(in_channels=hidden_dims, out_channels=output_dims, kernel_size=1) + nn.Conv1d(in_channels=n_hidden, out_channels=n_output, kernel_size=1) ) - def forward(self, x: Tensor) -> Tensor: + def forward(self, specgram: Tensor) -> Tensor: r"""Pass the input through the _MelResNet layer. + Args: + specgram (Tensor): the input sequence to the _MelResNet layer (n_batch, n_freq, n_time). + + Return: + Tensor shape: (n_batch, n_output, n_time - kernel_size + 1) + """ + + return self.melresnet_model(specgram) + + +class _Stretch2d(nn.Module): + r"""Upscale the frequency and time dimensions of a spectrogram. + + Args: + time_scale: the scale factor in time dimension + freq_scale: the scale factor in frequency dimension + + Examples + >>> stretch2d = _Stretch2d(time_scale=10, freq_scale=5) + + >>> input = torch.rand(10, 100, 512) # a random spectrogram + >>> output = stretch2d(input) # shape: (10, 500, 5120) + """ + + def __init__(self, + time_scale: int, + freq_scale: int) -> None: + super().__init__() + + self.freq_scale = freq_scale + self.time_scale = time_scale + + def forward(self, specgram: Tensor) -> Tensor: + r"""Pass the input through the _Stretch2d layer. Args: - x: the input sequence to the _MelResNet layer (required). + specgram (Tensor): the input sequence to the _Stretch2d layer (..., n_freq, n_time). - Shape: - - x: :math:`(N, S, T)`. - - output: :math:`(N, P, T - 2 * pad)`. - where N is the batch size, S is the number of input sequence, - P is the number of output sequence, T is the length of input sequence. + Return: + Tensor shape: (..., n_freq * freq_scale, n_time * time_scale) """ - return self.melresnet_model(x) + return specgram.repeat_interleave(self.freq_scale, -2).repeat_interleave(self.time_scale, -1) + + +class _UpsampleNetwork(nn.Module): + r"""Upscale the dimensions of a spectrogram. + + Args: + upsample_scales: the list of upsample scales + n_res_block: the number of ResBlock in stack (default=10) + n_freq: the number of bins in a spectrogram (default=128) + n_hidden: the number of hidden dimensions (default=128) + n_output: the number of output dimensions (default=128) + kernel_size: the number of kernel size in the first Conv1d layer (default=5) + + Examples + >>> upsamplenetwork = _UpsampleNetwork(upsample_scales=[4, 4, 16]) + >>> input = torch.rand(10, 128, 10) # a random spectrogram + >>> output = upsamplenetwork(input) # shape: (10, 1536, 128), (10, 1536, 128) + """ + + def __init__(self, + upsample_scales: List[int], + n_res_block: int = 10, + n_freq: int = 128, + n_hidden: int = 128, + n_output: int = 128, + kernel_size: int = 5) -> None: + super().__init__() + + total_scale = 1 + for upsample_scale in upsample_scales: + total_scale *= upsample_scale + + self.indent = (kernel_size - 1) // 2 * total_scale + self.resnet = _MelResNet(n_res_block, n_freq, n_hidden, n_output, kernel_size) + self.resnet_stretch = _Stretch2d(total_scale, 1) + + up_layers = [] + for scale in upsample_scales: + stretch = _Stretch2d(scale, 1) + conv = nn.Conv2d(in_channels=1, + out_channels=1, + kernel_size=(1, scale * 2 + 1), + padding=(0, scale), + bias=False) + conv.weight.data.fill_(1. / (scale * 2 + 1)) + up_layers.append(stretch) + up_layers.append(conv) + self.upsample_layers = nn.Sequential(*up_layers) + + def forward(self, specgram: Tensor) -> Tensor: + r"""Pass the input through the _UpsampleNetwork layer. + + Args: + specgram (Tensor): the input sequence to the _UpsampleNetwork layer (n_batch, n_freq, n_time) + + Return: + Tensor shape: (n_batch, n_freq, (n_time - kernel_size + 1) * total_scale), + (n_batch, n_output, (n_time - kernel_size + 1) * total_scale) + where total_scale is the product of all elements in upsample_scales. + """ + + resnet_output = self.resnet(specgram).unsqueeze(1) + resnet_output = self.resnet_stretch(resnet_output) + resnet_output = resnet_output.squeeze(1) + + specgram = specgram.unsqueeze(1) + upsampling_output = self.upsample_layers(specgram) + upsampling_output = upsampling_output.squeeze(1)[:, :, self.indent:-self.indent] + + return upsampling_output, resnet_output + + +class _WaveRNN(nn.Module): + r"""WaveRNN model based on the implementation from `fatchord `_. + + The original implementation was introduced in + `"Efficient Neural Audio Synthesis" `_. + The input channels of waveform and spectrogram have to be 1. The product of + `upsample_scales` must equal `hop_length`. + + Args: + upsample_scales: the list of upsample scales + n_bits: the bits of output waveform + sample_rate: the rate of audio dimensions (samples per second) + hop_length: the number of samples between the starts of consecutive frames + n_res_block: the number of ResBlock in stack (default=10) + n_rnn: the dimension of RNN layer (default=512) + n_fc: the dimension of fully connected layer (default=512) + kernel_size: the number of kernel size in the first Conv1d layer (default=5) + n_freq: the number of bins in a spectrogram (default=128) + n_hidden: the number of hidden dimensions (default=128) + n_output: the number of output dimensions (default=128) + mode: the mode of waveform in ['waveform', 'mol'] (default='waveform') + + Example + >>> wavernn = _waveRNN(upsample_scales=[5,5,8], n_bits=9, sample_rate=24000, hop_length=200) + >>> waveform, sample_rate = torchaudio.load(file) + >>> # waveform shape: (n_batch, n_channel, (n_time - kernel_size + 1) * hop_length) + >>> specgram = MelSpectrogram(sample_rate)(waveform) # shape: (n_batch, n_channel, n_freq, n_time) + >>> output = wavernn(waveform, specgram) + >>> # output shape: (n_batch, n_channel, (n_time - kernel_size + 1) * hop_length, 2 ** n_bits) + """ + + def __init__(self, + upsample_scales: List[int], + n_bits: int, + sample_rate: int, + hop_length: int, + n_res_block: int = 10, + n_rnn: int = 512, + n_fc: int = 512, + kernel_size: int = 5, + n_freq: int = 128, + n_hidden: int = 128, + n_output: int = 128, + mode: str = 'waveform') -> None: + super().__init__() + + self.mode = mode + self.kernel_size = kernel_size + + if self.mode == 'waveform': + self.n_classes = 2 ** n_bits + elif self.mode == 'mol': + self.n_classes = 30 + else: + raise ValueError(f"Expected mode: `waveform` or `mol`, but found {self.mode}") + + self.n_rnn = n_rnn + self.n_aux = n_output // 4 + self.hop_length = hop_length + self.sample_rate = sample_rate + + total_scale = 1 + for upsample_scale in upsample_scales: + total_scale *= upsample_scale + if total_scale != self.hop_length: + raise ValueError(f"Expected: total_scale == hop_length, but found {total_scale} != {hop_length}") + + self.upsample = _UpsampleNetwork(upsample_scales, n_res_block, n_freq, n_hidden, n_output, kernel_size) + self.fc = nn.Linear(n_freq + self.n_aux + 1, n_rnn) + + self.rnn1 = nn.GRU(n_rnn, n_rnn, batch_first=True) + self.rnn2 = nn.GRU(n_rnn + self.n_aux, n_rnn, batch_first=True) + + self.relu1 = nn.ReLU(inplace=True) + self.relu2 = nn.ReLU(inplace=True) + + self.fc1 = nn.Linear(n_rnn + self.n_aux, n_fc) + self.fc2 = nn.Linear(n_fc + self.n_aux, n_fc) + self.fc3 = nn.Linear(n_fc, self.n_classes) + + def forward(self, waveform: Tensor, specgram: Tensor) -> Tensor: + r"""Pass the input through the _WaveRNN model. + + Args: + waveform: the input waveform to the _WaveRNN layer (n_batch, 1, (n_time - kernel_size + 1) * hop_length) + specgram: the input spectrogram to the _WaveRNN layer (n_batch, 1, n_freq, n_time) + + Return: + Tensor shape: (n_batch, 1, (n_time - kernel_size + 1) * hop_length, 2 ** n_bits) + """ + + assert waveform.size(1) == 1, 'Require the input channel of waveform is 1' + assert specgram.size(1) == 1, 'Require the input channel of specgram is 1' + # remove channel dimension until the end + waveform, specgram = waveform.squeeze(1), specgram.squeeze(1) + + batch_size = waveform.size(0) + h1 = torch.zeros(1, batch_size, self.n_rnn, dtype=waveform.dtype, device=waveform.device) + h2 = torch.zeros(1, batch_size, self.n_rnn, dtype=waveform.dtype, device=waveform.device) + # output of upsample: + # specgram: (n_batch, n_freq, (n_time - kernel_size + 1) * total_scale) + # aux: (n_batch, n_output, (n_time - kernel_size + 1) * total_scale) + specgram, aux = self.upsample(specgram) + specgram = specgram.transpose(1, 2) + aux = aux.transpose(1, 2) + + aux_idx = [self.n_aux * i for i in range(5)] + a1 = aux[:, :, aux_idx[0]:aux_idx[1]] + a2 = aux[:, :, aux_idx[1]:aux_idx[2]] + a3 = aux[:, :, aux_idx[2]:aux_idx[3]] + a4 = aux[:, :, aux_idx[3]:aux_idx[4]] + + x = torch.cat([waveform.unsqueeze(-1), specgram, a1], dim=-1) + x = self.fc(x) + res = x + x, _ = self.rnn1(x, h1) + + x = x + res + res = x + x = torch.cat([x, a2], dim=-1) + x, _ = self.rnn2(x, h2) + + x = x + res + x = torch.cat([x, a3], dim=-1) + x = self.fc1(x) + x = self.relu1(x) + + x = torch.cat([x, a4], dim=-1) + x = self.fc2(x) + x = self.relu2(x) + x = self.fc3(x) + + # bring back channel dimension + return x.unsqueeze(1) diff --git a/torchaudio/sox_effects/__init__.py b/torchaudio/sox_effects/__init__.py index 115b70c895..507dc5c3af 100644 --- a/torchaudio/sox_effects/__init__.py +++ b/torchaudio/sox_effects/__init__.py @@ -9,4 +9,6 @@ if _mod_utils.is_module_available('torchaudio._torchaudio'): + import atexit init_sox_effects() + atexit.register(shutdown_sox_effects) diff --git a/torchaudio/sox_effects/sox_effects.py b/torchaudio/sox_effects/sox_effects.py index 6a6b5be0a5..0aee312126 100644 --- a/torchaudio/sox_effects/sox_effects.py +++ b/torchaudio/sox_effects/sox_effects.py @@ -1,4 +1,3 @@ -import atexit from typing import Any, Callable, List, Optional, Tuple, Union import torch @@ -13,19 +12,8 @@ from torchaudio import _torchaudio -_SOX_INITIALIZED: Optional[bool] = False -# This variable has a micro lifecycle. (False -> True -> None) -# False: Not initialized -# True: Initialized -# None: Already shut down (should not be initialized again.) - -_SOX_SUCCESS_CODE = 0 -# defined at -# https://fossies.org/dox/sox-14.4.2/sox_8h.html#a8e07e80cebeff3339265d89c387cea93a9ef2b87ec303edfe40751d9a85fadeeb - - @_mod_utils.requires_module('torchaudio._torchaudio') -def init_sox_effects() -> int: +def init_sox_effects() -> None: """Initialize resources required to use ``SoxEffectsChain`` You do not need to call this function manually. It is called automatically. @@ -33,50 +21,26 @@ def init_sox_effects() -> int: Once initialized, you do not need to call this function again across the multiple call of ``SoxEffectsChain.sox_build_flow_effects``, though it is safe to do so as long as ``shutdown_sox_effects`` is not called yet. - Once ``shutdown_sox_effects`` is called, you can no longer use SoX effects and calling - this function results in `RuntimeError`. + Once ``shutdown_sox_effects`` is called, you can no longer use SoX effects and + initializing again will result in error. Note: This function is not required for simple loading. - - Returns: - int: Code corresponding to sox_error_t enum. See - https://fossies.org/dox/sox-14.4.2/sox_8h.html#a8e07e80cebeff3339265d89c387cea93 """ - global _SOX_INITIALIZED - if _SOX_INITIALIZED is None: - raise RuntimeError('SoX effects chain has been already shut down. Can not initialize again.') - if not _SOX_INITIALIZED: - code = _torchaudio.initialize_sox() - if code == _SOX_SUCCESS_CODE: - _SOX_INITIALIZED = True - atexit.register(shutdown_sox_effects) - return code - return _SOX_SUCCESS_CODE + torch.ops.torchaudio.sox_effects_initialize_sox_effects() @_mod_utils.requires_module("torchaudio._torchaudio") -def shutdown_sox_effects() -> int: +def shutdown_sox_effects() -> None: """Clean up resources required to use ``SoxEffectsChain`` You do not need to call this function manually. It is called automatically. It is safe to call this function multiple times. - Once ``shutdown_sox_effects`` is called, you can no longer use SoX effects and calling - this function results in `RuntimeError`. - - - Returns: - int: Code corresponding to sox_error_t enum. See - https://fossies.org/dox/sox-14.4.2/sox_8h.html#a8e07e80cebeff3339265d89c387cea93 + Once ``shutdown_sox_effects`` is called, you can no longer use SoX effects and + initializing again will result in error. """ - global _SOX_INITIALIZED - if _SOX_INITIALIZED: - code = _torchaudio.shutdown_sox() - if code == _SOX_INITIALIZED: - _SOX_INITIALIZED = None - return code - return _SOX_SUCCESS_CODE + torch.ops.torchaudio.sox_effects_shutdown_sox_effects() @_mod_utils.requires_module('torchaudio._torchaudio') @@ -88,7 +52,7 @@ def effect_names() -> List[str]: Example >>> EFFECT_NAMES = torchaudio.sox_effects.effect_names() """ - return _torchaudio.get_effect_names() + return torch.ops.torchaudio.sox_effects_list_effects() @_mod_utils.requires_module('torchaudio._torchaudio') From fd7460ecfbfa47ff1612fba939b7dc47aae613dd Mon Sep 17 00:00:00 2001 From: Stanislau Hlebik Date: Fri, 17 Jul 2020 17:07:23 -0700 Subject: [PATCH 11/73] remediation of S205607 fbshipit-source-id: 5113fe0c527595e4227ff827253b7414abbdf7ac --- .python3 | 1 + build_tools/__init__.py | 1 + examples/test/__init__.py | 1 + test/compliance/__init__.py | 1 + test/sox_io_backend/__init__.py | 1 + torchaudio/_internal/__init__.py | 1 + 6 files changed, 6 insertions(+) diff --git a/.python3 b/.python3 index e69de29bb2..56de9c5ee1 100644 --- a/.python3 +++ b/.python3 @@ -0,0 +1 @@ +S205607 diff --git a/build_tools/__init__.py b/build_tools/__init__.py index e69de29bb2..56de9c5ee1 100644 --- a/build_tools/__init__.py +++ b/build_tools/__init__.py @@ -0,0 +1 @@ +S205607 diff --git a/examples/test/__init__.py b/examples/test/__init__.py index e69de29bb2..56de9c5ee1 100644 --- a/examples/test/__init__.py +++ b/examples/test/__init__.py @@ -0,0 +1 @@ +S205607 diff --git a/test/compliance/__init__.py b/test/compliance/__init__.py index e69de29bb2..56de9c5ee1 100644 --- a/test/compliance/__init__.py +++ b/test/compliance/__init__.py @@ -0,0 +1 @@ +S205607 diff --git a/test/sox_io_backend/__init__.py b/test/sox_io_backend/__init__.py index e69de29bb2..56de9c5ee1 100644 --- a/test/sox_io_backend/__init__.py +++ b/test/sox_io_backend/__init__.py @@ -0,0 +1 @@ +S205607 diff --git a/torchaudio/_internal/__init__.py b/torchaudio/_internal/__init__.py index e69de29bb2..56de9c5ee1 100644 --- a/torchaudio/_internal/__init__.py +++ b/torchaudio/_internal/__init__.py @@ -0,0 +1 @@ +S205607 From 4f19eef10cfcef472ab534b5907b3e2e38f2843d Mon Sep 17 00:00:00 2001 From: Stanislau Hlebik Date: Fri, 17 Jul 2020 17:07:23 -0700 Subject: [PATCH 12/73] remediation of S205607 fbshipit-source-id: 798decc90db4f13770e97cdce3c0df7d5421b2a3 --- .python3 | 1 - build_tools/__init__.py | 1 - examples/test/__init__.py | 1 - test/compliance/__init__.py | 1 - test/sox_io_backend/__init__.py | 1 - torchaudio/_internal/__init__.py | 1 - 6 files changed, 6 deletions(-) diff --git a/.python3 b/.python3 index 56de9c5ee1..e69de29bb2 100644 --- a/.python3 +++ b/.python3 @@ -1 +0,0 @@ -S205607 diff --git a/build_tools/__init__.py b/build_tools/__init__.py index 56de9c5ee1..e69de29bb2 100644 --- a/build_tools/__init__.py +++ b/build_tools/__init__.py @@ -1 +0,0 @@ -S205607 diff --git a/examples/test/__init__.py b/examples/test/__init__.py index 56de9c5ee1..e69de29bb2 100644 --- a/examples/test/__init__.py +++ b/examples/test/__init__.py @@ -1 +0,0 @@ -S205607 diff --git a/test/compliance/__init__.py b/test/compliance/__init__.py index 56de9c5ee1..e69de29bb2 100644 --- a/test/compliance/__init__.py +++ b/test/compliance/__init__.py @@ -1 +0,0 @@ -S205607 diff --git a/test/sox_io_backend/__init__.py b/test/sox_io_backend/__init__.py index 56de9c5ee1..e69de29bb2 100644 --- a/test/sox_io_backend/__init__.py +++ b/test/sox_io_backend/__init__.py @@ -1 +0,0 @@ -S205607 diff --git a/torchaudio/_internal/__init__.py b/torchaudio/_internal/__init__.py index 56de9c5ee1..e69de29bb2 100644 --- a/torchaudio/_internal/__init__.py +++ b/torchaudio/_internal/__init__.py @@ -1 +0,0 @@ -S205607 From 57a88cd7d91f0cdeab39b7e1fae55e6bb22bc41c Mon Sep 17 00:00:00 2001 From: Moto Hira Date: Mon, 27 Jul 2020 06:03:09 -0700 Subject: [PATCH 13/73] Import torchaudio 20200723 Summary: Import torchaudio 20200723 #814 Reviewed By: fmassa Differential Revision: D22666393 fbshipit-source-id: 50df07b5c158fe4e95ada7ea54381b2e26f6aecd --- .circleci/config.yml | 1342 +++++++++++++++++ .circleci/config.yml.in | 631 ++++++++ .circleci/regenerate.py | 180 +++ .circleci/smoke_test/docker/Dockerfile | 36 + .circleci/test/test_sort_yaml.py | 14 + .circleci/unittest/linux/README.md | 6 + .circleci/unittest/linux/docker/.dockerignore | 2 + .circleci/unittest/linux/docker/.gitignore | 2 + .circleci/unittest/linux/docker/Dockerfile | 59 + .../unittest/linux/docker/build_and_push.sh | 27 + .../docker/scripts/copy_kaldi_executables.sh | 58 + .../unittest/linux/scripts/environment.yml | 17 + .circleci/unittest/linux/scripts/install.sh | 23 + .../unittest/linux/scripts/post_process.sh | 8 + .../linux/scripts/run_style_checks.sh | 32 + .circleci/unittest/linux/scripts/run_test.sh | 10 + .circleci/unittest/linux/scripts/setup_env.sh | 50 + .circleci/unittest/windows/README.md | 4 + .../unittest/windows/scripts/environment.yml | 18 + .circleci/unittest/windows/scripts/install.sh | 23 + .../windows/scripts/install_conda.bat | 1 + .../unittest/windows/scripts/post_process.sh | 8 + .../unittest/windows/scripts/run_test.sh | 10 + .../unittest/windows/scripts/setup_env.sh | 39 + .clang-format | 88 ++ .clang-tidy | 33 + .flake8 | 4 + .github/ISSUE_TEMPLATE/bug-report.md | 53 + .github/ISSUE_TEMPLATE/documentation.md | 9 + .github/ISSUE_TEMPLATE/feature-request.md | 24 + .../ISSUE_TEMPLATE/questions-help-support.md | 13 + .github/pytorch-probot.yml | 1 + .gitignore | 129 ++ .travis.yml | 32 + docs/source/backend.rst | 138 ++ docs/source/datasets.rst | 8 + docs/source/index.rst | 15 +- docs/source/sox_effects.rst | 47 +- docs/source/torchaudio.rst | 43 + docs/source/utils.rst | 11 + examples/pipeline_wavernn/README.md | 36 + examples/pipeline_wavernn/datasets.py | 115 ++ examples/pipeline_wavernn/losses.py | 119 ++ examples/pipeline_wavernn/main.py | 390 +++++ examples/pipeline_wavernn/processing.py | 58 + examples/pipeline_wavernn/utils.py | 61 + test/README.md | 2 +- test/assets/100Hz_44100Hz_16bit_05sec.wav | Bin 444524 -> 0 bytes test/assets/440Hz_44100Hz_16bit_05sec.wav | Bin 444524 -> 0 bytes test/assets/genres/noise/noise.0000.wav | Bin 223532 -> 0 bytes test/assets/sox_effect_test_args.json | 88 ++ test/assets/sox_effect_test_fir_coeffs.txt | 1 + test/assets/waves_yesno/0_1_0_1_0_1_1_0.wav | Bin 84 -> 0 bytes test/assets/whitenoise.mp3 | Bin 57136 -> 0 bytes test/assets/whitenoise.wav | Bin 441078 -> 0 bytes test/assets/whitenoise_1min.mp3 | Bin 666705 -> 0 bytes test/common_utils/backend_utils.py | 4 +- test/common_utils/case_utils.py | 21 +- test/common_utils/data_utils.py | 44 +- test/common_utils/sox_utils.py | 21 + test/datasets/__init__.py | 0 .../datasets_test.py} | 29 +- test/datasets/gtzan_test.py | 88 ++ test/datasets/libritts_test.py | 71 + test/datasets/utils_test.py | 47 + test/datasets/yesno_test.py | 49 + test/functional_cpu_test.py | 31 +- test/sox_effect/__init__.py | 0 test/sox_effect/common.py | 26 + test/sox_effect/smoke_test.py | 59 + .../sox_effects_chain_test.py} | 58 +- test/sox_effect/test_dataset.py | 114 ++ test/sox_effect/test_sox_effect.py | 221 +++ test/sox_effect/test_torchscript.py | 100 ++ test/sox_io_backend/smoke_test.py | 87 ++ test/test_batch_consistency.py | 32 +- test/test_compliance_kaldi.py | 59 +- test/test_dataloader.py | 4 - test/test_io.py | 3 - test/test_kaldi_io.py | 4 - test/test_librosa_compatibility.py | 11 +- test/test_models.py | 47 +- test/test_sox_compatibility.py | 534 +++---- test/test_transforms.py | 4 - test/utils/__init__.py | 0 test/utils/test_sox_utils.py | 49 + torchaudio/__init__.py | 7 +- torchaudio/_internal/module_utils.py | 2 +- torchaudio/backend/common.py | 26 + torchaudio/backend/sox_io_backend.py | 159 +- torchaudio/backend/utils.py | 19 +- torchaudio/csrc/register.cpp | 33 +- torchaudio/csrc/sox_effects.cpp | 135 +- torchaudio/csrc/sox_effects.h | 11 +- torchaudio/csrc/sox_effects_chain.cpp | 287 ++++ torchaudio/csrc/sox_effects_chain.h | 42 + torchaudio/csrc/sox_io.cpp | 98 +- torchaudio/csrc/sox_utils.cpp | 66 +- torchaudio/csrc/sox_utils.h | 32 +- torchaudio/datasets/__init__.py | 2 + torchaudio/datasets/gtzan.py | 49 +- torchaudio/datasets/libritts.py | 131 ++ torchaudio/datasets/utils.py | 8 +- torchaudio/functional.py | 4 +- torchaudio/models/_wavernn.py | 80 +- torchaudio/models/wav2letter.py | 9 +- torchaudio/sox_effects/__init__.py | 2 + torchaudio/sox_effects/sox_effects.py | 322 +++- torchaudio/transforms.py | 37 +- torchaudio/utils/__init__.py | 9 + torchaudio/utils/sox_utils.py | 94 ++ 111 files changed, 6697 insertions(+), 902 deletions(-) create mode 100644 .circleci/config.yml create mode 100644 .circleci/config.yml.in create mode 100755 .circleci/regenerate.py create mode 100644 .circleci/smoke_test/docker/Dockerfile create mode 100755 .circleci/test/test_sort_yaml.py create mode 100644 .circleci/unittest/linux/README.md create mode 100644 .circleci/unittest/linux/docker/.dockerignore create mode 100644 .circleci/unittest/linux/docker/.gitignore create mode 100644 .circleci/unittest/linux/docker/Dockerfile create mode 100755 .circleci/unittest/linux/docker/build_and_push.sh create mode 100755 .circleci/unittest/linux/docker/scripts/copy_kaldi_executables.sh create mode 100644 .circleci/unittest/linux/scripts/environment.yml create mode 100755 .circleci/unittest/linux/scripts/install.sh create mode 100755 .circleci/unittest/linux/scripts/post_process.sh create mode 100755 .circleci/unittest/linux/scripts/run_style_checks.sh create mode 100755 .circleci/unittest/linux/scripts/run_test.sh create mode 100755 .circleci/unittest/linux/scripts/setup_env.sh create mode 100644 .circleci/unittest/windows/README.md create mode 100644 .circleci/unittest/windows/scripts/environment.yml create mode 100644 .circleci/unittest/windows/scripts/install.sh create mode 100644 .circleci/unittest/windows/scripts/install_conda.bat create mode 100644 .circleci/unittest/windows/scripts/post_process.sh create mode 100644 .circleci/unittest/windows/scripts/run_test.sh create mode 100644 .circleci/unittest/windows/scripts/setup_env.sh create mode 100644 .clang-format create mode 100644 .clang-tidy create mode 100644 .flake8 create mode 100644 .github/ISSUE_TEMPLATE/bug-report.md create mode 100644 .github/ISSUE_TEMPLATE/documentation.md create mode 100644 .github/ISSUE_TEMPLATE/feature-request.md create mode 100644 .github/ISSUE_TEMPLATE/questions-help-support.md create mode 100644 .github/pytorch-probot.yml create mode 100644 .gitignore create mode 100644 .travis.yml create mode 100644 docs/source/backend.rst create mode 100644 docs/source/torchaudio.rst create mode 100644 docs/source/utils.rst create mode 100644 examples/pipeline_wavernn/README.md create mode 100644 examples/pipeline_wavernn/datasets.py create mode 100644 examples/pipeline_wavernn/losses.py create mode 100644 examples/pipeline_wavernn/main.py create mode 100644 examples/pipeline_wavernn/processing.py create mode 100644 examples/pipeline_wavernn/utils.py delete mode 100644 test/assets/100Hz_44100Hz_16bit_05sec.wav delete mode 100644 test/assets/440Hz_44100Hz_16bit_05sec.wav delete mode 100644 test/assets/genres/noise/noise.0000.wav create mode 100644 test/assets/sox_effect_test_args.json create mode 100644 test/assets/sox_effect_test_fir_coeffs.txt delete mode 100644 test/assets/waves_yesno/0_1_0_1_0_1_1_0.wav delete mode 100644 test/assets/whitenoise.mp3 delete mode 100644 test/assets/whitenoise.wav delete mode 100644 test/assets/whitenoise_1min.mp3 create mode 100644 test/datasets/__init__.py rename test/{test_datasets.py => datasets/datasets_test.py} (71%) create mode 100644 test/datasets/gtzan_test.py create mode 100644 test/datasets/libritts_test.py create mode 100644 test/datasets/utils_test.py create mode 100644 test/datasets/yesno_test.py create mode 100644 test/sox_effect/__init__.py create mode 100644 test/sox_effect/common.py create mode 100644 test/sox_effect/smoke_test.py rename test/{test_sox_effects.py => sox_effect/sox_effects_chain_test.py} (82%) create mode 100644 test/sox_effect/test_dataset.py create mode 100644 test/sox_effect/test_sox_effect.py create mode 100644 test/sox_effect/test_torchscript.py create mode 100644 test/sox_io_backend/smoke_test.py create mode 100644 test/utils/__init__.py create mode 100644 test/utils/test_sox_utils.py create mode 100644 torchaudio/csrc/sox_effects_chain.cpp create mode 100644 torchaudio/csrc/sox_effects_chain.h create mode 100644 torchaudio/datasets/libritts.py create mode 100644 torchaudio/utils/__init__.py create mode 100644 torchaudio/utils/sox_utils.py diff --git a/.circleci/config.yml b/.circleci/config.yml new file mode 100644 index 0000000000..771dccc515 --- /dev/null +++ b/.circleci/config.yml @@ -0,0 +1,1342 @@ +version: 2.1 + +# How to test the Linux jobs: +# - Install CircleCI local CLI: https://circleci.com/docs/2.0/local-cli/ +# - circleci config process .circleci/config.yml > gen.yml && circleci local execute -c gen.yml --job binary_linux_wheel_py3.8 +# - Replace binary_linux_wheel_py3.8 with the name of the job you want to test. +# Job names are 'name:' key. + +executors: + windows-cpu: + machine: + resource_class: windows.xlarge + image: windows-server-2019-vs2019:stable + shell: bash.exe + + windows-gpu: + machine: + resource_class: windows.gpu.nvidia.medium + image: windows-server-2019-nvidia:stable + shell: bash.exe + +commands: + generate_cache_key: + description: "Generates a cache key file that changes daily" + steps: + - run: + name: Generate cache key + command: echo "$(date +"%Y-%m-%d")" > .cachekey + designate_upload_channel: + description: "inserts the correct upload channel into ${BASH_ENV}" + steps: + - run: + name: adding UPLOAD_CHANNEL to BASH_ENV + command: | + our_upload_channel=nightly + # On tags upload to test instead + if [[ -n "${CIRCLE_TAG}" ]]; then + our_upload_channel=test + fi + echo "export UPLOAD_CHANNEL=${our_upload_channel}" >> ${BASH_ENV} + install_build_tools_macos: + description: "installs tools required to build torchaudio" + steps: + - run: + name: Install cmake and pkg-config + command: HOMEBREW_NO_AUTO_UPDATE=1 brew install cmake pkg-config wget + # Disable brew auto update which is very slow + +binary_common: &binary_common + parameters: + # Edit these defaults to do a release + build_version: + description: "version number of release binary; by default, build a nightly" + type: string + default: "" + pytorch_version: + description: "PyTorch version to build against; by default, use a nightly" + type: string + default: "" + # Don't edit these + python_version: + description: "Python version to build against (e.g., 3.8)" + type: string + environment: + PYTHON_VERSION: << parameters.python_version >> + BUILD_VERSION: << parameters.build_version >> + PYTORCH_VERSION: << parameters.pytorch_version >> + CU_VERSION: cpu + +smoke_test_common: &smoke_test_common + <<: *binary_common + docker: + - image: 308535385114.dkr.ecr.us-east-1.amazonaws.com/torchaudio/smoke_test:56c846a5-acaa-41a7-92f5-46ec66186c61 + aws_auth: + aws_access_key_id: ${ECR_AWS_ACCESS_KEY} + aws_secret_access_key: ${ECR_AWS_SECRET_ACCESS_KEY} + +jobs: + circleci_consistency: + docker: + - image: circleci/python:3.8 + steps: + - checkout + - run: + command: | + pip install --user --progress-bar off jinja2 pyyaml + python .circleci/regenerate.py + git diff --exit-code || (echo ".circleci/config.yml not in sync with config.yml.in! Run .circleci/regenerate.py to update config"; exit 1) + + download_third_parties_nix: + docker: + - image: "pytorch/torchaudio_unittest_base:manylinux" + resource_class: small + steps: + - checkout + - generate_cache_key + - restore_cache: + + keys: + - tp-nix-v2-{{ checksum ".cachekey" }} + + - run: + command: | + mkdir -p third_party/archives/ + wget --no-clobber --directory-prefix=third_party/archives/ $(awk '/URL /{print $2}' third_party/CMakeLists.txt) + - save_cache: + + key: tp-nix-v2-{{ checksum ".cachekey" }} + + paths: + - third_party/archives + - persist_to_workspace: + root: third_party + paths: + - archives + + binary_linux_wheel: + <<: *binary_common + docker: + - image: "pytorch/manylinux-cuda100" + resource_class: 2xlarge+ + steps: + - checkout + - attach_workspace: + at: third_party + - run: packaging/build_wheel.sh + - store_artifacts: + path: dist + - persist_to_workspace: + root: dist + paths: + - "*" + + binary_linux_conda: + <<: *binary_common + docker: + - image: "pytorch/conda-cuda" + resource_class: 2xlarge+ + steps: + - checkout + - attach_workspace: + at: third_party + - run: packaging/build_conda.sh + - store_artifacts: + path: /opt/conda/conda-bld/linux-64 + - persist_to_workspace: + root: /opt/conda/conda-bld/linux-64 + paths: + - "*" + + binary_macos_wheel: + <<: *binary_common + macos: + xcode: "9.0" + steps: + - checkout + - install_build_tools_macos + - attach_workspace: + at: third_party + - run: + # Cannot easily deduplicate this as source'ing activate + # will set environment variables which we need to propagate + # to build_wheel.sh + command: | + curl -o conda.sh https://repo.anaconda.com/miniconda/Miniconda3-latest-MacOSX-x86_64.sh + sh conda.sh -b + source $HOME/miniconda3/bin/activate + packaging/build_wheel.sh + - store_artifacts: + path: dist + - persist_to_workspace: + root: dist + paths: + - "*" + + binary_macos_conda: + <<: *binary_common + macos: + xcode: "9.0" + steps: + - checkout + - install_build_tools_macos + - attach_workspace: + at: third_party + - run: + command: | + curl -o conda.sh https://repo.anaconda.com/miniconda/Miniconda3-latest-MacOSX-x86_64.sh + sh conda.sh -b + source $HOME/miniconda3/bin/activate + conda install -yq conda-build + packaging/build_conda.sh + - store_artifacts: + path: /Users/distiller/miniconda3/conda-bld/osx-64 + - persist_to_workspace: + root: /Users/distiller/miniconda3/conda-bld/osx-64 + paths: + - "*" + + binary_windows_wheel: + <<: *binary_common + executor: + name: windows-cpu + steps: + - checkout + - run: + name: build + command: | + eval "$('/C/tools/miniconda3/Scripts/conda.exe' 'shell.bash' 'hook')" + conda activate base + bash packaging/build_wheel.sh + - store_artifacts: + path: dist + - persist_to_workspace: + root: dist + paths: + - "*" + + binary_windows_conda: + <<: *binary_common + executor: + name: windows-cpu + steps: + - checkout + - run: + name: build + command: | + eval "$('/C/tools/miniconda3/Scripts/conda.exe' 'shell.bash' 'hook')" + conda activate base + conda install -yq conda-build "conda-package-handling!=1.5.0" + bash packaging/build_conda.sh + - store_artifacts: + path: C:/tools/miniconda3/conda-bld/win-64 + - persist_to_workspace: + root: C:/tools/miniconda3/conda-bld/win-64 + paths: + - "*" + + # Requires org-member context + binary_conda_upload: + docker: + - image: continuumio/miniconda + steps: + - attach_workspace: + at: ~/workspace + - designate_upload_channel + - run: + command: | + # Prevent credential from leaking + conda install -yq anaconda-client + set -x + anaconda -t "${CONDA_PYTORCHBOT_TOKEN}" upload ~/workspace/*.tar.bz2 -u "pytorch-${UPLOAD_CHANNEL}" --label main --no-progress --force + + # Requires org-member context + binary_wheel_upload: + docker: + - image: circleci/python:3.8 + steps: + - attach_workspace: + at: ~/workspace + - checkout + - designate_upload_channel + - run: + command: | + pip install --user awscli + export PATH="$HOME/.local/bin:$PATH" + # Prevent credential from leaking + set +x + export AWS_ACCESS_KEY_ID="${PYTORCH_BINARY_AWS_ACCESS_KEY_ID}" + export AWS_SECRET_ACCESS_KEY="${PYTORCH_BINARY_AWS_SECRET_ACCESS_KEY}" + set -x + for pkg in ~/workspace/*.whl; do + aws s3 cp "$pkg" "s3://pytorch/whl/${UPLOAD_CHANNEL}/" --acl public-read + done + + smoke_test_linux_conda: + <<: *smoke_test_common + steps: + - attach_workspace: + at: ~/workspace + - run: + name: install binaries + command: | + set -x + source /usr/local/etc/profile.d/conda.sh && conda activate python${PYTHON_VERSION} + conda install -v -y -c pytorch-test -c pytorch-nightly pytorch + conda install -v -y $(ls ~/workspace/torchaudio*.tar.bz2) + - run: + name: smoke test + command: | + source /usr/local/etc/profile.d/conda.sh && conda activate python${PYTHON_VERSION} + python -c "import torchaudio" + + smoke_test_linux_pip: + <<: *smoke_test_common + steps: + - attach_workspace: + at: ~/workspace + - run: + name: install binaries + command: | + set -x + source /usr/local/etc/profile.d/conda.sh && conda activate python${PYTHON_VERSION} + pip install $(ls ~/workspace/torchaudio*.whl) -f https://download.pytorch.org/whl/nightly/torch_nightly.html -f https://download.pytorch.org/whl/test/torch_test.html + - run: + name: smoke test + command: | + source /usr/local/etc/profile.d/conda.sh && conda activate python${PYTHON_VERSION} + python -c "import torchaudio" + + smoke_test_windows_conda: + <<: *binary_common + executor: + name: windows-cpu + steps: + - attach_workspace: + at: ~/workspace + - run: + name: install binaries + command: | + set -x + eval "$('/C/tools/miniconda3/Scripts/conda.exe' 'shell.bash' 'hook')" + conda env remove -n python${PYTHON_VERSION} || true + conda create -yn python${PYTHON_VERSION} python=${PYTHON_VERSION} + conda activate python${PYTHON_VERSION} + conda install -v -y -c pytorch-test -c pytorch-nightly pytorch + conda install -v -y $(ls ~/workspace/torchaudio*.tar.bz2) + - run: + name: smoke test + command: | + eval "$('/C/tools/miniconda3/Scripts/conda.exe' 'shell.bash' 'hook')" + conda activate python${PYTHON_VERSION} + python -c "import torchaudio" + + smoke_test_windows_pip: + <<: *binary_common + executor: + name: windows-cpu + steps: + - attach_workspace: + at: ~/workspace + - run: + name: install binaries + command: | + set -x + eval "$('/C/tools/miniconda3/Scripts/conda.exe' 'shell.bash' 'hook')" + conda env remove -n python${PYTHON_VERSION} || true + conda create -yn python${PYTHON_VERSION} python=${PYTHON_VERSION} + conda activate python${PYTHON_VERSION} + pip install $(ls ~/workspace/torchaudio*.whl) -f https://download.pytorch.org/whl/nightly/torch_nightly.html -f https://download.pytorch.org/whl/test/torch_test.html + - run: + name: smoke test + command: | + eval "$('/C/tools/miniconda3/Scripts/conda.exe' 'shell.bash' 'hook')" + conda activate python${PYTHON_VERSION} + python -c "import torchaudio" + + smoke_test_docker_image_build: + machine: + image: ubuntu-1604:201903-01 + resource_class: large + environment: + image_name: torchaudio/smoke_test + steps: + - checkout + - run: + name: build_docker image + no_output_timeout: "1h" + command: | + cd .circleci/smoke_test/docker && docker build . -t ${image_name}:${CIRCLE_WORKFLOW_ID} + - run: + name: upload docker image + no_output_timeout: "1h" + command: | + set +x + export AWS_ACCESS_KEY_ID=${ECR_AWS_ACCESS_KEY} + export AWS_SECRET_ACCESS_KEY=${ECR_AWS_SECRET_ACCESS_KEY} + eval $(aws ecr get-login --region us-east-1 --no-include-email) + set -x + docker tag ${image_name}:${CIRCLE_WORKFLOW_ID} 308535385114.dkr.ecr.us-east-1.amazonaws.com/${image_name}:${CIRCLE_WORKFLOW_ID} + docker tag ${image_name}:${CIRCLE_WORKFLOW_ID} 308535385114.dkr.ecr.us-east-1.amazonaws.com/${image_name}:latest + docker push 308535385114.dkr.ecr.us-east-1.amazonaws.com/${image_name}:${CIRCLE_WORKFLOW_ID} + docker push 308535385114.dkr.ecr.us-east-1.amazonaws.com/${image_name}:latest + + unittest_linux_cpu: + <<: *binary_common + docker: + - image: "pytorch/torchaudio_unittest_base:manylinux" + resource_class: 2xlarge+ + steps: + - checkout + - attach_workspace: + at: third_party + - generate_cache_key + - restore_cache: + + keys: + - env-v3-linux-{{ arch }}-py<< parameters.python_version >>-{{ checksum ".circleci/unittest/linux/scripts/environment.yml" }}-{{ checksum "third_party/CMakeLists.txt" }}-{{ checksum ".cachekey" }} + + - run: + name: Setup + command: .circleci/unittest/linux/scripts/setup_env.sh + - save_cache: + + key: env-v3-linux-{{ arch }}-py<< parameters.python_version >>-{{ checksum ".circleci/unittest/linux/scripts/environment.yml" }}-{{ checksum "third_party/CMakeLists.txt" }}-{{ checksum ".cachekey" }} + + paths: + - conda + - env + - third_party/build + - third_party/install + - third_party/src + - run: + name: Install torchaudio + command: .circleci/unittest/linux/scripts/install.sh + - run: + name: Run tests + command: .circleci/unittest/linux/scripts/run_test.sh + - run: + name: Post process + command: .circleci/unittest/linux/scripts/post_process.sh + - store_test_results: + path: test-results + + unittest_linux_gpu: + <<: *binary_common + machine: + image: ubuntu-1604-cuda-10.1:201909-23 + resource_class: gpu.small + environment: + image_name: "pytorch/torchaudio_unittest_base:manylinux-cuda10.1" + steps: + - checkout + - attach_workspace: + at: third_party + - generate_cache_key + - restore_cache: + + keys: + - env-v3-linux-{{ arch }}-py<< parameters.python_version >>-{{ checksum ".circleci/unittest/linux/scripts/environment.yml" }}-{{ checksum "third_party/CMakeLists.txt" }}-{{ checksum ".cachekey" }} + + - run: + name: Setup + command: docker run -t --gpus all -v $PWD:$PWD -w $PWD "${image_name}" .circleci/unittest/linux/scripts/setup_env.sh + - save_cache: + + key: env-v3-linux-{{ arch }}-py<< parameters.python_version >>-{{ checksum ".circleci/unittest/linux/scripts/environment.yml" }}-{{ checksum "third_party/CMakeLists.txt" }}-{{ checksum ".cachekey" }} + + paths: + - conda + - env + - third_party/build + - third_party/install + - third_party/src + - run: + name: Install torchaudio + command: docker run -t --gpus all -v $PWD:$PWD -w $PWD "${image_name}" .circleci/unittest/linux/scripts/install.sh + - run: + name: Run tests + command: docker run -t --gpus all -v $PWD:$PWD -w $PWD "${image_name}" .circleci/unittest/linux/scripts/run_test.sh + - run: + name: Post Process + command: docker run -t --gpus all -v $PWD:$PWD -w $PWD "${image_name}" .circleci/unittest/linux/scripts/post_process.sh + - store_test_results: + path: test-results + + unittest_windows_cpu: + <<: *binary_common + executor: + name: windows-cpu + steps: + - checkout + - generate_cache_key + - restore_cache: + + keys: + - env-v3-windows-{{ arch }}-py<< parameters.python_version >>-{{ checksum ".circleci/unittest/windows/scripts/environment.yml" }}-{{ checksum ".cachekey" }} + + - run: + name: Setup + command: .circleci/unittest/windows/scripts/setup_env.sh + - save_cache: + + key: env-v3-windows-{{ arch }}-py<< parameters.python_version >>-{{ checksum ".circleci/unittest/windows/scripts/environment.yml" }}-{{ checksum ".cachekey" }} + + paths: + - conda + - env + - run: + name: Install torchaudio + command: .circleci/unittest/windows/scripts/install.sh + - run: + name: Run tests + command: .circleci/unittest/windows/scripts/run_test.sh + - run: + name: Post process + command: .circleci/unittest/windows/scripts/post_process.sh + - store_test_results: + path: test-results + + unittest_windows_gpu: + <<: *binary_common + executor: + name: windows-gpu + environment: + CUDA_VERSION: "10.1" + steps: + - checkout + - generate_cache_key + - restore_cache: + + keys: + - env-v1-windows-{{ arch }}-py<< parameters.python_version >>-{{ checksum ".circleci/unittest/windows/scripts/environment.yml" }}-{{ checksum ".cachekey" }} + + - run: + name: Setup + command: .circleci/unittest/windows/scripts/setup_env.sh + - save_cache: + + key: env-v1-windows-{{ arch }}-py<< parameters.python_version >>-{{ checksum ".circleci/unittest/windows/scripts/environment.yml" }}-{{ checksum ".cachekey" }} + + paths: + - conda + - env + - run: + name: Install torchaudio + command: .circleci/unittest/windows/scripts/install.sh + - run: + name: Run tests + command: .circleci/unittest/windows/scripts/run_test.sh + - run: + name: Post process + command: .circleci/unittest/windows/scripts/post_process.sh + - store_test_results: + path: test-results + + unittest_macos_cpu: + <<: *binary_common + macos: + xcode: "9.0" + resource_class: large + steps: + - checkout + - install_build_tools_macos + - attach_workspace: + at: third_party + - generate_cache_key + - restore_cache: + + keys: + - env-v3-macos-{{ arch }}-py<< parameters.python_version >>-{{ checksum ".circleci/unittest/linux/scripts/environment.yml" }}-{{ checksum "third_party/CMakeLists.txt" }}-{{ checksum ".cachekey" }} + + - run: + name: Setup + command: .circleci/unittest/linux/scripts/setup_env.sh + - save_cache: + + key: env-v3-macos-{{ arch }}-py<< parameters.python_version >>-{{ checksum ".circleci/unittest/linux/scripts/environment.yml" }}-{{ checksum "third_party/CMakeLists.txt" }}-{{ checksum ".cachekey" }} + + paths: + - conda + - env + - third_party/build + - third_party/install + - third_party/src + - run: + name: Install torchaudio + command: .circleci/unittest/linux/scripts/install.sh + - run: + name: Run tests + command: .circleci/unittest/linux/scripts/run_test.sh + - run: + name: Post process + command: .circleci/unittest/linux/scripts/post_process.sh + - store_test_results: + path: test-results + + stylecheck: + <<: *binary_common + docker: + - image: "pytorch/torchaudio_unittest_base:manylinux" + resource_class: medium + steps: + - checkout + - generate_cache_key + - restore_cache: + + keys: + - env-v2-linux-{{ arch }}-py<< parameters.python_version >>-{{ checksum ".circleci/unittest/linux/scripts/environment.yml" }}-{{ checksum ".cachekey" }} + + - run: + name: Setup + command: .circleci/unittest/linux/scripts/setup_env.sh + - save_cache: + + key: env-v2-linux-{{ arch }}-py<< parameters.python_version >>-{{ checksum ".circleci/unittest/linux/scripts/environment.yml" }}-{{ checksum ".cachekey" }} + + paths: + - conda + - env + - third_party/build + - third_party/install + - third_party/src + - run: + name: Run style check + command: .circleci/unittest/linux/scripts/run_style_checks.sh + +workflows: + build: + jobs: + - circleci_consistency + - download_third_parties_nix: + name: download_third_parties_nix + - binary_linux_wheel: + name: binary_linux_wheel_py3.6 + python_version: '3.6' + requires: + - download_third_parties_nix + - binary_linux_wheel: + name: binary_linux_wheel_py3.7 + python_version: '3.7' + requires: + - download_third_parties_nix + - binary_linux_wheel: + name: binary_linux_wheel_py3.8 + python_version: '3.8' + requires: + - download_third_parties_nix + - binary_macos_wheel: + name: binary_macos_wheel_py3.6 + python_version: '3.6' + requires: + - download_third_parties_nix + - binary_macos_wheel: + name: binary_macos_wheel_py3.7 + python_version: '3.7' + requires: + - download_third_parties_nix + - binary_macos_wheel: + name: binary_macos_wheel_py3.8 + python_version: '3.8' + requires: + - download_third_parties_nix + - binary_windows_wheel: + name: binary_windows_wheel_py3.6 + python_version: '3.6' + - binary_windows_wheel: + name: binary_windows_wheel_py3.7 + python_version: '3.7' + - binary_windows_wheel: + name: binary_windows_wheel_py3.8 + python_version: '3.8' + - binary_linux_conda: + name: binary_linux_conda_py3.6 + python_version: '3.6' + requires: + - download_third_parties_nix + - binary_linux_conda: + name: binary_linux_conda_py3.7 + python_version: '3.7' + requires: + - download_third_parties_nix + - binary_linux_conda: + name: binary_linux_conda_py3.8 + python_version: '3.8' + requires: + - download_third_parties_nix + - binary_macos_conda: + name: binary_macos_conda_py3.6 + python_version: '3.6' + requires: + - download_third_parties_nix + - binary_macos_conda: + name: binary_macos_conda_py3.7 + python_version: '3.7' + requires: + - download_third_parties_nix + - binary_macos_conda: + name: binary_macos_conda_py3.8 + python_version: '3.8' + requires: + - download_third_parties_nix + - binary_windows_conda: + name: binary_windows_conda_py3.6 + python_version: '3.6' + - binary_windows_conda: + name: binary_windows_conda_py3.7 + python_version: '3.7' + - binary_windows_conda: + name: binary_windows_conda_py3.8 + python_version: '3.8' + unittest: + jobs: + - download_third_parties_nix: + name: download_third_parties_nix + - unittest_linux_cpu: + name: unittest_linux_cpu_py3.6 + python_version: '3.6' + requires: + - download_third_parties_nix + - stylecheck: + name: stylecheck_py3.6 + python_version: '3.6' + - unittest_linux_cpu: + name: unittest_linux_cpu_py3.7 + python_version: '3.7' + requires: + - download_third_parties_nix + - unittest_linux_cpu: + name: unittest_linux_cpu_py3.8 + python_version: '3.8' + requires: + - download_third_parties_nix + - unittest_linux_gpu: + filters: + branches: + only: + - master + - nightly + tags: + only: /v[0-9]+(\.[0-9]+)*-rc[0-9]+/ + name: unittest_linux_gpu_py3.6 + python_version: '3.6' + requires: + - download_third_parties_nix + - unittest_linux_gpu: + filters: + branches: + only: + - master + - nightly + tags: + only: /v[0-9]+(\.[0-9]+)*-rc[0-9]+/ + name: unittest_linux_gpu_py3.7 + python_version: '3.7' + requires: + - download_third_parties_nix + - unittest_linux_gpu: + filters: + branches: + only: + - master + - nightly + tags: + only: /v[0-9]+(\.[0-9]+)*-rc[0-9]+/ + name: unittest_linux_gpu_py3.8 + python_version: '3.8' + requires: + - download_third_parties_nix + - unittest_windows_cpu: + name: unittest_windows_cpu_py3.6 + python_version: '3.6' + - unittest_windows_cpu: + name: unittest_windows_cpu_py3.7 + python_version: '3.7' + - unittest_windows_cpu: + name: unittest_windows_cpu_py3.8 + python_version: '3.8' + - unittest_windows_gpu: + filters: + branches: + only: + - master + - nightly + tags: + only: /v[0-9]+(\.[0-9]+)*-rc[0-9]+/ + name: unittest_windows_gpu_py3.6 + python_version: '3.6' + - unittest_windows_gpu: + filters: + branches: + only: + - master + - nightly + tags: + only: /v[0-9]+(\.[0-9]+)*-rc[0-9]+/ + name: unittest_windows_gpu_py3.7 + python_version: '3.7' + - unittest_windows_gpu: + filters: + branches: + only: + - master + - nightly + tags: + only: /v[0-9]+(\.[0-9]+)*-rc[0-9]+/ + name: unittest_windows_gpu_py3.8 + python_version: '3.8' + - unittest_macos_cpu: + name: unittest_macos_cpu_py3.6 + python_version: '3.6' + requires: + - download_third_parties_nix + - unittest_macos_cpu: + name: unittest_macos_cpu_py3.7 + python_version: '3.7' + requires: + - download_third_parties_nix + - unittest_macos_cpu: + name: unittest_macos_cpu_py3.8 + python_version: '3.8' + requires: + - download_third_parties_nix + nightly: + jobs: + - circleci_consistency: + filters: + branches: + only: nightly + - download_third_parties_nix: + filters: + branches: + only: + - nightly + tags: + only: /v[0-9]+(\.[0-9]+)*-rc[0-9]+/ + name: download_third_parties_nix + - binary_linux_wheel: + filters: + branches: + only: + - nightly + tags: + only: /v[0-9]+(\.[0-9]+)*-rc[0-9]+/ + name: nightly_binary_linux_wheel_py3.6 + python_version: '3.6' + requires: + - download_third_parties_nix + - binary_wheel_upload: + context: org-member + filters: + branches: + only: + - nightly + tags: + only: /v[0-9]+(\.[0-9]+)*-rc[0-9]+/ + name: nightly_binary_linux_wheel_py3.6_upload + requires: + - nightly_binary_linux_wheel_py3.6 + - smoke_test_linux_pip: + filters: + branches: + only: + - nightly + tags: + only: /v[0-9]+(\.[0-9]+)*-rc[0-9]+/ + name: nightly_binary_linux_wheel_py3.6_smoke_test_pip + python_version: '3.6' + requires: + - nightly_binary_linux_wheel_py3.6_upload + - binary_linux_wheel: + filters: + branches: + only: + - nightly + tags: + only: /v[0-9]+(\.[0-9]+)*-rc[0-9]+/ + name: nightly_binary_linux_wheel_py3.7 + python_version: '3.7' + requires: + - download_third_parties_nix + - binary_wheel_upload: + context: org-member + filters: + branches: + only: + - nightly + tags: + only: /v[0-9]+(\.[0-9]+)*-rc[0-9]+/ + name: nightly_binary_linux_wheel_py3.7_upload + requires: + - nightly_binary_linux_wheel_py3.7 + - smoke_test_linux_pip: + filters: + branches: + only: + - nightly + tags: + only: /v[0-9]+(\.[0-9]+)*-rc[0-9]+/ + name: nightly_binary_linux_wheel_py3.7_smoke_test_pip + python_version: '3.7' + requires: + - nightly_binary_linux_wheel_py3.7_upload + - binary_linux_wheel: + filters: + branches: + only: + - nightly + tags: + only: /v[0-9]+(\.[0-9]+)*-rc[0-9]+/ + name: nightly_binary_linux_wheel_py3.8 + python_version: '3.8' + requires: + - download_third_parties_nix + - binary_wheel_upload: + context: org-member + filters: + branches: + only: + - nightly + tags: + only: /v[0-9]+(\.[0-9]+)*-rc[0-9]+/ + name: nightly_binary_linux_wheel_py3.8_upload + requires: + - nightly_binary_linux_wheel_py3.8 + - smoke_test_linux_pip: + filters: + branches: + only: + - nightly + tags: + only: /v[0-9]+(\.[0-9]+)*-rc[0-9]+/ + name: nightly_binary_linux_wheel_py3.8_smoke_test_pip + python_version: '3.8' + requires: + - nightly_binary_linux_wheel_py3.8_upload + - binary_macos_wheel: + filters: + branches: + only: + - nightly + tags: + only: /v[0-9]+(\.[0-9]+)*-rc[0-9]+/ + name: nightly_binary_macos_wheel_py3.6 + python_version: '3.6' + requires: + - download_third_parties_nix + - binary_wheel_upload: + context: org-member + filters: + branches: + only: + - nightly + tags: + only: /v[0-9]+(\.[0-9]+)*-rc[0-9]+/ + name: nightly_binary_macos_wheel_py3.6_upload + requires: + - nightly_binary_macos_wheel_py3.6 + - binary_macos_wheel: + filters: + branches: + only: + - nightly + tags: + only: /v[0-9]+(\.[0-9]+)*-rc[0-9]+/ + name: nightly_binary_macos_wheel_py3.7 + python_version: '3.7' + requires: + - download_third_parties_nix + - binary_wheel_upload: + context: org-member + filters: + branches: + only: + - nightly + tags: + only: /v[0-9]+(\.[0-9]+)*-rc[0-9]+/ + name: nightly_binary_macos_wheel_py3.7_upload + requires: + - nightly_binary_macos_wheel_py3.7 + - binary_macos_wheel: + filters: + branches: + only: + - nightly + tags: + only: /v[0-9]+(\.[0-9]+)*-rc[0-9]+/ + name: nightly_binary_macos_wheel_py3.8 + python_version: '3.8' + requires: + - download_third_parties_nix + - binary_wheel_upload: + context: org-member + filters: + branches: + only: + - nightly + tags: + only: /v[0-9]+(\.[0-9]+)*-rc[0-9]+/ + name: nightly_binary_macos_wheel_py3.8_upload + requires: + - nightly_binary_macos_wheel_py3.8 + - binary_windows_wheel: + filters: + branches: + only: + - nightly + tags: + only: /v[0-9]+(\.[0-9]+)*-rc[0-9]+/ + name: nightly_binary_windows_wheel_py3.6 + python_version: '3.6' + - binary_wheel_upload: + context: org-member + filters: + branches: + only: + - nightly + tags: + only: /v[0-9]+(\.[0-9]+)*-rc[0-9]+/ + name: nightly_binary_windows_wheel_py3.6_upload + requires: + - nightly_binary_windows_wheel_py3.6 + - smoke_test_windows_pip: + filters: + branches: + only: + - nightly + tags: + only: /v[0-9]+(\.[0-9]+)*-rc[0-9]+/ + name: nightly_binary_windows_wheel_py3.6_smoke_test_pip + python_version: '3.6' + requires: + - nightly_binary_windows_wheel_py3.6_upload + - binary_windows_wheel: + filters: + branches: + only: + - nightly + tags: + only: /v[0-9]+(\.[0-9]+)*-rc[0-9]+/ + name: nightly_binary_windows_wheel_py3.7 + python_version: '3.7' + - binary_wheel_upload: + context: org-member + filters: + branches: + only: + - nightly + tags: + only: /v[0-9]+(\.[0-9]+)*-rc[0-9]+/ + name: nightly_binary_windows_wheel_py3.7_upload + requires: + - nightly_binary_windows_wheel_py3.7 + - smoke_test_windows_pip: + filters: + branches: + only: + - nightly + tags: + only: /v[0-9]+(\.[0-9]+)*-rc[0-9]+/ + name: nightly_binary_windows_wheel_py3.7_smoke_test_pip + python_version: '3.7' + requires: + - nightly_binary_windows_wheel_py3.7_upload + - binary_windows_wheel: + filters: + branches: + only: + - nightly + tags: + only: /v[0-9]+(\.[0-9]+)*-rc[0-9]+/ + name: nightly_binary_windows_wheel_py3.8 + python_version: '3.8' + - binary_wheel_upload: + context: org-member + filters: + branches: + only: + - nightly + tags: + only: /v[0-9]+(\.[0-9]+)*-rc[0-9]+/ + name: nightly_binary_windows_wheel_py3.8_upload + requires: + - nightly_binary_windows_wheel_py3.8 + - smoke_test_windows_pip: + filters: + branches: + only: + - nightly + tags: + only: /v[0-9]+(\.[0-9]+)*-rc[0-9]+/ + name: nightly_binary_windows_wheel_py3.8_smoke_test_pip + python_version: '3.8' + requires: + - nightly_binary_windows_wheel_py3.8_upload + - binary_linux_conda: + filters: + branches: + only: + - nightly + tags: + only: /v[0-9]+(\.[0-9]+)*-rc[0-9]+/ + name: nightly_binary_linux_conda_py3.6 + python_version: '3.6' + requires: + - download_third_parties_nix + - binary_conda_upload: + context: org-member + filters: + branches: + only: + - nightly + tags: + only: /v[0-9]+(\.[0-9]+)*-rc[0-9]+/ + name: nightly_binary_linux_conda_py3.6_upload + requires: + - nightly_binary_linux_conda_py3.6 + - smoke_test_linux_conda: + filters: + branches: + only: + - nightly + tags: + only: /v[0-9]+(\.[0-9]+)*-rc[0-9]+/ + name: nightly_binary_linux_conda_py3.6_smoke_test_conda + python_version: '3.6' + requires: + - nightly_binary_linux_conda_py3.6_upload + - binary_linux_conda: + filters: + branches: + only: + - nightly + tags: + only: /v[0-9]+(\.[0-9]+)*-rc[0-9]+/ + name: nightly_binary_linux_conda_py3.7 + python_version: '3.7' + requires: + - download_third_parties_nix + - binary_conda_upload: + context: org-member + filters: + branches: + only: + - nightly + tags: + only: /v[0-9]+(\.[0-9]+)*-rc[0-9]+/ + name: nightly_binary_linux_conda_py3.7_upload + requires: + - nightly_binary_linux_conda_py3.7 + - smoke_test_linux_conda: + filters: + branches: + only: + - nightly + tags: + only: /v[0-9]+(\.[0-9]+)*-rc[0-9]+/ + name: nightly_binary_linux_conda_py3.7_smoke_test_conda + python_version: '3.7' + requires: + - nightly_binary_linux_conda_py3.7_upload + - binary_linux_conda: + filters: + branches: + only: + - nightly + tags: + only: /v[0-9]+(\.[0-9]+)*-rc[0-9]+/ + name: nightly_binary_linux_conda_py3.8 + python_version: '3.8' + requires: + - download_third_parties_nix + - binary_conda_upload: + context: org-member + filters: + branches: + only: + - nightly + tags: + only: /v[0-9]+(\.[0-9]+)*-rc[0-9]+/ + name: nightly_binary_linux_conda_py3.8_upload + requires: + - nightly_binary_linux_conda_py3.8 + - smoke_test_linux_conda: + filters: + branches: + only: + - nightly + tags: + only: /v[0-9]+(\.[0-9]+)*-rc[0-9]+/ + name: nightly_binary_linux_conda_py3.8_smoke_test_conda + python_version: '3.8' + requires: + - nightly_binary_linux_conda_py3.8_upload + - binary_macos_conda: + filters: + branches: + only: + - nightly + tags: + only: /v[0-9]+(\.[0-9]+)*-rc[0-9]+/ + name: nightly_binary_macos_conda_py3.6 + python_version: '3.6' + requires: + - download_third_parties_nix + - binary_conda_upload: + context: org-member + filters: + branches: + only: + - nightly + tags: + only: /v[0-9]+(\.[0-9]+)*-rc[0-9]+/ + name: nightly_binary_macos_conda_py3.6_upload + requires: + - nightly_binary_macos_conda_py3.6 + - binary_macos_conda: + filters: + branches: + only: + - nightly + tags: + only: /v[0-9]+(\.[0-9]+)*-rc[0-9]+/ + name: nightly_binary_macos_conda_py3.7 + python_version: '3.7' + requires: + - download_third_parties_nix + - binary_conda_upload: + context: org-member + filters: + branches: + only: + - nightly + tags: + only: /v[0-9]+(\.[0-9]+)*-rc[0-9]+/ + name: nightly_binary_macos_conda_py3.7_upload + requires: + - nightly_binary_macos_conda_py3.7 + - binary_macos_conda: + filters: + branches: + only: + - nightly + tags: + only: /v[0-9]+(\.[0-9]+)*-rc[0-9]+/ + name: nightly_binary_macos_conda_py3.8 + python_version: '3.8' + requires: + - download_third_parties_nix + - binary_conda_upload: + context: org-member + filters: + branches: + only: + - nightly + tags: + only: /v[0-9]+(\.[0-9]+)*-rc[0-9]+/ + name: nightly_binary_macos_conda_py3.8_upload + requires: + - nightly_binary_macos_conda_py3.8 + - binary_windows_conda: + filters: + branches: + only: + - nightly + tags: + only: /v[0-9]+(\.[0-9]+)*-rc[0-9]+/ + name: nightly_binary_windows_conda_py3.6 + python_version: '3.6' + - binary_conda_upload: + context: org-member + filters: + branches: + only: + - nightly + tags: + only: /v[0-9]+(\.[0-9]+)*-rc[0-9]+/ + name: nightly_binary_windows_conda_py3.6_upload + requires: + - nightly_binary_windows_conda_py3.6 + - smoke_test_windows_conda: + filters: + branches: + only: + - nightly + tags: + only: /v[0-9]+(\.[0-9]+)*-rc[0-9]+/ + name: nightly_binary_windows_conda_py3.6_smoke_test_conda + python_version: '3.6' + requires: + - nightly_binary_windows_conda_py3.6_upload + - binary_windows_conda: + filters: + branches: + only: + - nightly + tags: + only: /v[0-9]+(\.[0-9]+)*-rc[0-9]+/ + name: nightly_binary_windows_conda_py3.7 + python_version: '3.7' + - binary_conda_upload: + context: org-member + filters: + branches: + only: + - nightly + tags: + only: /v[0-9]+(\.[0-9]+)*-rc[0-9]+/ + name: nightly_binary_windows_conda_py3.7_upload + requires: + - nightly_binary_windows_conda_py3.7 + - smoke_test_windows_conda: + filters: + branches: + only: + - nightly + tags: + only: /v[0-9]+(\.[0-9]+)*-rc[0-9]+/ + name: nightly_binary_windows_conda_py3.7_smoke_test_conda + python_version: '3.7' + requires: + - nightly_binary_windows_conda_py3.7_upload + - binary_windows_conda: + filters: + branches: + only: + - nightly + tags: + only: /v[0-9]+(\.[0-9]+)*-rc[0-9]+/ + name: nightly_binary_windows_conda_py3.8 + python_version: '3.8' + - binary_conda_upload: + context: org-member + filters: + branches: + only: + - nightly + tags: + only: /v[0-9]+(\.[0-9]+)*-rc[0-9]+/ + name: nightly_binary_windows_conda_py3.8_upload + requires: + - nightly_binary_windows_conda_py3.8 + - smoke_test_windows_conda: + filters: + branches: + only: + - nightly + tags: + only: /v[0-9]+(\.[0-9]+)*-rc[0-9]+/ + name: nightly_binary_windows_conda_py3.8_smoke_test_conda + python_version: '3.8' + requires: + - nightly_binary_windows_conda_py3.8_upload + docker_build: + triggers: + - schedule: + cron: "0 10 * * 0" + filters: + branches: + only: + - master + jobs: + - smoke_test_docker_image_build \ No newline at end of file diff --git a/.circleci/config.yml.in b/.circleci/config.yml.in new file mode 100644 index 0000000000..6d6d77d50f --- /dev/null +++ b/.circleci/config.yml.in @@ -0,0 +1,631 @@ +version: 2.1 + +# How to test the Linux jobs: +# - Install CircleCI local CLI: https://circleci.com/docs/2.0/local-cli/ +# - circleci config process .circleci/config.yml > gen.yml && circleci local execute -c gen.yml --job binary_linux_wheel_py3.8 +# - Replace binary_linux_wheel_py3.8 with the name of the job you want to test. +# Job names are 'name:' key. + +executors: + windows-cpu: + machine: + resource_class: windows.xlarge + image: windows-server-2019-vs2019:stable + shell: bash.exe + + windows-gpu: + machine: + resource_class: windows.gpu.nvidia.medium + image: windows-server-2019-nvidia:stable + shell: bash.exe + +commands: + generate_cache_key: + description: "Generates a cache key file that changes daily" + steps: + - run: + name: Generate cache key + command: echo "$(date +"%Y-%m-%d")" > .cachekey + designate_upload_channel: + description: "inserts the correct upload channel into ${BASH_ENV}" + steps: + - run: + name: adding UPLOAD_CHANNEL to BASH_ENV + command: | + our_upload_channel=nightly + # On tags upload to test instead + if [[ -n "${CIRCLE_TAG}" ]]; then + our_upload_channel=test + fi + echo "export UPLOAD_CHANNEL=${our_upload_channel}" >> ${BASH_ENV} + install_build_tools_macos: + description: "installs tools required to build torchaudio" + steps: + - run: + name: Install cmake and pkg-config + command: HOMEBREW_NO_AUTO_UPDATE=1 brew install cmake pkg-config wget + # Disable brew auto update which is very slow + +binary_common: &binary_common + parameters: + # Edit these defaults to do a release + build_version: + description: "version number of release binary; by default, build a nightly" + type: string + default: "" + pytorch_version: + description: "PyTorch version to build against; by default, use a nightly" + type: string + default: "" + # Don't edit these + python_version: + description: "Python version to build against (e.g., 3.8)" + type: string + environment: + PYTHON_VERSION: << parameters.python_version >> + BUILD_VERSION: << parameters.build_version >> + PYTORCH_VERSION: << parameters.pytorch_version >> + CU_VERSION: cpu + +smoke_test_common: &smoke_test_common + <<: *binary_common + docker: + - image: 308535385114.dkr.ecr.us-east-1.amazonaws.com/torchaudio/smoke_test:56c846a5-acaa-41a7-92f5-46ec66186c61 + aws_auth: + aws_access_key_id: ${ECR_AWS_ACCESS_KEY} + aws_secret_access_key: ${ECR_AWS_SECRET_ACCESS_KEY} + +jobs: + circleci_consistency: + docker: + - image: circleci/python:3.8 + steps: + - checkout + - run: + command: | + pip install --user --progress-bar off jinja2 pyyaml + python .circleci/regenerate.py + git diff --exit-code || (echo ".circleci/config.yml not in sync with config.yml.in! Run .circleci/regenerate.py to update config"; exit 1) + + download_third_parties_nix: + docker: + - image: "pytorch/torchaudio_unittest_base:manylinux" + resource_class: small + steps: + - checkout + - generate_cache_key + - restore_cache: + {% raw %} + keys: + - tp-nix-v2-{{ checksum ".cachekey" }} + {% endraw %} + - run: + command: | + mkdir -p third_party/archives/ + wget --no-clobber --directory-prefix=third_party/archives/ $(awk '/URL /{print $2}' third_party/CMakeLists.txt) + - save_cache: + {% raw %} + key: tp-nix-v2-{{ checksum ".cachekey" }} + {% endraw %} + paths: + - third_party/archives + - persist_to_workspace: + root: third_party + paths: + - archives + + binary_linux_wheel: + <<: *binary_common + docker: + - image: "pytorch/manylinux-cuda100" + resource_class: 2xlarge+ + steps: + - checkout + - attach_workspace: + at: third_party + - run: packaging/build_wheel.sh + - store_artifacts: + path: dist + - persist_to_workspace: + root: dist + paths: + - "*" + + binary_linux_conda: + <<: *binary_common + docker: + - image: "pytorch/conda-cuda" + resource_class: 2xlarge+ + steps: + - checkout + - attach_workspace: + at: third_party + - run: packaging/build_conda.sh + - store_artifacts: + path: /opt/conda/conda-bld/linux-64 + - persist_to_workspace: + root: /opt/conda/conda-bld/linux-64 + paths: + - "*" + + binary_macos_wheel: + <<: *binary_common + macos: + xcode: "9.0" + steps: + - checkout + - install_build_tools_macos + - attach_workspace: + at: third_party + - run: + # Cannot easily deduplicate this as source'ing activate + # will set environment variables which we need to propagate + # to build_wheel.sh + command: | + curl -o conda.sh https://repo.anaconda.com/miniconda/Miniconda3-latest-MacOSX-x86_64.sh + sh conda.sh -b + source $HOME/miniconda3/bin/activate + packaging/build_wheel.sh + - store_artifacts: + path: dist + - persist_to_workspace: + root: dist + paths: + - "*" + + binary_macos_conda: + <<: *binary_common + macos: + xcode: "9.0" + steps: + - checkout + - install_build_tools_macos + - attach_workspace: + at: third_party + - run: + command: | + curl -o conda.sh https://repo.anaconda.com/miniconda/Miniconda3-latest-MacOSX-x86_64.sh + sh conda.sh -b + source $HOME/miniconda3/bin/activate + conda install -yq conda-build + packaging/build_conda.sh + - store_artifacts: + path: /Users/distiller/miniconda3/conda-bld/osx-64 + - persist_to_workspace: + root: /Users/distiller/miniconda3/conda-bld/osx-64 + paths: + - "*" + + binary_windows_wheel: + <<: *binary_common + executor: + name: windows-cpu + steps: + - checkout + - run: + name: build + command: | + eval "$('/C/tools/miniconda3/Scripts/conda.exe' 'shell.bash' 'hook')" + conda activate base + bash packaging/build_wheel.sh + - store_artifacts: + path: dist + - persist_to_workspace: + root: dist + paths: + - "*" + + binary_windows_conda: + <<: *binary_common + executor: + name: windows-cpu + steps: + - checkout + - run: + name: build + command: | + eval "$('/C/tools/miniconda3/Scripts/conda.exe' 'shell.bash' 'hook')" + conda activate base + conda install -yq conda-build "conda-package-handling!=1.5.0" + bash packaging/build_conda.sh + - store_artifacts: + path: C:/tools/miniconda3/conda-bld/win-64 + - persist_to_workspace: + root: C:/tools/miniconda3/conda-bld/win-64 + paths: + - "*" + + # Requires org-member context + binary_conda_upload: + docker: + - image: continuumio/miniconda + steps: + - attach_workspace: + at: ~/workspace + - designate_upload_channel + - run: + command: | + # Prevent credential from leaking + conda install -yq anaconda-client + set -x + anaconda -t "${CONDA_PYTORCHBOT_TOKEN}" upload ~/workspace/*.tar.bz2 -u "pytorch-${UPLOAD_CHANNEL}" --label main --no-progress --force + + # Requires org-member context + binary_wheel_upload: + docker: + - image: circleci/python:3.8 + steps: + - attach_workspace: + at: ~/workspace + - checkout + - designate_upload_channel + - run: + command: | + pip install --user awscli + export PATH="$HOME/.local/bin:$PATH" + # Prevent credential from leaking + set +x + export AWS_ACCESS_KEY_ID="${PYTORCH_BINARY_AWS_ACCESS_KEY_ID}" + export AWS_SECRET_ACCESS_KEY="${PYTORCH_BINARY_AWS_SECRET_ACCESS_KEY}" + set -x + for pkg in ~/workspace/*.whl; do + aws s3 cp "$pkg" "s3://pytorch/whl/${UPLOAD_CHANNEL}/" --acl public-read + done + + smoke_test_linux_conda: + <<: *smoke_test_common + steps: + - attach_workspace: + at: ~/workspace + - run: + name: install binaries + command: | + set -x + source /usr/local/etc/profile.d/conda.sh && conda activate python${PYTHON_VERSION} + conda install -v -y -c pytorch-test -c pytorch-nightly pytorch + conda install -v -y $(ls ~/workspace/torchaudio*.tar.bz2) + - run: + name: smoke test + command: | + source /usr/local/etc/profile.d/conda.sh && conda activate python${PYTHON_VERSION} + python -c "import torchaudio" + + smoke_test_linux_pip: + <<: *smoke_test_common + steps: + - attach_workspace: + at: ~/workspace + - run: + name: install binaries + command: | + set -x + source /usr/local/etc/profile.d/conda.sh && conda activate python${PYTHON_VERSION} + pip install $(ls ~/workspace/torchaudio*.whl) -f https://download.pytorch.org/whl/nightly/torch_nightly.html -f https://download.pytorch.org/whl/test/torch_test.html + - run: + name: smoke test + command: | + source /usr/local/etc/profile.d/conda.sh && conda activate python${PYTHON_VERSION} + python -c "import torchaudio" + + smoke_test_windows_conda: + <<: *binary_common + executor: + name: windows-cpu + steps: + - attach_workspace: + at: ~/workspace + - run: + name: install binaries + command: | + set -x + eval "$('/C/tools/miniconda3/Scripts/conda.exe' 'shell.bash' 'hook')" + conda env remove -n python${PYTHON_VERSION} || true + conda create -yn python${PYTHON_VERSION} python=${PYTHON_VERSION} + conda activate python${PYTHON_VERSION} + conda install -v -y -c pytorch-test -c pytorch-nightly pytorch + conda install -v -y $(ls ~/workspace/torchaudio*.tar.bz2) + - run: + name: smoke test + command: | + eval "$('/C/tools/miniconda3/Scripts/conda.exe' 'shell.bash' 'hook')" + conda activate python${PYTHON_VERSION} + python -c "import torchaudio" + + smoke_test_windows_pip: + <<: *binary_common + executor: + name: windows-cpu + steps: + - attach_workspace: + at: ~/workspace + - run: + name: install binaries + command: | + set -x + eval "$('/C/tools/miniconda3/Scripts/conda.exe' 'shell.bash' 'hook')" + conda env remove -n python${PYTHON_VERSION} || true + conda create -yn python${PYTHON_VERSION} python=${PYTHON_VERSION} + conda activate python${PYTHON_VERSION} + pip install $(ls ~/workspace/torchaudio*.whl) -f https://download.pytorch.org/whl/nightly/torch_nightly.html -f https://download.pytorch.org/whl/test/torch_test.html + - run: + name: smoke test + command: | + eval "$('/C/tools/miniconda3/Scripts/conda.exe' 'shell.bash' 'hook')" + conda activate python${PYTHON_VERSION} + python -c "import torchaudio" + + smoke_test_docker_image_build: + machine: + image: ubuntu-1604:201903-01 + resource_class: large + environment: + image_name: torchaudio/smoke_test + steps: + - checkout + - run: + name: build_docker image + no_output_timeout: "1h" + command: | + cd .circleci/smoke_test/docker && docker build . -t ${image_name}:${CIRCLE_WORKFLOW_ID} + - run: + name: upload docker image + no_output_timeout: "1h" + command: | + set +x + export AWS_ACCESS_KEY_ID=${ECR_AWS_ACCESS_KEY} + export AWS_SECRET_ACCESS_KEY=${ECR_AWS_SECRET_ACCESS_KEY} + eval $(aws ecr get-login --region us-east-1 --no-include-email) + set -x + docker tag ${image_name}:${CIRCLE_WORKFLOW_ID} 308535385114.dkr.ecr.us-east-1.amazonaws.com/${image_name}:${CIRCLE_WORKFLOW_ID} + docker tag ${image_name}:${CIRCLE_WORKFLOW_ID} 308535385114.dkr.ecr.us-east-1.amazonaws.com/${image_name}:latest + docker push 308535385114.dkr.ecr.us-east-1.amazonaws.com/${image_name}:${CIRCLE_WORKFLOW_ID} + docker push 308535385114.dkr.ecr.us-east-1.amazonaws.com/${image_name}:latest + + unittest_linux_cpu: + <<: *binary_common + docker: + - image: "pytorch/torchaudio_unittest_base:manylinux" + resource_class: 2xlarge+ + steps: + - checkout + - attach_workspace: + at: third_party + - generate_cache_key + - restore_cache: + {% raw %} + keys: + - env-v3-linux-{{ arch }}-py<< parameters.python_version >>-{{ checksum ".circleci/unittest/linux/scripts/environment.yml" }}-{{ checksum "third_party/CMakeLists.txt" }}-{{ checksum ".cachekey" }} + {% endraw %} + - run: + name: Setup + command: .circleci/unittest/linux/scripts/setup_env.sh + - save_cache: + {% raw %} + key: env-v3-linux-{{ arch }}-py<< parameters.python_version >>-{{ checksum ".circleci/unittest/linux/scripts/environment.yml" }}-{{ checksum "third_party/CMakeLists.txt" }}-{{ checksum ".cachekey" }} + {% endraw %} + paths: + - conda + - env + - third_party/build + - third_party/install + - third_party/src + - run: + name: Install torchaudio + command: .circleci/unittest/linux/scripts/install.sh + - run: + name: Run tests + command: .circleci/unittest/linux/scripts/run_test.sh + - run: + name: Post process + command: .circleci/unittest/linux/scripts/post_process.sh + - store_test_results: + path: test-results + + unittest_linux_gpu: + <<: *binary_common + machine: + image: ubuntu-1604-cuda-10.1:201909-23 + resource_class: gpu.small + environment: + image_name: "pytorch/torchaudio_unittest_base:manylinux-cuda10.1" + steps: + - checkout + - attach_workspace: + at: third_party + - generate_cache_key + - restore_cache: + {% raw %} + keys: + - env-v3-linux-{{ arch }}-py<< parameters.python_version >>-{{ checksum ".circleci/unittest/linux/scripts/environment.yml" }}-{{ checksum "third_party/CMakeLists.txt" }}-{{ checksum ".cachekey" }} + {% endraw %} + - run: + name: Setup + command: docker run -t --gpus all -v $PWD:$PWD -w $PWD "${image_name}" .circleci/unittest/linux/scripts/setup_env.sh + - save_cache: + {% raw %} + key: env-v3-linux-{{ arch }}-py<< parameters.python_version >>-{{ checksum ".circleci/unittest/linux/scripts/environment.yml" }}-{{ checksum "third_party/CMakeLists.txt" }}-{{ checksum ".cachekey" }} + {% endraw %} + paths: + - conda + - env + - third_party/build + - third_party/install + - third_party/src + - run: + name: Install torchaudio + command: docker run -t --gpus all -v $PWD:$PWD -w $PWD "${image_name}" .circleci/unittest/linux/scripts/install.sh + - run: + name: Run tests + command: docker run -t --gpus all -v $PWD:$PWD -w $PWD "${image_name}" .circleci/unittest/linux/scripts/run_test.sh + - run: + name: Post Process + command: docker run -t --gpus all -v $PWD:$PWD -w $PWD "${image_name}" .circleci/unittest/linux/scripts/post_process.sh + - store_test_results: + path: test-results + + unittest_windows_cpu: + <<: *binary_common + executor: + name: windows-cpu + steps: + - checkout + - generate_cache_key + - restore_cache: + {% raw %} + keys: + - env-v3-windows-{{ arch }}-py<< parameters.python_version >>-{{ checksum ".circleci/unittest/windows/scripts/environment.yml" }}-{{ checksum ".cachekey" }} + {% endraw %} + - run: + name: Setup + command: .circleci/unittest/windows/scripts/setup_env.sh + - save_cache: + {% raw %} + key: env-v3-windows-{{ arch }}-py<< parameters.python_version >>-{{ checksum ".circleci/unittest/windows/scripts/environment.yml" }}-{{ checksum ".cachekey" }} + {% endraw %} + paths: + - conda + - env + - run: + name: Install torchaudio + command: .circleci/unittest/windows/scripts/install.sh + - run: + name: Run tests + command: .circleci/unittest/windows/scripts/run_test.sh + - run: + name: Post process + command: .circleci/unittest/windows/scripts/post_process.sh + - store_test_results: + path: test-results + + unittest_windows_gpu: + <<: *binary_common + executor: + name: windows-gpu + environment: + CUDA_VERSION: "10.1" + steps: + - checkout + - generate_cache_key + - restore_cache: + {% raw %} + keys: + - env-v1-windows-{{ arch }}-py<< parameters.python_version >>-{{ checksum ".circleci/unittest/windows/scripts/environment.yml" }}-{{ checksum ".cachekey" }} + {% endraw %} + - run: + name: Setup + command: .circleci/unittest/windows/scripts/setup_env.sh + - save_cache: + {% raw %} + key: env-v1-windows-{{ arch }}-py<< parameters.python_version >>-{{ checksum ".circleci/unittest/windows/scripts/environment.yml" }}-{{ checksum ".cachekey" }} + {% endraw %} + paths: + - conda + - env + - run: + name: Install torchaudio + command: .circleci/unittest/windows/scripts/install.sh + - run: + name: Run tests + command: .circleci/unittest/windows/scripts/run_test.sh + - run: + name: Post process + command: .circleci/unittest/windows/scripts/post_process.sh + - store_test_results: + path: test-results + + unittest_macos_cpu: + <<: *binary_common + macos: + xcode: "9.0" + resource_class: large + steps: + - checkout + - install_build_tools_macos + - attach_workspace: + at: third_party + - generate_cache_key + - restore_cache: + {% raw %} + keys: + - env-v3-macos-{{ arch }}-py<< parameters.python_version >>-{{ checksum ".circleci/unittest/linux/scripts/environment.yml" }}-{{ checksum "third_party/CMakeLists.txt" }}-{{ checksum ".cachekey" }} + {% endraw %} + - run: + name: Setup + command: .circleci/unittest/linux/scripts/setup_env.sh + - save_cache: + {% raw %} + key: env-v3-macos-{{ arch }}-py<< parameters.python_version >>-{{ checksum ".circleci/unittest/linux/scripts/environment.yml" }}-{{ checksum "third_party/CMakeLists.txt" }}-{{ checksum ".cachekey" }} + {% endraw %} + paths: + - conda + - env + - third_party/build + - third_party/install + - third_party/src + - run: + name: Install torchaudio + command: .circleci/unittest/linux/scripts/install.sh + - run: + name: Run tests + command: .circleci/unittest/linux/scripts/run_test.sh + - run: + name: Post process + command: .circleci/unittest/linux/scripts/post_process.sh + - store_test_results: + path: test-results + + stylecheck: + <<: *binary_common + docker: + - image: "pytorch/torchaudio_unittest_base:manylinux" + resource_class: medium + steps: + - checkout + - generate_cache_key + - restore_cache: + {% raw %} + keys: + - env-v2-linux-{{ arch }}-py<< parameters.python_version >>-{{ checksum ".circleci/unittest/linux/scripts/environment.yml" }}-{{ checksum ".cachekey" }} + {% endraw %} + - run: + name: Setup + command: .circleci/unittest/linux/scripts/setup_env.sh + - save_cache: + {% raw %} + key: env-v2-linux-{{ arch }}-py<< parameters.python_version >>-{{ checksum ".circleci/unittest/linux/scripts/environment.yml" }}-{{ checksum ".cachekey" }} + {% endraw %} + paths: + - conda + - env + - third_party/build + - third_party/install + - third_party/src + - run: + name: Run style check + command: .circleci/unittest/linux/scripts/run_style_checks.sh + +workflows: + build: + jobs: + - circleci_consistency + {{ build_workflows() }} + unittest: + jobs: + {{ unittest_workflows() }} + nightly: + jobs: + - circleci_consistency: + filters: + branches: + only: nightly + {{ build_workflows(prefix="nightly_", filter_branch="nightly", upload=True) }} + docker_build: + triggers: + - schedule: + cron: "0 10 * * 0" + filters: + branches: + only: + - master + jobs: + - smoke_test_docker_image_build diff --git a/.circleci/regenerate.py b/.circleci/regenerate.py new file mode 100755 index 0000000000..2c9fe7ee4f --- /dev/null +++ b/.circleci/regenerate.py @@ -0,0 +1,180 @@ +#!/usr/bin/env python3 + +""" +This script should use a very simple, functional programming style. +Avoid Jinja macros in favor of native Python functions. + +Don't go overboard on code generation; use Python only to generate +content that can't be easily declared statically using CircleCI's YAML API. + +Data declarations (e.g. the nested loops for defining the configuration matrix) +should be at the top of the file for easy updating. + +See this comment for design rationale: +https://github.com/pytorch/vision/pull/1321#issuecomment-531033978 +""" + +import jinja2 +import yaml +import os.path + + +PYTHON_VERSIONS = ["3.6", "3.7", "3.8"] + + +def build_workflows(prefix='', upload=False, filter_branch=None, indentation=6): + w = [] + w += build_download_job(filter_branch) + for btype in ["wheel", "conda"]: + for os_type in ["linux", "macos", "windows"]: + for python_version in PYTHON_VERSIONS: + w += build_workflow_pair(btype, os_type, python_version, filter_branch, prefix, upload) + + return indent(indentation, w) + + +def build_download_job(filter_branch): + job = { + "name": "download_third_parties_nix", + } + + if filter_branch: + job["filters"] = gen_filter_branch_tree(filter_branch) + return [{"download_third_parties_nix": job}] + + +def build_workflow_pair(btype, os_type, python_version, filter_branch, prefix='', upload=False): + + w = [] + base_workflow_name = "{prefix}binary_{os_type}_{btype}_py{python_version}".format( + prefix=prefix, + os_type=os_type, + btype=btype, + python_version=python_version, + ) + + w.append(generate_base_workflow(base_workflow_name, python_version, filter_branch, os_type, btype)) + + if upload: + + is_py3_linux = os_type in ['linux', "windows"] and not python_version.startswith("2.") + + w.append(generate_upload_workflow(base_workflow_name, filter_branch, btype)) + + if filter_branch == 'nightly' and is_py3_linux: + pydistro = 'pip' if btype == 'wheel' else 'conda' + w.append(generate_smoketest_workflow(pydistro, base_workflow_name, filter_branch, python_version, os_type)) + + return w + + +def generate_base_workflow(base_workflow_name, python_version, filter_branch, os_type, btype): + + d = { + "name": base_workflow_name, + "python_version": python_version, + } + + if os_type in ['linux', 'macos']: + d['requires'] = ['download_third_parties_nix'] + + if filter_branch: + d["filters"] = gen_filter_branch_tree(filter_branch) + + return {"binary_{os_type}_{btype}".format(os_type=os_type, btype=btype): d} + + +def gen_filter_branch_tree(*branches): + return { + "branches": { + "only": list(branches), + }, + "tags": { + # Using a raw string here to avoid having to escape + # anything + "only": r"/v[0-9]+(\.[0-9]+)*-rc[0-9]+/" + } + } + + +def generate_upload_workflow(base_workflow_name, filter_branch, btype): + d = { + "name": "{base_workflow_name}_upload".format(base_workflow_name=base_workflow_name), + "context": "org-member", + "requires": [base_workflow_name], + } + + if filter_branch: + d["filters"] = gen_filter_branch_tree(filter_branch) + + return {"binary_{btype}_upload".format(btype=btype): d} + + +def generate_smoketest_workflow(pydistro, base_workflow_name, filter_branch, python_version, os_type): + + required_build_suffix = "_upload" + required_build_name = base_workflow_name + required_build_suffix + + smoke_suffix = "smoke_test_{pydistro}".format(pydistro=pydistro) + d = { + "name": "{base_workflow_name}_{smoke_suffix}".format( + base_workflow_name=base_workflow_name, smoke_suffix=smoke_suffix), + "requires": [required_build_name], + "python_version": python_version, + } + + if filter_branch: + d["filters"] = gen_filter_branch_tree(filter_branch) + + return {"smoke_test_{os_type}_{pydistro}".format(os_type=os_type, pydistro=pydistro): d} + + +def indent(indentation, data_list): + return ("\n" + " " * indentation).join(yaml.dump(data_list).splitlines()) + + +def unittest_workflows(indentation=6): + jobs = [] + jobs += build_download_job(None) + for os_type in ["linux", "windows", "macos"]: + for device_type in ["cpu", "gpu"]: + if os_type == "macos" and device_type == "gpu": + continue + + for i, python_version in enumerate(PYTHON_VERSIONS): + job = { + "name": f"unittest_{os_type}_{device_type}_py{python_version}", + "python_version": python_version, + } + + if device_type == 'gpu': + job['filters'] = gen_filter_branch_tree('master', 'nightly') + + if os_type != "windows": + job['requires'] = ['download_third_parties_nix'] + + jobs.append({f"unittest_{os_type}_{device_type}": job}) + + if i == 0 and os_type == "linux" and device_type == "cpu": + jobs.append({ + f"stylecheck": { + "name": f"stylecheck_py{python_version}", + "python_version": python_version, + } + }) + return indent(indentation, jobs) + + +if __name__ == "__main__": + d = os.path.dirname(__file__) + env = jinja2.Environment( + loader=jinja2.FileSystemLoader(d), + lstrip_blocks=True, + autoescape=False, + ) + + with open(os.path.join(d, 'config.yml'), 'w') as f: + f.write(env.get_template('config.yml.in').render( + build_workflows=build_workflows, + unittest_workflows=unittest_workflows, + )) diff --git a/.circleci/smoke_test/docker/Dockerfile b/.circleci/smoke_test/docker/Dockerfile new file mode 100644 index 0000000000..acfac51fcd --- /dev/null +++ b/.circleci/smoke_test/docker/Dockerfile @@ -0,0 +1,36 @@ +# this Dockerfile is for torchaudio smoke test, it will be created periodically via CI system +# if you need to do it locally, follow below steps once you have Docker installed +# assuming you're within the directory where this Dockerfile located +# $ docker build . -t torchaudio/smoketest + +# if you want to push to aws ecr, make sure you have the rights to write to ECR, then run +# $ eval $(aws ecr get-login --region us-east-1 --no-include-email) +# $ export MYTAG=localbuild ## you can choose whatever tag you like +# $ docker tag torchaudio/smoketest 308535385114.dkr.ecr.us-east-1.amazonaws.com/torchaudio/smoke_test:${MYTAG} +# $ docker push 308535385114.dkr.ecr.us-east-1.amazonaws.com/torchaudio/smoke_test:${MYTAG} + +FROM ubuntu:latest + +RUN apt-get -qq update && apt-get -qq -y install curl bzip2 sox libsox-dev libsox-fmt-all \ + && curl -sSL https://repo.continuum.io/miniconda/Miniconda3-latest-Linux-x86_64.sh -o /tmp/miniconda.sh \ + && bash /tmp/miniconda.sh -bfp /usr/local \ + && rm -rf /tmp/miniconda.sh \ + && conda install -y python=3 \ + && conda update conda \ + && apt-get -qq -y remove curl bzip2 \ + && apt-get -qq -y autoremove \ + && apt-get autoclean \ + && rm -rf /var/lib/apt/lists/* /var/log/dpkg.log \ + && conda clean --all --yes + +ENV PATH /opt/conda/bin:$PATH + +RUN conda create -y --name python3.6 python=3.6 +RUN conda create -y --name python3.7 python=3.7 +RUN conda create -y --name python3.8 python=3.8 +SHELL [ "/bin/bash", "-c" ] +RUN echo "source /usr/local/etc/profile.d/conda.sh" >> ~/.bashrc +RUN source /usr/local/etc/profile.d/conda.sh && conda activate python3.6 && conda install -y -c conda-forge sox && conda install -y numpy +RUN source /usr/local/etc/profile.d/conda.sh && conda activate python3.7 && conda install -y -c conda-forge sox && conda install -y numpy +RUN source /usr/local/etc/profile.d/conda.sh && conda activate python3.8 && conda install -y -c conda-forge sox && conda install -y numpy +CMD [ "/bin/bash"] diff --git a/.circleci/test/test_sort_yaml.py b/.circleci/test/test_sort_yaml.py new file mode 100755 index 0000000000..dc6db481dd --- /dev/null +++ b/.circleci/test/test_sort_yaml.py @@ -0,0 +1,14 @@ +#!/usr/bin/env python3 + +""" +To compare new version with previous: + + ./regenerate.sh + meld <(git show HEAD:./config.yml | ./sort-yaml.py) <(cat config.yml | ./sort-yaml.py) +""" + + +import sys +import yaml + +sys.stdout.write(yaml.dump(yaml.load(sys.stdin, Loader=yaml.FullLoader), sort_keys=True)) diff --git a/.circleci/unittest/linux/README.md b/.circleci/unittest/linux/README.md new file mode 100644 index 0000000000..0a4b0e0e63 --- /dev/null +++ b/.circleci/unittest/linux/README.md @@ -0,0 +1,6 @@ +This directory contains; + + - docker + Docker image definition and scripts to build and update Docker image for unittest. + - scripts + Scripts used by CircleCI to run unit tests. diff --git a/.circleci/unittest/linux/docker/.dockerignore b/.circleci/unittest/linux/docker/.dockerignore new file mode 100644 index 0000000000..1398d409f8 --- /dev/null +++ b/.circleci/unittest/linux/docker/.dockerignore @@ -0,0 +1,2 @@ +* +!scripts diff --git a/.circleci/unittest/linux/docker/.gitignore b/.circleci/unittest/linux/docker/.gitignore new file mode 100644 index 0000000000..7e977058dd --- /dev/null +++ b/.circleci/unittest/linux/docker/.gitignore @@ -0,0 +1,2 @@ +scripts/build_third_parties.sh +Dockerfile.tmp diff --git a/.circleci/unittest/linux/docker/Dockerfile b/.circleci/unittest/linux/docker/Dockerfile new file mode 100644 index 0000000000..d91b5222a4 --- /dev/null +++ b/.circleci/unittest/linux/docker/Dockerfile @@ -0,0 +1,59 @@ +FROM ubuntu:18.04 as builder + +RUN apt update -q + +################################################################################ +# Build Kaldi +################################################################################ +RUN apt install -q -y \ + autoconf \ + automake \ + bzip2 \ + g++ \ + gfortran \ + git \ + libatlas-base-dev \ + libtool \ + make \ + python2.7 \ + python3 \ + sox \ + subversion \ + unzip \ + wget \ + zlib1g-dev + +# KALDI uses MKL as a default math library, but we are going to copy featbin binaries and dependent +# shared libraries to the final image, so we use ATLAS, which is easy to reinstall in the final image. +RUN git clone --depth 1 https://github.com/kaldi-asr/kaldi.git /opt/kaldi && \ + cd /opt/kaldi/tools && \ + make -j $(nproc) && \ + cd /opt/kaldi/src && \ + ./configure --shared --mathlib=ATLAS --use-cuda=no && \ + make featbin -j $(nproc) + +# Copy featbins and dependent libraries +ADD ./scripts /scripts +RUN bash /scripts/copy_kaldi_executables.sh /opt/kaldi /kaldi + +################################################################################ +# Build the final image +################################################################################ +FROM BASE_IMAGE +RUN apt update && apt install -y \ + g++ \ + gfortran \ + git \ + libatlas3-base \ + wget \ + curl \ + make \ + file \ + sox \ + libsox-dev \ + libsox-fmt-all \ + cmake \ + pkg-config \ + && rm -rf /var/lib/apt/lists/* +COPY --from=builder /kaldi /kaldi +ENV PATH="${PATH}:/kaldi/bin" LD_LIBRARY_PATH="${LD_LIBRARY_PATH}:/kaldi/lib" diff --git a/.circleci/unittest/linux/docker/build_and_push.sh b/.circleci/unittest/linux/docker/build_and_push.sh new file mode 100755 index 0000000000..8bf33eaaa3 --- /dev/null +++ b/.circleci/unittest/linux/docker/build_and_push.sh @@ -0,0 +1,27 @@ +#!/usr/bin/env bash + +set -euo pipefail + +if [ $# -ne 1 ]; then + printf "Usage %s \n\n" "$0" + exit 1 +fi + +if [ "$1" = "cpu" ]; then + base_image="ubuntu:18.04" + image="pytorch/torchaudio_unittest_base:manylinux" +elif [[ "$1" =~ ^(9.2|10.1)$ ]]; then + base_image="nvidia/cuda:$1-runtime-ubuntu18.04" + image="pytorch/torchaudio_unittest_base:manylinux-cuda$1" +else + printf "Unexpected string: %s" "$1" + exit 1; +fi + +cd "$( dirname "${BASH_SOURCE[0]}" )" + +# docker build also accepts reading from STDIN +# but in that case, no context (other files) can be passed, so we write out Dockerfile +sed "s|BASE_IMAGE|${base_image}|g" Dockerfile > Dockerfile.tmp +docker build -t "${image}" -f Dockerfile.tmp . +docker push "${image}" diff --git a/.circleci/unittest/linux/docker/scripts/copy_kaldi_executables.sh b/.circleci/unittest/linux/docker/scripts/copy_kaldi_executables.sh new file mode 100755 index 0000000000..b0cf207143 --- /dev/null +++ b/.circleci/unittest/linux/docker/scripts/copy_kaldi_executables.sh @@ -0,0 +1,58 @@ +#!/usr/bin/env bash + +list_executables() { + # List up executables in the given directory + find "$1" -type f -executable +} + +list_kaldi_libraries() { + # List up shared libraries used by executables found in the given directory ($1) + # that reside in Kaldi directory ($2) + while read file; do + ldd "${file}" | grep -o "${2}.* "; + done < <(list_executables "$1") | sort -u +} + +set -euo pipefail + +kaldi_root="$(realpath "$1")" +target_dir="$(realpath "$2")" + +bin_dir="${target_dir}/bin" +lib_dir="${target_dir}/lib" + +mkdir -p "${bin_dir}" "${lib_dir}" + +# 1. Copy featbins +printf "Copying executables to %s\n" "${bin_dir}" +while read file; do + printf " %s\n" "${file}" + cp "${file}" "${bin_dir}" +done < <(list_executables "${kaldi_root}/src/featbin") + +# 2. Copy dependent libraries from Kaldi +printf "Copying libraries to %s\n" "${lib_dir}" +while read file; do + printf " %s\n" "$file" + # If it is not symlink, just copy to the target directory + if [ ! -L "${file}" ]; then + cp "${file}" "${lib_dir}" + continue + fi + + # If it is symlink, + # 1. Copy the actual library to the target directory. + library="$(realpath "${file}")" + cp "${library}" "${lib_dir}" + # 2. then if the name of the symlink is different from the actual library name, + # create the symlink in the target directory. + lib_name="$(basename "${library}")" + link_name="$(basename "${file}")" + if [ "${lib_name}" != "${link_name}" ]; then + printf " Linking %s -> %s\n" "${lib_name}" "${link_name}" + ( + cd "${lib_dir}" + ln -sf "${lib_name}" "${link_name}" + ) + fi +done < <(list_kaldi_libraries "${bin_dir}" "${kaldi_root}") diff --git a/.circleci/unittest/linux/scripts/environment.yml b/.circleci/unittest/linux/scripts/environment.yml new file mode 100644 index 0000000000..108d97d193 --- /dev/null +++ b/.circleci/unittest/linux/scripts/environment.yml @@ -0,0 +1,17 @@ +channels: + - conda-forge + - defaults +dependencies: + - flake8 + - numpy + - pytest + - pytest-cov + - codecov + - librosa + - llvmlite==0.31 # See https://github.com/pytorch/audio/pull/766 + - pip + - pip: + - kaldi-io + - scipy + - parameterized + - numba==0.48 # See https://github.com/librosa/librosa/issues/1160 diff --git a/.circleci/unittest/linux/scripts/install.sh b/.circleci/unittest/linux/scripts/install.sh new file mode 100755 index 0000000000..131c9e43bf --- /dev/null +++ b/.circleci/unittest/linux/scripts/install.sh @@ -0,0 +1,23 @@ +#!/usr/bin/env bash + +unset PYTORCH_VERSION +# For unittest, nightly PyTorch is used as the following section, +# so no need to set PYTORCH_VERSION. +# In fact, keeping PYTORCH_VERSION forces us to hardcode PyTorch version in config. + +set -e + +eval "$(./conda/bin/conda shell.bash hook)" +conda activate ./env + +if [ -z "${CUDA_VERSION:-}" ] ; then + cudatoolkit="cpuonly" +else + version="$(python -c "print('.'.join(\"${CUDA_VERSION}\".split('.')[:2]))")" + cudatoolkit="cudatoolkit=${version}" +fi +printf "Installing PyTorch with %s\n" "${cudatoolkit}" +conda install -y -c pytorch-nightly pytorch "${cudatoolkit}" + +printf "* Installing torchaudio\n" +BUILD_SOX=1 python setup.py develop diff --git a/.circleci/unittest/linux/scripts/post_process.sh b/.circleci/unittest/linux/scripts/post_process.sh new file mode 100755 index 0000000000..a84a0dea55 --- /dev/null +++ b/.circleci/unittest/linux/scripts/post_process.sh @@ -0,0 +1,8 @@ +#!/usr/bin/env bash + +set -e + +eval "$(./conda/bin/conda shell.bash hook)" +conda activate ./env + +codecov diff --git a/.circleci/unittest/linux/scripts/run_style_checks.sh b/.circleci/unittest/linux/scripts/run_style_checks.sh new file mode 100755 index 0000000000..70b83e19f5 --- /dev/null +++ b/.circleci/unittest/linux/scripts/run_style_checks.sh @@ -0,0 +1,32 @@ +#!/usr/bin/env bash + +set -u + +eval "$(./conda/bin/conda shell.bash hook)" +conda activate ./env + +# We want to run all the style checks even if one of them fail. + +exit_status=0 + +printf "\x1b[34mRunning flake8: " +flake8 --version +printf "\x1b[0m\n" +flake8 torchaudio test build_tools/setup_helpers +status=$? +exit_status="$((exit_status+status))" +if [ "${status}" -ne 0 ]; then + printf "\x1b[31mflake8 failed. Check the format of Python files.\x1b[0m\n" +fi + +printf "\x1b[34mRunning clang-format: " +clang-format --version +printf "\x1b[0m\n" +git-clang-format origin/master +git diff --exit-code +status=$? +exit_status="$((exit_status+status))" +if [ "${status}" -ne 0 ]; then + printf "\x1b[31mC++ files are not formatted. Please use git-clang-format to format CPP files.\x1b[0m\n" +fi +exit $exit_status diff --git a/.circleci/unittest/linux/scripts/run_test.sh b/.circleci/unittest/linux/scripts/run_test.sh new file mode 100755 index 0000000000..9ea942851e --- /dev/null +++ b/.circleci/unittest/linux/scripts/run_test.sh @@ -0,0 +1,10 @@ +#!/usr/bin/env bash + +set -e + +eval "$(./conda/bin/conda shell.bash hook)" +conda activate ./env + +python -m torch.utils.collect_env +export PATH="${PWD}/third_party/install/bin/:${PATH}" +pytest --cov=torchaudio --junitxml=test-results/junit.xml -v --durations 20 test diff --git a/.circleci/unittest/linux/scripts/setup_env.sh b/.circleci/unittest/linux/scripts/setup_env.sh new file mode 100755 index 0000000000..290f0f8f97 --- /dev/null +++ b/.circleci/unittest/linux/scripts/setup_env.sh @@ -0,0 +1,50 @@ +#!/usr/bin/env bash + +# This script is for setting up environment in which unit test is ran. +# To speed up the CI time, the resulting environment is cached. +# +# Do not install PyTorch and torchaudio here, otherwise they also get cached. + +set -e + +this_dir="$( cd "$( dirname "${BASH_SOURCE[0]}" )" >/dev/null 2>&1 && pwd )" +root_dir="$(git rev-parse --show-toplevel)" +conda_dir="${root_dir}/conda" +env_dir="${root_dir}/env" + +cd "${root_dir}" + +case "$(uname -s)" in + Darwin*) os=MacOSX;; + *) os=Linux +esac + +# 1. Install conda at ./conda +if [ ! -d "${conda_dir}" ]; then + printf "* Installing conda\n" + wget -O miniconda.sh "http://repo.continuum.io/miniconda/Miniconda3-latest-${os}-x86_64.sh" + bash ./miniconda.sh -b -f -p "${conda_dir}" +fi +eval "$(${conda_dir}/bin/conda shell.bash hook)" + +# 2. Create test environment at ./env +if [ ! -d "${env_dir}" ]; then + printf "* Creating a test environment\n" + conda create --prefix "${env_dir}" -y python="$PYTHON_VERSION" +fi +conda activate "${env_dir}" + +# 3. Install Conda dependencies +printf "* Installing dependencies (except PyTorch)\n" +conda env update --file "${this_dir}/environment.yml" --prune +if [ "${os}" == Linux ] ; then + pip install clang-format +fi + +# 4. Buld codecs +mkdir -p third_party/build +( + cd third_party/build + cmake .. + cmake --build . +) diff --git a/.circleci/unittest/windows/README.md b/.circleci/unittest/windows/README.md new file mode 100644 index 0000000000..2c06af62bd --- /dev/null +++ b/.circleci/unittest/windows/README.md @@ -0,0 +1,4 @@ +This directory contains; + + - scripts + Scripts used by CircleCI to run unit tests. diff --git a/.circleci/unittest/windows/scripts/environment.yml b/.circleci/unittest/windows/scripts/environment.yml new file mode 100644 index 0000000000..fb57f0facc --- /dev/null +++ b/.circleci/unittest/windows/scripts/environment.yml @@ -0,0 +1,18 @@ +channels: + - conda-forge + - defaults +dependencies: + - flake8 + - numpy + - pytest + - pytest-cov + - codecov + - pip + - pip: + - scipy == 1.4.1 + - kaldi-io + - PySoundFile + - librosa + - future + - parameterized + - numba==0.48 diff --git a/.circleci/unittest/windows/scripts/install.sh b/.circleci/unittest/windows/scripts/install.sh new file mode 100644 index 0000000000..acbd79ae50 --- /dev/null +++ b/.circleci/unittest/windows/scripts/install.sh @@ -0,0 +1,23 @@ +#!/usr/bin/env bash + +unset PYTORCH_VERSION +# For unittest, nightly PyTorch is used as the following section, +# so no need to set PYTORCH_VERSION. +# In fact, keeping PYTORCH_VERSION forces us to hardcode PyTorch version in config. + +set -e + +eval "$(./conda/Scripts/conda.exe 'shell.bash' 'hook')" +conda activate ./env + +if [ -z "${CUDA_VERSION:-}" ] ; then + cudatoolkit="cpuonly" +else + version="$(python -c "print('.'.join(\"${CUDA_VERSION}\".split('.')[:2]))")" + cudatoolkit="cudatoolkit=${version}" +fi +printf "Installing PyTorch with %s\n" "${cudatoolkit}" +conda install -y -c pytorch-nightly pytorch "${cudatoolkit}" + +printf "* Installing torchaudio\n" +python setup.py develop diff --git a/.circleci/unittest/windows/scripts/install_conda.bat b/.circleci/unittest/windows/scripts/install_conda.bat new file mode 100644 index 0000000000..6052ad08b1 --- /dev/null +++ b/.circleci/unittest/windows/scripts/install_conda.bat @@ -0,0 +1 @@ +start /wait "" "%miniconda_exe%" /S /InstallationType=JustMe /RegisterPython=0 /AddToPath=0 /D=%tmp_conda% diff --git a/.circleci/unittest/windows/scripts/post_process.sh b/.circleci/unittest/windows/scripts/post_process.sh new file mode 100644 index 0000000000..b132113194 --- /dev/null +++ b/.circleci/unittest/windows/scripts/post_process.sh @@ -0,0 +1,8 @@ +#!/usr/bin/env bash + +set -e + +eval "$(./conda/Scripts/conda.exe 'shell.bash' 'hook')" +conda activate ./env + +codecov diff --git a/.circleci/unittest/windows/scripts/run_test.sh b/.circleci/unittest/windows/scripts/run_test.sh new file mode 100644 index 0000000000..252c1e9f46 --- /dev/null +++ b/.circleci/unittest/windows/scripts/run_test.sh @@ -0,0 +1,10 @@ +#!/usr/bin/env bash + +set -e + +eval "$(./conda/Scripts/conda.exe 'shell.bash' 'hook')" +conda activate ./env + +python -m torch.utils.collect_env +pytest --cov=torchaudio --junitxml=test-results/junit.xml -v --durations 20 test +flake8 torchaudio test diff --git a/.circleci/unittest/windows/scripts/setup_env.sh b/.circleci/unittest/windows/scripts/setup_env.sh new file mode 100644 index 0000000000..a45cf856ac --- /dev/null +++ b/.circleci/unittest/windows/scripts/setup_env.sh @@ -0,0 +1,39 @@ +#!/usr/bin/env bash + +# This script is for setting up environment in which unit test is ran. +# To speed up the CI time, the resulting environment is cached. +# +# Do not install PyTorch and torchaudio here, otherwise they also get cached. + +set -e + +this_dir="$( cd "$( dirname "${BASH_SOURCE[0]}" )" >/dev/null 2>&1 && pwd )" +root_dir="$(git rev-parse --show-toplevel)" +conda_dir="${root_dir}/conda" +env_dir="${root_dir}/env" + +cd "${root_dir}" + +# 1. Install conda at ./conda +if [ ! -d "${conda_dir}" ]; then + printf "* Installing conda\n" + export tmp_conda="$(echo $conda_dir | tr '/' '\\')" + export miniconda_exe="$(echo $root_dir | tr '/' '\\')\\miniconda.exe" + curl --output miniconda.exe https://repo.anaconda.com/miniconda/Miniconda3-latest-Windows-x86_64.exe -O + "$this_dir/install_conda.bat" + unset tmp_conda + unset miniconda_exe +fi + +eval "$(${conda_dir}/Scripts/conda.exe 'shell.bash' 'hook')" + +# 2. Create test environment at ./env +if [ ! -d "${env_dir}" ]; then + printf "* Creating a test environment\n" + conda create --prefix "${env_dir}" -y python="$PYTHON_VERSION" +fi +conda activate "${env_dir}" + +# 3. Install Conda dependencies +printf "* Installing dependencies (except PyTorch)\n" +conda env update --file "${this_dir}/environment.yml" --prune diff --git a/.clang-format b/.clang-format new file mode 100644 index 0000000000..73304266bd --- /dev/null +++ b/.clang-format @@ -0,0 +1,88 @@ +--- +AccessModifierOffset: -1 +AlignAfterOpenBracket: AlwaysBreak +AlignConsecutiveAssignments: false +AlignConsecutiveDeclarations: false +AlignEscapedNewlinesLeft: true +AlignOperands: false +AlignTrailingComments: false +AllowAllParametersOfDeclarationOnNextLine: false +AllowShortBlocksOnASingleLine: false +AllowShortCaseLabelsOnASingleLine: false +AllowShortFunctionsOnASingleLine: Empty +AllowShortIfStatementsOnASingleLine: false +AllowShortLoopsOnASingleLine: false +AlwaysBreakAfterReturnType: None +AlwaysBreakBeforeMultilineStrings: true +AlwaysBreakTemplateDeclarations: true +BinPackArguments: false +BinPackParameters: false +BraceWrapping: + AfterClass: false + AfterControlStatement: false + AfterEnum: false + AfterFunction: false + AfterNamespace: false + AfterObjCDeclaration: false + AfterStruct: false + AfterUnion: false + BeforeCatch: false + BeforeElse: false + IndentBraces: false +BreakBeforeBinaryOperators: None +BreakBeforeBraces: Attach +BreakBeforeTernaryOperators: true +BreakConstructorInitializersBeforeComma: false +BreakAfterJavaFieldAnnotations: false +BreakStringLiterals: false +ColumnLimit: 80 +CommentPragmas: '^ IWYU pragma:' +CompactNamespaces: false +ConstructorInitializerAllOnOneLineOrOnePerLine: true +ConstructorInitializerIndentWidth: 4 +ContinuationIndentWidth: 4 +Cpp11BracedListStyle: true +DerivePointerAlignment: false +DisableFormat: false +ForEachMacros: [ FOR_EACH_RANGE, FOR_EACH, ] +IncludeCategories: + - Regex: '^<.*\.h(pp)?>' + Priority: 1 + - Regex: '^<.*' + Priority: 2 + - Regex: '.*' + Priority: 3 +IndentCaseLabels: true +IndentWidth: 2 +IndentWrappedFunctionNames: false +KeepEmptyLinesAtTheStartOfBlocks: false +MacroBlockBegin: '' +MacroBlockEnd: '' +MaxEmptyLinesToKeep: 1 +NamespaceIndentation: None +ObjCBlockIndentWidth: 2 +ObjCSpaceAfterProperty: false +ObjCSpaceBeforeProtocolList: false +PenaltyBreakBeforeFirstCallParameter: 1 +PenaltyBreakComment: 300 +PenaltyBreakFirstLessLess: 120 +PenaltyBreakString: 1000 +PenaltyExcessCharacter: 1000000 +PenaltyReturnTypeOnItsOwnLine: 2000000 +PointerAlignment: Left +ReflowComments: true +SortIncludes: true +SpaceAfterCStyleCast: false +SpaceBeforeAssignmentOperators: true +SpaceBeforeParens: ControlStatements +SpaceInEmptyParentheses: false +SpacesBeforeTrailingComments: 1 +SpacesInAngles: false +SpacesInContainerLiterals: true +SpacesInCStyleCastParentheses: false +SpacesInParentheses: false +SpacesInSquareBrackets: false +Standard: Cpp11 +TabWidth: 8 +UseTab: Never +... diff --git a/.clang-tidy b/.clang-tidy new file mode 100644 index 0000000000..a3a40b5907 --- /dev/null +++ b/.clang-tidy @@ -0,0 +1,33 @@ +--- +# NOTE there must be no spaces before the '-', so put the comma first. +Checks: ' + -* + ,bugprone-* + ,-bugprone-forward-declaration-namespace + ,-bugprone-macro-parentheses + ,cppcoreguidelines-* + ,-cppcoreguidelines-interfaces-global-init + ,-cppcoreguidelines-owning-memory + ,-cppcoreguidelines-pro-bounds-array-to-pointer-decay + ,-cppcoreguidelines-pro-bounds-constant-array-index + ,-cppcoreguidelines-pro-bounds-pointer-arithmetic + ,-cppcoreguidelines-pro-type-cstyle-cast + ,-cppcoreguidelines-pro-type-reinterpret-cast + ,-cppcoreguidelines-pro-type-static-cast-downcast + ,-cppcoreguidelines-pro-type-union-access + ,-cppcoreguidelines-pro-type-vararg + ,-cppcoreguidelines-special-member-functions + ,hicpp-exception-baseclass + ,hicpp-avoid-goto + ,modernize-* + ,-modernize-return-braced-init-list + ,-modernize-use-auto + ,-modernize-use-default-member-init + ,-modernize-use-using + ,performance-unnecessary-value-param + ' +WarningsAsErrors: '*' +HeaderFilterRegex: 'torchaudio/.*' +AnalyzeTemporaryDtors: false +CheckOptions: +... diff --git a/.flake8 b/.flake8 new file mode 100644 index 0000000000..9d0eaed2bd --- /dev/null +++ b/.flake8 @@ -0,0 +1,4 @@ +[flake8] +max-line-length = 120 +ignore = E305,E402,E721,E741,F401,F403,F405,F999,W503,W504 +exclude = build,docs/source,_ext,third_party diff --git a/.github/ISSUE_TEMPLATE/bug-report.md b/.github/ISSUE_TEMPLATE/bug-report.md new file mode 100644 index 0000000000..fb50bd8504 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/bug-report.md @@ -0,0 +1,53 @@ +--- +name: "\U0001F41B Bug Report" +about: Submit a bug report to help us improve Torchaudio + +--- + +## ๐Ÿ› Bug + + + +## To Reproduce + +Steps to reproduce the behavior: + +1. +1. +1. + + + +## Expected behavior + + + +## Environment + + - What commands did you used to install torchaudio (conda/pip/build from source)? + - If you are building from source, which commit is it? + - What does `torchaudio.__version__` print? (If applicable) + +Please copy and paste the output from our +[environment collection script](https://raw.githubusercontent.com/pytorch/pytorch/master/torch/utils/collect_env.py) +(or fill out the checklist below manually). + +You can get the script and run it with: +``` +wget https://raw.githubusercontent.com/pytorch/pytorch/master/torch/utils/collect_env.py +# For security purposes, please check the contents of collect_env.py before running it. +python collect_env.py +``` + + - PyTorch Version (e.g., 1.0): + - OS (e.g., Linux): + - How you installed PyTorch (`conda`, `pip`, source): + - Build command you used (if compiling from source): + - Python version: + - CUDA/cuDNN version: + - GPU models and configuration: + - Any other relevant information: + +## Additional context + + diff --git a/.github/ISSUE_TEMPLATE/documentation.md b/.github/ISSUE_TEMPLATE/documentation.md new file mode 100644 index 0000000000..ae745121c5 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/documentation.md @@ -0,0 +1,9 @@ +--- +name: "\U0001F4DA Documentation" +about: Report an issue related to https://pytorch.org/audio + +--- + +## ๐Ÿ“š Documentation + + diff --git a/.github/ISSUE_TEMPLATE/feature-request.md b/.github/ISSUE_TEMPLATE/feature-request.md new file mode 100644 index 0000000000..f3896e5368 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/feature-request.md @@ -0,0 +1,24 @@ +--- +name: "\U0001F680Feature Request" +about: Submit a proposal/request for a new Torchaudio feature + +--- + +## ๐Ÿš€ Feature + + +## Motivation + + + +## Pitch + + + +## Alternatives + + + +## Additional context + + diff --git a/.github/ISSUE_TEMPLATE/questions-help-support.md b/.github/ISSUE_TEMPLATE/questions-help-support.md new file mode 100644 index 0000000000..77bfb55b9a --- /dev/null +++ b/.github/ISSUE_TEMPLATE/questions-help-support.md @@ -0,0 +1,13 @@ +--- +name: "โ“Questions/Help/Support" +about: Do you need support? We have resources. + +--- + +## โ“ Questions and Help + +### Please note that this issue tracker is not a help form and this issue will be closed. + +We have a set of [listed resources available on the website](https://pytorch.org/resources). Our primary means of support is our discussion forum: + +- [Discussion Forum](https://discuss.pytorch.org/) diff --git a/.github/pytorch-probot.yml b/.github/pytorch-probot.yml new file mode 100644 index 0000000000..d9daca0fb2 --- /dev/null +++ b/.github/pytorch-probot.yml @@ -0,0 +1 @@ +tracking_issue: 736 diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000000..e8a9d4c409 --- /dev/null +++ b/.gitignore @@ -0,0 +1,129 @@ +# Byte-compiled / optimized / DLL files +__pycache__/ +*.py[cod] +*$py.class + +# temp files +~* +*.swp + +# C extensions / folders +*.so +_ext/ + +# Distribution / packaging +.Python +env/ +build/ +develop-eggs/ +dist/ +downloads/ +eggs/ +.eggs/ +lib/ +lib64/ +parts/ +sdist/ +var/ +wheels/ +*.egg-info/ +.installed.cfg +*.egg + +# PyInstaller +# Usually these files are written by a python script from a template +# before PyInstaller builds the exe, so as to inject date/other infos into it. +*.manifest +*.spec + +# Installer logs +pip-log.txt +pip-delete-this-directory.txt + +# Unit test / coverage reports +htmlcov/ +.tox/ +.coverage +.coverage.* +.cache +nosetests.xml +coverage.xml +*.cover +.hypothesis/ + +# Translations +*.mo +*.pot + +# Django stuff: +*.log +local_settings.py + +# Flask stuff: +instance/ +.webassets-cache + +# Scrapy stuff: +.scrapy + +# Sphinx documentation +docs/_build/ +docs/src/ + +# PyBuilder +target/ + +# Jupyter Notebook +.ipynb_checkpoints/ + +# pyenv +.python-version + +# celery beat schedule file +celerybeat-schedule + +# SageMath parsed files +*.sage.py + +# dotenv +.env + +# virtualenv +.venv +venv/ +ENV/ + +# Spyder project settings +.spyderproject +.spyproject + +# Rope project settings +.ropeproject + +# PyCharm project settings +.idea + +# OSX dir files +.DS_Store + +# mkdocs documentation +/site + +# mypy +.mypy_cache/ + +# Generated Files +test/assets/sinewave.wav +torchaudio/version.py +gen.yml + +# Examples +examples/interactive_asr/data/*.txt +examples/interactive_asr/data/*.model +examples/interactive_asr/data/*.pt + +# third parties +third_party/archives/ +third_party/install/ +third_party/src/ +third_party/tmp/ diff --git a/.travis.yml b/.travis.yml new file mode 100644 index 0000000000..81e37b4120 --- /dev/null +++ b/.travis.yml @@ -0,0 +1,32 @@ +# note dist: 'trusty' does not work here +dist: xenial + +language: python + +# cache miniconda installer and similar files +cache: + directories: + - /home/travis/download + +# This matrix tests that the code works on Python 3.5, 3.6, 3.7, passes +# lint and example tests. +matrix: + fast_finish: true + include: + - env: PYTHON_VERSION="3.6" RUN_EXAMPLE_TESTS="true" SKIP_TESTS="true" + allow_failures: + - env: PYTHON_VERSION="3.6" RUN_EXAMPLE_TESTS="true" SKIP_TESTS="true" + +addons: + apt: + packages: + sox + libsox-dev + libsox-fmt-all + portaudio19-dev + +notifications: + email: false + +install: source build_tools/travis/install.sh +script: bash build_tools/travis/test_script.sh diff --git a/docs/source/backend.rst b/docs/source/backend.rst new file mode 100644 index 0000000000..6b0e074d5c --- /dev/null +++ b/docs/source/backend.rst @@ -0,0 +1,138 @@ +.. _backend: + +torchaudio.backend +================== + +:mod:`torchaudio.backend` module provides implementations for audio file I/O, using different backend libraries. +To switch backend, use :py:func:`torchaudio.set_audio_backend`. To check the current backend use :py:func:`torchaudio.get_audio_backend`. + +.. warning:: + Although ``sox`` backend is default for backward compatibility reason, it has a number of issues, therefore it is highly recommended to use ``sox_io`` backend instead. Note, however, that due to the interface refinement, functions defined in ``sox`` backend and those defined in ``sox_io`` backend do not have the same signatures. + +.. note:: + Instead of calling functions in :mod:`torchaudio.backend` directly, please use ``torchaudio.info``, ``torhcaudio.load``, ``torchaudio.load_wav`` and ``torchaudio.save`` with proper backend set with :func:`torchaudio.get_audio_backend`. + +There are currently three implementations available. + + * :ref:`sox` + * :ref:`sox_io` + * :ref:`soundfile` + +``sox`` backend is the original backend which is built on ``libsox``. This module is currently default but is known to have number of issues, such as wrong handling of WAV files other than 16-bit signed integer. Users are encouraged to use ``sox_io`` backend. This backend requires C++ extension module and is not available on Windows system. + +``sox_io`` backend is the new backend which is built on ``libsox`` and bound to Python with ``Torchscript``. This module addresses all the known issues ``sox`` backend has. Function calls to this backend can be Torchscriptable. This backend requires C++ extension module and is not available on Windows system. + +``soundfile`` backend is built on ``PySoundFile``. You need to install ``PySoundFile`` separately. + +Common Data Structure +~~~~~~~~~~~~~~~~~~~~~ + +Structures used to exchange data between Python interface and ``libsox``. They are used by :ref:`sox` and :ref:`soundfile` but not by :ref:`sox_io`. + +.. autoclass:: torchaudio.backend.common.SignalInfo + +.. autoclass:: torchaudio.backend.common.EncodingInfo + +.. _sox_backend: + +Sox Backend +~~~~~~~~~~~ + +``sox`` backend is available on ``torchaudio`` installation with C++ extension. It is currently not available on Windows system. + +It is currently default backend when it's available. You can switch from another backend to ``sox`` backend with the following; + +.. code:: + + torchaudio.set_audio_backend("sox") + +info +---- + +.. autofunction:: torchaudio.backend.sox_backend.info + +load +---- + +.. autofunction:: torchaudio.backend.sox_backend.load + +.. autofunction:: torchaudio.backend.sox_backend.load_wav + + +save +---- + +.. autofunction:: torchaudio.backend.sox_backend.save + +others +------ + +.. automodule:: torchaudio.backend.sox_backend + :members: + :exclude-members: info, load, load_wav, save + +.. _sox_io_backend: + +Sox IO Backend +~~~~~~~~~~~~~~ + +``sox_io`` backend is available on ``torchaudio`` installation with C++ extension. It is currently not available on Windows system. + +This new backend is recommended over ``sox`` backend. You can switch from another backend to ``sox_io`` backend with the following; + +.. code:: + + torchaudio.set_audio_backend("sox_io") + +The function call to this backend can be Torchsript-able. You can apply :func:`torch.jit.script` and dump the object to file, then call it from C++ application. + +info +---- + +.. autoclass:: torchaudio.backend.sox_io_backend.AudioMetaData + +.. autofunction:: torchaudio.backend.sox_io_backend.info + +load +---- + +.. autofunction:: torchaudio.backend.sox_io_backend.load + +.. autofunction:: torchaudio.backend.sox_io_backend.load_wav + + +save +---- + +.. autofunction:: torchaudio.backend.sox_io_backend.save + +.. _soundfile_backend: + +Soundfile Backend +~~~~~~~~~~~~~~~~~ + +``soundfile`` backend is available when ``PySoundFile`` is installed. This backend works on ``torchaudio`` installation without C++ extension. (i.e. Windows) + +You can switch from another backend to ``soundfile`` backend with the following; + +.. code:: + + torchaudio.set_audio_backend("soundfile") + +info +---- + +.. autofunction:: torchaudio.backend.soundfile_backend.info + +load +---- + +.. autofunction:: torchaudio.backend.soundfile_backend.load + +.. autofunction:: torchaudio.backend.soundfile_backend.load_wav + + +save +---- + +.. autofunction:: torchaudio.backend.soundfile_backend.save diff --git a/docs/source/datasets.rst b/docs/source/datasets.rst index 2f844293f6..96ba045c5e 100644 --- a/docs/source/datasets.rst +++ b/docs/source/datasets.rst @@ -57,6 +57,14 @@ LIBRISPEECH :special-members: +LIBRITTS +~~~~~~~~ + +.. autoclass:: LIBRITTS + :members: __getitem__ + :special-members: + + LJSPEECH ~~~~~~~~ diff --git a/docs/source/index.rst b/docs/source/index.rst index c6d0efde69..8146e545c3 100644 --- a/docs/source/index.rst +++ b/docs/source/index.rst @@ -1,5 +1,5 @@ torchaudio -=========== +========== The :mod:`torchaudio` package consists of I/O, popular datasets and common audio transformations. @@ -7,12 +7,13 @@ The :mod:`torchaudio` package consists of I/O, popular datasets and common audio :maxdepth: 2 :caption: Package Reference - sox_effects + torchaudio + backend + functional + transforms datasets + models + sox_effects compliance.kaldi kaldi_io - transforms - functional - -.. automodule:: torchaudio - :members: + utils diff --git a/docs/source/sox_effects.rst b/docs/source/sox_effects.rst index 56cd985d0a..0aa34e7908 100644 --- a/docs/source/sox_effects.rst +++ b/docs/source/sox_effects.rst @@ -1,21 +1,52 @@ -.. role:: hidden - :class: hidden-section +.. _sox_effects: torchaudio.sox_effects ====================== -Create SoX effects chain for preprocessing audio. - .. currentmodule:: torchaudio.sox_effects -:hidden:`SoxEffect` -~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +.. warning:: + + The :py:class:`SoxEffect` and :py:class:`SoxEffectsChain` classes are deprecated. Please migrate to :func:`apply_effects_tensor` and :func:`apply_effects_file`. + +Resource initialization / shutdown +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +.. autofunction:: init_sox_effects + +.. autofunction:: shutdown_sox_effects + +Listing supported effects +~~~~~~~~~~~~~~~~~~~~~~~~~ + +.. autofunction:: effect_names + +Applying effects +~~~~~~~~~~~~~~~~ + +Apply SoX effects chain on torch.Tensor or on file and load as torch.Tensor. + +Applying effects on Tensor +-------------------------- + +.. autofunction:: apply_effects_tensor + +Applying effects on file +------------------------ + +.. autofunction:: apply_effects_file + +Legacy +~~~~~~ + +SoxEffect +--------- .. autoclass:: SoxEffect :members: -:hidden:`SoxEffectsChain` -~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +SoxEffectsChain +--------------- .. autoclass:: SoxEffectsChain :members: append_effect_to_chain, sox_build_flow_effects, clear_chain, set_input_file diff --git a/docs/source/torchaudio.rst b/docs/source/torchaudio.rst new file mode 100644 index 0000000000..f7b826b571 --- /dev/null +++ b/docs/source/torchaudio.rst @@ -0,0 +1,43 @@ +torchaudio +========== + +I/O functionalities +~~~~~~~~~~~~~~~~~~~ + +Audio I/O functions are implemented in :ref:`torchaudio.backend` module, but for the ease of use, the following functions are made available on :mod:`torchaudio` module. There are different backends available and you can switch backends with :func:`set_audio_backend`. + +Refer to :ref:`backend` for the detail. + +.. function:: torchaudio.info(filepath: str, ...) + + Fetch meta data of an audio file. Refer to :ref:`backend` for the detail. + +.. function:: torchaudio.load(filepath: str, ...) + + Load audio file into torch.Tensor object. Refer to :ref:`backend` for the detail. + +.. function:: torchaudio.load_wav(filepath: str, ...) + + Load audio file into torch.Tensor, Refer to :ref:`backend` for the detail. + +.. function:: torchaudio.save(filepath: str, src: torch.Tensor, sample_rate: int, ...) + + Save torch.Tensor object into an audio format. Refer to :ref:`backend` for the detail. + +.. currentmodule:: torchaudio + +Backend Utilities +~~~~~~~~~~~~~~~~~ + +.. autofunction:: list_audio_backends + +.. autofunction:: get_audio_backend + +.. autofunction:: set_audio_backend + +Sox Effects Utilities +~~~~~~~~~~~~~~~~~~~~~ + +.. autofunction:: initialize_sox + +.. autofunction:: shutdown_sox diff --git a/docs/source/utils.rst b/docs/source/utils.rst new file mode 100644 index 0000000000..dc5ad0fd73 --- /dev/null +++ b/docs/source/utils.rst @@ -0,0 +1,11 @@ +torchaudio.utils +================ + +torchaudio.utils.sox_utils +~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Utility module to configure libsox. +This affects functionalities in :ref:`Sox IO backend` and :ref:`Sox Effects`. + +.. automodule:: torchaudio.utils.sox_utils + :members: diff --git a/examples/pipeline_wavernn/README.md b/examples/pipeline_wavernn/README.md new file mode 100644 index 0000000000..865f06c181 --- /dev/null +++ b/examples/pipeline_wavernn/README.md @@ -0,0 +1,36 @@ +This is an example vocoder pipeline using the WaveRNN model trained with LJSpeech. WaveRNN model is based on the implementation from [this repository](https://github.com/fatchord/WaveRNN). The original implementation was +introduced in "Efficient Neural Audio Synthesis". WaveRNN and LJSpeech are available in torchaudio. + +### Usage + +An example can be invoked as follows. +``` +python main.py \ + --batch-size 256 \ + --learning-rate 1e-4 \ + --n-freq 80 \ + --loss 'crossentropy' \ + --n-bits 8 \ +``` + +### Output + +The information reported at each iteration and epoch (e.g. loss) is printed to standard output in the form of one json per line. Here is an example python function to parse the output if redirected to a file. +```python +def read_json(filename): + """ + Convert the standard output saved to filename into a pandas dataframe for analysis. + """ + + import pandas + import json + + with open(filename, "r") as f: + data = f.read() + + # pandas doesn't read single quotes for json + data = data.replace("'", '"') + + data = [json.loads(l) for l in data.splitlines()] + return pandas.DataFrame(data) +``` diff --git a/examples/pipeline_wavernn/datasets.py b/examples/pipeline_wavernn/datasets.py new file mode 100644 index 0000000000..8d3068a229 --- /dev/null +++ b/examples/pipeline_wavernn/datasets.py @@ -0,0 +1,115 @@ +import os +import random + +import torch +import torchaudio +from torch.utils.data.dataset import random_split +from torchaudio.datasets import LJSPEECH +from torchaudio.transforms import MuLawEncoding + +from processing import bits_to_normalized_waveform, normalized_waveform_to_bits + + +class MapMemoryCache(torch.utils.data.Dataset): + r"""Wrap a dataset so that, whenever a new item is returned, it is saved to memory. + """ + + def __init__(self, dataset): + self.dataset = dataset + self._cache = [None] * len(dataset) + + def __getitem__(self, n): + if self._cache[n] is not None: + return self._cache[n] + + item = self.dataset[n] + self._cache[n] = item + + return item + + def __len__(self): + return len(self.dataset) + + +class Processed(torch.utils.data.Dataset): + def __init__(self, dataset, transforms): + self.dataset = dataset + self.transforms = transforms + + def __getitem__(self, key): + item = self.dataset[key] + return self.process_datapoint(item) + + def __len__(self): + return len(self.dataset) + + def process_datapoint(self, item): + specgram = self.transforms(item[0]) + return item[0].squeeze(0), specgram + + +def split_process_ljspeech(args, transforms): + data = LJSPEECH(root=args.file_path, download=False) + + val_length = int(len(data) * args.val_ratio) + lengths = [len(data) - val_length, val_length] + train_dataset, val_dataset = random_split(data, lengths) + + train_dataset = Processed(train_dataset, transforms) + val_dataset = Processed(val_dataset, transforms) + + train_dataset = MapMemoryCache(train_dataset) + val_dataset = MapMemoryCache(val_dataset) + + return train_dataset, val_dataset + + +def collate_factory(args): + def raw_collate(batch): + + pad = (args.kernel_size - 1) // 2 + + # input waveform length + wave_length = args.hop_length * args.seq_len_factor + # input spectrogram length + spec_length = args.seq_len_factor + pad * 2 + + # max start postion in spectrogram + max_offsets = [x[1].shape[-1] - (spec_length + pad * 2) for x in batch] + + # random start postion in spectrogram + spec_offsets = [random.randint(0, offset) for offset in max_offsets] + # random start postion in waveform + wave_offsets = [(offset + pad) * args.hop_length for offset in spec_offsets] + + waveform_combine = [ + x[0][wave_offsets[i]: wave_offsets[i] + wave_length + 1] + for i, x in enumerate(batch) + ] + specgram = [ + x[1][:, spec_offsets[i]: spec_offsets[i] + spec_length] + for i, x in enumerate(batch) + ] + + specgram = torch.stack(specgram) + waveform_combine = torch.stack(waveform_combine) + + waveform = waveform_combine[:, :wave_length] + target = waveform_combine[:, 1:] + + # waveform: [-1, 1], target: [0, 2**bits-1] if loss = 'crossentropy' + if args.loss == "crossentropy": + + if args.mulaw: + mulaw_encode = MuLawEncoding(2 ** args.n_bits) + waveform = mulaw_encode(waveform) + target = mulaw_encode(target) + + waveform = bits_to_normalized_waveform(waveform, args.n_bits) + + else: + target = normalized_waveform_to_bits(target, args.n_bits) + + return waveform.unsqueeze(1), specgram.unsqueeze(1), target.unsqueeze(1) + + return raw_collate diff --git a/examples/pipeline_wavernn/losses.py b/examples/pipeline_wavernn/losses.py new file mode 100644 index 0000000000..a4494b05fb --- /dev/null +++ b/examples/pipeline_wavernn/losses.py @@ -0,0 +1,119 @@ +import math + +import torch +from torch import nn as nn +from torch.nn import functional as F + + +class LongCrossEntropyLoss(nn.Module): + r""" CrossEntropy loss + """ + + def __init__(self): + super(LongCrossEntropyLoss, self).__init__() + + def forward(self, output, target): + output = output.transpose(1, 2) + target = target.long() + + criterion = nn.CrossEntropyLoss() + return criterion(output, target) + + +class MoLLoss(nn.Module): + r""" Discretized mixture of logistic distributions loss + + Adapted from wavenet vocoder + (https://github.com/r9y9/wavenet_vocoder/blob/master/wavenet_vocoder/mixture.py) + Explanation of loss (https://github.com/Rayhane-mamah/Tacotron-2/issues/155) + + Args: + y_hat (Tensor): Predicted output (n_batch x n_time x n_channel) + y (Tensor): Target (n_batch x n_time x 1) + num_classes (int): Number of classes + log_scale_min (float): Log scale minimum value + reduce (bool): If True, the losses are averaged or summed for each minibatch + + Returns + Tensor: loss + """ + + def __init__(self, num_classes=65536, log_scale_min=None, reduce=True): + super(MoLLoss, self).__init__() + self.num_classes = num_classes + self.log_scale_min = log_scale_min + self.reduce = reduce + + def forward(self, y_hat, y): + y = y.unsqueeze(-1) + + if self.log_scale_min is None: + self.log_scale_min = math.log(1e-14) + + assert y_hat.dim() == 3 + assert y_hat.size(-1) % 3 == 0 + + nr_mix = y_hat.size(-1) // 3 + + # unpack parameters (n_batch, n_time, num_mixtures) x 3 + logit_probs = y_hat[:, :, :nr_mix] + means = y_hat[:, :, nr_mix: 2 * nr_mix] + log_scales = torch.clamp( + y_hat[:, :, 2 * nr_mix: 3 * nr_mix], min=self.log_scale_min + ) + + # (n_batch x n_time x 1) to (n_batch x n_time x num_mixtures) + y = y.expand_as(means) + + centered_y = y - means + inv_stdv = torch.exp(-log_scales) + plus_in = inv_stdv * (centered_y + 1.0 / (self.num_classes - 1)) + cdf_plus = torch.sigmoid(plus_in) + min_in = inv_stdv * (centered_y - 1.0 / (self.num_classes - 1)) + cdf_min = torch.sigmoid(min_in) + + # log probability for edge case of 0 (before scaling) + # equivalent: torch.log(F.sigmoid(plus_in)) + log_cdf_plus = plus_in - F.softplus(plus_in) + + # log probability for edge case of 255 (before scaling) + # equivalent: (1 - F.sigmoid(min_in)).log() + log_one_minus_cdf_min = -F.softplus(min_in) + + # probability for all other cases + cdf_delta = cdf_plus - cdf_min + + mid_in = inv_stdv * centered_y + # log probability in the center of the bin, to be used in extreme cases + log_pdf_mid = mid_in - log_scales - 2.0 * F.softplus(mid_in) + + inner_inner_cond = (cdf_delta > 1e-5).float() + + inner_inner_out = inner_inner_cond * torch.log( + torch.clamp(cdf_delta, min=1e-12) + ) + (1.0 - inner_inner_cond) * ( + log_pdf_mid - math.log((self.num_classes - 1) / 2) + ) + inner_cond = (y > 0.999).float() + inner_out = ( + inner_cond * log_one_minus_cdf_min + (1.0 - inner_cond) * inner_inner_out + ) + cond = (y < -0.999).float() + log_probs = cond * log_cdf_plus + (1.0 - cond) * inner_out + + log_probs = log_probs + F.log_softmax(logit_probs, -1) + + if self.reduce: + return -torch.mean(_log_sum_exp(log_probs)) + else: + return -_log_sum_exp(log_probs).unsqueeze(-1) + + +def _log_sum_exp(x): + r""" Numerically stable log_sum_exp implementation that prevents overflow + """ + + axis = len(x.size()) - 1 + m, _ = torch.max(x, dim=axis) + m2, _ = torch.max(x, dim=axis, keepdim=True) + return m + torch.log(torch.sum(torch.exp(x - m2), dim=axis)) diff --git a/examples/pipeline_wavernn/main.py b/examples/pipeline_wavernn/main.py new file mode 100644 index 0000000000..032e9fc70e --- /dev/null +++ b/examples/pipeline_wavernn/main.py @@ -0,0 +1,390 @@ +import argparse +import logging +import os +import signal +from collections import defaultdict +from datetime import datetime +from time import time +from typing import List + +import torch +import torchaudio +from torch import nn as nn +from torch.optim import Adam +from torch.utils.data import DataLoader +from torchaudio.datasets.utils import bg_iterator +from torchaudio.models._wavernn import _WaveRNN + +from datasets import collate_factory, split_process_ljspeech +from losses import LongCrossEntropyLoss, MoLLoss +from processing import LinearToMel, NormalizeDB +from utils import MetricLogger, count_parameters, save_checkpoint + + +def parse_args(): + parser = argparse.ArgumentParser() + + parser.add_argument( + "--workers", + default=4, + type=int, + metavar="N", + help="number of data loading workers", + ) + parser.add_argument( + "--checkpoint", + default="", + type=str, + metavar="PATH", + help="path to latest checkpoint", + ) + parser.add_argument( + "--epochs", + default=8000, + type=int, + metavar="N", + help="number of total epochs to run", + ) + parser.add_argument( + "--start-epoch", default=0, type=int, metavar="N", help="manual epoch number" + ) + parser.add_argument( + "--print-freq", + default=10, + type=int, + metavar="N", + help="print frequency in epochs", + ) + parser.add_argument( + "--batch-size", default=256, type=int, metavar="N", help="mini-batch size" + ) + parser.add_argument( + "--learning-rate", default=1e-4, type=float, metavar="LR", help="learning rate", + ) + parser.add_argument("--clip-grad", metavar="NORM", type=float, default=4.0) + parser.add_argument( + "--mulaw", + default=True, + action="store_true", + help="if used, waveform is mulaw encoded", + ) + parser.add_argument( + "--jit", default=False, action="store_true", help="if used, model is jitted" + ) + parser.add_argument( + "--upsample-scales", + default=[5, 5, 11], + type=List[int], + help="the list of upsample scales", + ) + parser.add_argument( + "--n-bits", default=8, type=int, help="the bits of output waveform", + ) + parser.add_argument( + "--sample-rate", + default=22050, + type=int, + help="the rate of audio dimensions (samples per second)", + ) + parser.add_argument( + "--hop-length", + default=275, + type=int, + help="the number of samples between the starts of consecutive frames", + ) + parser.add_argument( + "--win-length", default=1100, type=int, help="the length of the STFT window", + ) + parser.add_argument( + "--f-min", default=40.0, type=float, help="the minimum frequency", + ) + parser.add_argument( + "--min-level-db", + default=-100, + type=float, + help="the minimum db value for spectrogam normalization", + ) + parser.add_argument( + "--n-res-block", default=10, type=int, help="the number of ResBlock in stack", + ) + parser.add_argument( + "--n-rnn", default=512, type=int, help="the dimension of RNN layer", + ) + parser.add_argument( + "--n-fc", default=512, type=int, help="the dimension of fully connected layer", + ) + parser.add_argument( + "--kernel-size", + default=5, + type=int, + help="the number of kernel size in the first Conv1d layer", + ) + parser.add_argument( + "--n-freq", default=80, type=int, help="the number of spectrogram bins to use", + ) + parser.add_argument( + "--n-hidden-melresnet", + default=128, + type=int, + help="the number of hidden dimensions of resblock in melresnet", + ) + parser.add_argument( + "--n-output-melresnet", default=128, type=int, help="the output dimension of melresnet", + ) + parser.add_argument( + "--n-fft", default=2048, type=int, help="the number of Fourier bins", + ) + parser.add_argument( + "--loss", + default="crossentropy", + choices=["crossentropy", "mol"], + type=str, + help="the type of loss", + ) + parser.add_argument( + "--seq-len-factor", + default=5, + type=int, + help="the length of each waveform to process per batch = hop_length * seq_len_factor", + ) + parser.add_argument( + "--val-ratio", + default=0.1, + type=float, + help="the ratio of waveforms for validation", + ) + parser.add_argument( + "--file-path", default="", type=str, help="the path of audio files", + ) + + args = parser.parse_args() + return args + + +def train_one_epoch(model, criterion, optimizer, data_loader, device, epoch): + + model.train() + + sums = defaultdict(lambda: 0.0) + start1 = time() + + metric = MetricLogger("train_iteration") + metric["epoch"] = epoch + + for waveform, specgram, target in bg_iterator(data_loader, maxsize=2): + + start2 = time() + + waveform = waveform.to(device) + specgram = specgram.to(device) + target = target.to(device) + + output = model(waveform, specgram) + output, target = output.squeeze(1), target.squeeze(1) + + loss = criterion(output, target) + loss_item = loss.item() + sums["loss"] += loss_item + metric["loss"] = loss_item + + optimizer.zero_grad() + loss.backward() + + if args.clip_grad > 0: + gradient = torch.nn.utils.clip_grad_norm_( + model.parameters(), args.clip_grad + ) + sums["gradient"] += gradient.item() + metric["gradient"] = gradient.item() + + optimizer.step() + + metric["iteration"] = sums["iteration"] + metric["time"] = time() - start2 + metric() + sums["iteration"] += 1 + + avg_loss = sums["loss"] / len(data_loader) + + metric = MetricLogger("train_epoch") + metric["epoch"] = epoch + metric["loss"] = sums["loss"] / len(data_loader) + metric["gradient"] = avg_loss + metric["time"] = time() - start1 + metric() + + +def validate(model, criterion, data_loader, device, epoch): + + with torch.no_grad(): + + model.eval() + sums = defaultdict(lambda: 0.0) + start = time() + + for waveform, specgram, target in bg_iterator(data_loader, maxsize=2): + + waveform = waveform.to(device) + specgram = specgram.to(device) + target = target.to(device) + + output = model(waveform, specgram) + output, target = output.squeeze(1), target.squeeze(1) + + loss = criterion(output, target) + sums["loss"] += loss.item() + + avg_loss = sums["loss"] / len(data_loader) + + metric = MetricLogger("validation") + metric["epoch"] = epoch + metric["loss"] = avg_loss + metric["time"] = time() - start + metric() + + return avg_loss + + +def main(args): + + devices = ["cuda" if torch.cuda.is_available() else "cpu"] + + logging.info("Start time: {}".format(str(datetime.now()))) + + melkwargs = { + "n_fft": args.n_fft, + "power": 1, + "hop_length": args.hop_length, + "win_length": args.win_length, + } + + transforms = torch.nn.Sequential( + torchaudio.transforms.Spectrogram(**melkwargs), + LinearToMel( + sample_rate=args.sample_rate, + n_fft=args.n_fft, + n_mels=args.n_freq, + fmin=args.f_min, + ), + NormalizeDB(min_level_db=args.min_level_db), + ) + + train_dataset, val_dataset = split_process_ljspeech(args, transforms) + + loader_training_params = { + "num_workers": args.workers, + "pin_memory": False, + "shuffle": True, + "drop_last": False, + } + loader_validation_params = loader_training_params.copy() + loader_validation_params["shuffle"] = False + + collate_fn = collate_factory(args) + + train_loader = DataLoader( + train_dataset, + batch_size=args.batch_size, + collate_fn=collate_fn, + **loader_training_params, + ) + val_loader = DataLoader( + val_dataset, + batch_size=args.batch_size, + collate_fn=collate_fn, + **loader_validation_params, + ) + + n_classes = 2 ** args.n_bits if args.loss == "crossentropy" else 30 + + model = _WaveRNN( + upsample_scales=args.upsample_scales, + n_classes=n_classes, + hop_length=args.hop_length, + n_res_block=args.n_res_block, + n_rnn=args.n_rnn, + n_fc=args.n_fc, + kernel_size=args.kernel_size, + n_freq=args.n_freq, + n_hidden=args.n_hidden_melresnet, + n_output=args.n_output_melresnet, + ) + + if args.jit: + model = torch.jit.script(model) + + model = torch.nn.DataParallel(model) + model = model.to(devices[0], non_blocking=True) + + n = count_parameters(model) + logging.info(f"Number of parameters: {n}") + + # Optimizer + optimizer_params = { + "lr": args.learning_rate, + } + + optimizer = Adam(model.parameters(), **optimizer_params) + + criterion = LongCrossEntropyLoss() if args.loss == "crossentropy" else MoLLoss() + + best_loss = 10.0 + + if args.checkpoint and os.path.isfile(args.checkpoint): + logging.info(f"Checkpoint: loading '{args.checkpoint}'") + checkpoint = torch.load(args.checkpoint) + + args.start_epoch = checkpoint["epoch"] + best_loss = checkpoint["best_loss"] + + model.load_state_dict(checkpoint["state_dict"]) + optimizer.load_state_dict(checkpoint["optimizer"]) + + logging.info( + f"Checkpoint: loaded '{args.checkpoint}' at epoch {checkpoint['epoch']}" + ) + else: + logging.info("Checkpoint: not found") + + save_checkpoint( + { + "epoch": args.start_epoch, + "state_dict": model.state_dict(), + "best_loss": best_loss, + "optimizer": optimizer.state_dict(), + }, + False, + args.checkpoint, + ) + + for epoch in range(args.start_epoch, args.epochs): + + train_one_epoch( + model, criterion, optimizer, train_loader, devices[0], epoch, + ) + + if not (epoch + 1) % args.print_freq or epoch == args.epochs - 1: + + sum_loss = validate(model, criterion, val_loader, devices[0], epoch) + + is_best = sum_loss < best_loss + best_loss = min(sum_loss, best_loss) + save_checkpoint( + { + "epoch": epoch + 1, + "state_dict": model.state_dict(), + "best_loss": best_loss, + "optimizer": optimizer.state_dict(), + }, + is_best, + args.checkpoint, + ) + + logging.info(f"End time: {datetime.now()}") + + +if __name__ == "__main__": + + logging.basicConfig(level=logging.INFO) + args = parse_args() + main(args) diff --git a/examples/pipeline_wavernn/processing.py b/examples/pipeline_wavernn/processing.py new file mode 100644 index 0000000000..b22d60dae4 --- /dev/null +++ b/examples/pipeline_wavernn/processing.py @@ -0,0 +1,58 @@ +import librosa +import torch +import torch.nn as nn + + +# TODO Replace by torchaudio, once https://github.com/pytorch/audio/pull/593 is resolved +class LinearToMel(nn.Module): + def __init__(self, sample_rate, n_fft, n_mels, fmin, htk=False, norm="slaney"): + super().__init__() + self.sample_rate = sample_rate + self.n_fft = n_fft + self.n_mels = n_mels + self.fmin = fmin + self.htk = htk + self.norm = norm + + def forward(self, specgram): + specgram = librosa.feature.melspectrogram( + S=specgram.squeeze(0).numpy(), + sr=self.sample_rate, + n_fft=self.n_fft, + n_mels=self.n_mels, + fmin=self.fmin, + htk=self.htk, + norm=self.norm, + ) + return torch.from_numpy(specgram) + + +class NormalizeDB(nn.Module): + r"""Normalize the spectrogram with a minimum db value + """ + + def __init__(self, min_level_db): + super().__init__() + self.min_level_db = min_level_db + + def forward(self, specgram): + specgram = 20 * torch.log10(torch.clamp(specgram, min=1e-5)) + return torch.clamp( + (self.min_level_db - specgram) / self.min_level_db, min=0, max=1 + ) + + +def normalized_waveform_to_bits(waveform, bits): + r"""Transform waveform [-1, 1] to label [0, 2 ** bits - 1] + """ + + assert abs(waveform).max() <= 1.0 + waveform = (waveform + 1.0) * (2 ** bits - 1) / 2 + return torch.clamp(waveform, 0, 2 ** bits - 1).int() + + +def bits_to_normalized_waveform(label, bits): + r"""Transform label [0, 2 ** bits - 1] to waveform [-1, 1] + """ + + return 2 * label / (2 ** bits - 1.0) - 1.0 diff --git a/examples/pipeline_wavernn/utils.py b/examples/pipeline_wavernn/utils.py new file mode 100644 index 0000000000..e924c9f512 --- /dev/null +++ b/examples/pipeline_wavernn/utils.py @@ -0,0 +1,61 @@ +import logging +import os +import shutil +from collections import defaultdict, deque + +import torch + + +class MetricLogger: + r"""Logger for model metrics + """ + + def __init__(self, group, print_freq=1): + self.print_freq = print_freq + self._iter = 0 + self.data = defaultdict(lambda: deque(maxlen=self.print_freq)) + self.data["group"].append(group) + + def __setitem__(self, key, value): + self.data[key].append(value) + + def _get_last(self): + return {k: v[-1] for k, v in self.data.items()} + + def __str__(self): + return str(self._get_last()) + + def __call__(self): + self._iter = (self._iter + 1) % self.print_freq + if not self._iter: + print(self, flush=True) + + +def save_checkpoint(state, is_best, filename): + r"""Save the model to a temporary file first, + then copy it to filename, in case the signal interrupts + the torch.save() process. + """ + + if filename == "": + return + + tempfile = filename + ".temp" + + # Remove tempfile in case interuption during the copying from tempfile to filename + if os.path.isfile(tempfile): + os.remove(tempfile) + + torch.save(state, tempfile) + if os.path.isfile(tempfile): + os.rename(tempfile, filename) + if is_best: + shutil.copyfile(filename, "model_best.pth.tar") + logging.info("Checkpoint: saved") + + +def count_parameters(model): + r"""Count the total number of parameters in the model + """ + + return sum(p.numel() for p in model.parameters() if p.requires_grad) diff --git a/test/README.md b/test/README.md index 304bfa9c8e..c0a4b2a21d 100644 --- a/test/README.md +++ b/test/README.md @@ -29,7 +29,7 @@ The following test modules are defined for corresponding `torchaudio` module/fun - [`torchaudio.transforms`](./test_transforms.py) - [`torchaudio.compliance.kaldi`](./test_compliance_kaldi.py) - [`torchaudio.kaldi_io`](./test_kaldi_io.py) -- [`torchaudio.sox_effects`](test/test_sox_effects.py) +- [`torchaudio.sox_effects`](test/sox_effects) - [`torchaudio.save`, `torchaudio.load`, `torchaudio.info`](test/test_io.py) ### Test modules that do not fall into the above categories diff --git a/test/assets/100Hz_44100Hz_16bit_05sec.wav b/test/assets/100Hz_44100Hz_16bit_05sec.wav deleted file mode 100644 index c297fded305c15674357745a9e845fe3b29bfff6..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 444524 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¨e^^uhaps)R1FjvHZXIO@;;Ym@P7^o2 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 diff --git a/test/assets/440Hz_44100Hz_16bit_05sec.wav b/test/assets/440Hz_44100Hz_16bit_05sec.wav deleted file mode 100644 index a746f73df924cbe891e21ad74ad99890dfff7e55..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 444524 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∈{AO{|fw{rXu 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 diff --git a/test/assets/sox_effect_test_args.json b/test/assets/sox_effect_test_args.json new file mode 100644 index 0000000000..2a223df635 --- /dev/null +++ b/test/assets/sox_effect_test_args.json @@ -0,0 +1,88 @@ +{"effects": [["allpass", "300", "10"]]} +{"effects": [["band", "300", "10"]]} +{"effects": [["bandpass", "300", "10"]]} +{"effects": [["bandreject", "300", "10"]]} +{"effects": [["bass", "-10"]]} +{"effects": [["bend", ".35,180,.25", ".15,740,.53", "0,-520,.3"]]} +{"effects": [["biquad", "0.4", "0.2", "0.9", "0.7", "0.2", "0.6"]]} +{"effects": [["chorus", "0.7", "0.9", "55", "0.4", "0.25", "2", "-t"]]} +{"effects": [["chorus", "0.6", "0.9", "50", "0.4", "0.25", "2", "-t", "60", "0.32", "0.4", "1.3", "-s"]]} +{"effects": [["chorus", "0.5", "0.9", "50", "0.4", "0.25", "2", "-t", "60", "0.32", "0.4", "2.3", "-t", "40", "0.3", "0.3", "1.3", "-s"]]} +{"effects": [["channels", "1"]]} +{"effects": [["channels", "2"]]} +{"effects": [["channels", "3"]]} +{"effects": [["compand", "0.3,1", "6:-70,-60,-20", "-5", "-90", "0.2"]]} +{"effects": [["compand", ".1,.2", "-inf,-50.1,-inf,-50,-50", "0", "-90", ".1"]]} +{"effects": [["compand", ".1,.1", "-45.1,-45,-inf,0,-inf", "45", "-90", ".1"]]} +{"effects": [["contrast", "0"]]} +{"effects": [["contrast", "25"]]} +{"effects": [["contrast", "50"]]} +{"effects": [["contrast", "75"]]} +{"effects": [["contrast", "100"]]} +{"effects": [["dcshift", "1.0"]]} +{"effects": [["dcshift", "-1.0"]]} +{"effects": [["deemph"]], "input_sample_rate": 44100} +{"effects": [["delay", "1.5", "+1"]]} +{"effects": [["dither", "-s"]]} +{"effects": [["dither", "-S"]]} +{"effects": [["divide"]]} +{"effects": [["downsample", "2"]], "input_sample_rate": 8000, "output_sample_rate": 4000} +{"effects": [["earwax"]], "input_sample_rate": 44100} +{"effects": [["echo", "0.8", "0.88", "60", "0.4"]]} +{"effects": [["echo", "0.8", "0.88", "6", "0.4"]]} +{"effects": [["echo", "0.8", "0.9", "1000", "0.3"]]} +{"effects": [["echo", "0.8", "0.9", "1000", "0.3", "1800", "0.25"]]} +{"effects": [["echos", "0.8", "0.7", "700", "0.25", "700", "0.3"]]} +{"effects": [["echos", "0.8", "0.7", "700", "0.25", "900", "0.3"]]} +{"effects": [["echos", "0.8", "0.7", "40", "0.25", "63", "0.3"]]} +{"effects": [["equalizer", "300", "10", "5"]]} +{"effects": [["fade", "q", "3"]]} +{"effects": [["fade", "h", "3"]]} +{"effects": [["fade", "t", "3"]]} +{"effects": [["fade", "l", "3"]]} +{"effects": [["fade", "p", "3"]]} +{"effects": [["fir", "0.0195", "-0.082", "0.234", "0.891", "-0.145", "0.043"]]} +{"effects": [["fir", "/sox_effect_test_fir_coeffs.txt"]]} +{"effects": [["flanger"]]} +{"effects": [["gain", "-n"]]} +{"effects": [["gain", "-n", "-3"]]} +{"effects": [["gain", "-l", "-6"]]} +{"effects": [["highpass", "-1", "300"]]} +{"effects": [["highpass", "-2", "300"]]} +{"effects": [["hilbert"]]} +{"effects": [["loudness"]]} +{"effects": [["lowpass", "-1", "300"]]} +{"effects": [["lowpass", "-2", "300"]]} +{"effects": [["mcompand", "0.005,0.1 -47,-40,-34,-34,-17,-33", "100", "0.003,0.05 -47,-40,-34,-34,-17,-33", "400", "0.000625,0.0125 -47,-40,-34,-34,-15,-33", "1600", "0.0001,0.025 -47,-40,-34,-34,-31,-31,-0,-30", "6400", "0,0.025 -38,-31,-28,-28,-0,-25"]], "input_sample_rate": 44100} +{"effects": [["norm"]]} +{"effects": [["oops"]]} +{"effects": [["overdrive"]]} +{"effects": [["pad"]]} +{"effects": [["phaser"]]} +{"effects": [["pitch", "6.48"], ["rate", "8030"]], "output_sample_rate": 8030} +{"effects": [["pitch", "-6.50"], ["rate", "7970"]], "output_sample_rate": 7970} +{"effects": [["rate", "4567"]], "output_sample_rate": 4567} +{"effects": [["remix", "6", "7", "8", "0"]], "num_channels": 8} +{"effects": [["remix", "1-3,7", "3"]], "num_channels": 8} +{"effects": [["repeat"]]} +{"effects": [["reverb"]]} +{"effects": [["reverse"]]} +{"effects": [["riaa"]], "input_sample_rate": 44100} +{"effects": [["silence", "0"]]} +{"effects": [["sinc", "3k"]]} +{"effects": [["speed", "1.3"]], "input_sample_rate": 4000, "output_sample_rate": 5200} +{"effects": [["speed", "0.7"]], "input_sample_rate": 4000, "output_sample_rate": 2800} +{"effects": [["stat"]]} +{"effects": [["stats"]]} +{"effects": [["stretch"]]} +{"effects": [["swap"]]} +{"effects": [["synth"]]} +{"effects": [["tempo", "0.9"]]} +{"effects": [["tempo", "1.1"]]} +{"effects": [["treble", "3"]]} +{"effects": [["tremolo", "300", "40"]]} +{"effects": [["tremolo", "300", "50"]]} +{"effects": [["trim", "0", "0.1"]]} +{"effects": [["upsample", "2"]], "input_sample_rate": 8000, "output_sample_rate": 16000} +{"effects": [["vad"]]} +{"effects": [["vol", "3"]]} diff --git a/test/assets/sox_effect_test_fir_coeffs.txt b/test/assets/sox_effect_test_fir_coeffs.txt new file mode 100644 index 0000000000..903a607d3b --- /dev/null +++ b/test/assets/sox_effect_test_fir_coeffs.txt @@ -0,0 +1 @@ +0.0195 -0.082 0.234 0.891 -0.145 0.043 diff --git a/test/assets/waves_yesno/0_1_0_1_0_1_1_0.wav b/test/assets/waves_yesno/0_1_0_1_0_1_1_0.wav deleted file mode 100644 index 66ee46737e6fb4a50e41780fea3c0b01b45830b6..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 84 zcmWIYbaV4zU|L!fNF0&}04a|ce*gdg diff --git a/test/assets/whitenoise.mp3 b/test/assets/whitenoise.mp3 deleted file mode 100644 index d6fe9f44b90bb0e03d7b3ebfb8f46858f888bc3a..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 57136 zcmd>lWmB7NxNXqlgy32T0fM_ziWA%&THM`=v?aJx+@U~mEAEuy?(PMOYoRSgv*A5w ze>s2QJTuQ^lFTHTm37&=){VG}?*sh5m%g2|&C_f6Pj@!}u*n5LeSw98Pe4RUPDMip zVT7`KmDuT3FdSIJvladi%cr7#I>386B69l$@5C{kfp9 zq^z>Kw!W#kt+T7Ae{f`ca%O&UWp(4n&fdZC*~QhLe|L{h-=(fBsUpkEAuQ~U+WNmg ziJumNdLjux`tkfbV!mv-{qGz9zdR!Drk?(w7s^OUzX1UH`#x6$&jm(hMnr4mc-O6o zgw_^#2* zOUv`h@hq(!x3*RvMoUJh>5NN(^plG_NL?|vS1PUayFn#BG98k>mPCUYJ58PW2ReW@ z65F<@^lw!7H(YL84*8q5U!VY>=c))vPZSkSIIq|Rz9rJPFQ&FpR{S(r!emRd<>jlG z1t?D1)1)a;D{NAqA{4E!nO9#*hc(#M*Fsd1%F$Ohg!EhuSc#)P*_BsGW*Q18dEHhD zc7;45&k0rI@$O~Jp_N^cux6Ezr2ks2qKT_zKSx%v5Se3nccpv#?Q8pBWqPCjR-HY* z-$0p>eTQzb%je_R4;GZ0i05m6<54iyJY(^{CwDh56_0F1d_kiAMQ4b!_L6{8JD`*} z47pSvZRsDj2);gdKVOT9&o8Bnk$80U{NgXGB<4}I#HW))(fCTV{U%AaZ91ujWg7(w zK2-M_J>ceboHAtiky>PT5(|{T;JUOC(l?a=9y`$fxMlx#D1o2cXwZ{o6aQ zKta?Ns~jDuE)|AnZ$48whyrlE=t0p`71hBK&7u^}Sa(oVETgR|A^c}Dva_qlJGM$5 z;MvR>28tJZ$@t^@n>_3_PFG;d8w%FzfU@(`^O00vBV_;*oZ6I&c0VQ*Z21L+Lenq8 zHKe51jl-XU&HXD=d^3f}O0`~`+P1pPjDiV8WVf5XT7j?+Ih#)4$y zomc>w3MtSSW2NYF%4MmK4 z&@Wy|Sc!eU7w{7FC;9YOY?$ zF{qK+vAh>r;*%rz}$w+{l3rpT>K%j*eyswdsPP z>DhxD<;uyuvmZR5?lu{a!mMPeXArL8_}SgjCt}0)7!d9!5PlA;@0PLcXCG#Rx7~$v zHBBBI@(olsI6Mipu1nW9C)e7;O)Q-FqFd4O@-l!JX+0s_@Rrfez;fAe`R1JCPApHx zbsJUCgMKd8>{2F_f?<*S9G1jTIFc>RI#X^tRBm&?1&bdxh~1 z`b-T>#Z5IfT2?LRVwQ&BJvS0IIkXwvrt#n`^j+^VNT!v4L|j$KJ^r}@ZiWOn+l!$RD#u|CLcdZ-+jKT!=j>D2f8_?LB>epMH@-Jp z6OrgdG*0*`i6)$-cv+`T=x8A1{h*LR51NVnuJh9QL+{xuv&>Bm9H=lU` znPX|q)(P1KCJ{=YevgfXd$4K&E2wsogx%8yvy&-Nr>0>8slyWR!FBG!-`+HwPOzV$6v(R}MzYJ3z^Pk3O~kF5-L7{ff!{ zP&M55f>7PUodlVZ(l!J zR7z%BZsy>9`*51lJZczvhB$9;jWw15ND(Qd#J!+kPg~N)V!`vnoHYqyf5Gq$PD}A8 z_?PLMUzT&y)-Pzv*FUt}H0K_Ad8Gs2#4xE}X~{@?=<4WXIFb9hdi%a|Y97b`ruOHr zi1{QQQkWyeG-;p%V5LG>n#czj!-}U6VSzy$8Njl6et>eH0e^=F?~i8>mc31NuoVXR zN?PF`>ha|5sW=9nvr5IqdFtjz8eZ#UG3aO!24vbxIxPn}n2pNjL-%~OKc`NBz1EsX z-lC=OYRp@|(i02{R1&xDR~FCgIfDbmHp5RKZc^Y>u7@z(vM}c9hurg`eJ~k2iazCJ zb^fiY3`7H3qr%jK59CL#e?co@OQ~h}uYImeQ**o@Ep={bJ%DPk%Kl_yv#i*^vX(Jg z!cYTXWC4v&E;f}F9p;%)kj5*iY@BfTq>jge(hXK+W7}Pon^_5zGZdEsN1r+5J7d+m z4Qil*Y;)BD!~4P{8v0uJi1vIYiH0_4B$tL`CWYp5Sw38c1$Zf%EXTAM45)rTA$64z zCxY-z`RFIBB8No9NtB~B6~4Cja^9=@9dLfOr`@!wE5RJW(~Y`R;TY7@N1=>bZc8?l zfl9Yz+RDuR113NR5hBU#68YV3m6!u|4sUFwHcKv^{SLeBCc@3QNas^x4< zmq|?5NLTeDrMgK;*K+SW#K!q(nm?NzKo>Ycz%?KTtAV-_Ts*+Amm(c@*5~(B7^{6)T`)&RIv|fMZkE=VOleIDt+ZhYT zR1m0D_OcwhGp=_S-4A$X&ncY1iZk*A;v$7Y_3I%d_JOZNmmq}8>nm{WCUqRsj`_gh z{bh+A=;oI~?F1k^IarSgtHx!!Tbmtm{xA~m-{Ay_pkWW%Opn3@=noN63y1W50gKd# zqwRUf)MV3gGm`_Pr{G*y~I;U@SA@o9z0hj82BX%>y;7d%l0pcGrE*#g>a)M1ugOgy`Qs zJ#L(|g|{sYLjV%ETX2!@0Mex2c+QfSo|Z%Jp00VnSMOKc=u-y4vR@<2~xyy2n zdAlQdLqZG_KdOegzXCsl@COb|NQrz3p&b=jJN2mAeEjF=^PK@z*A&kh?L|W|7q)c}&HY~%kwvo1Bwgv|}3I=qL zEA0aqF69|trvpZvNVH0_$c|=Z2ho^0Yie<|^1jTrl9j^t;E7h04?+|>?5kHRBNAj) ztBx5zzG=7u%&qQ1^A3yd6-m(|Q9iu`MMN5^NJ@MN>kkPgpH6%Kw*6Y%nfyuv3@8NP z^7Or+!SK`3jwo7kh_c?Rj-czZtQILIgJP#FsDF`>@d6}x%Q#kt?M;bkc6Uro;-Q0o zvT!v4iaqdX)iBX2pF`*nfM3S+=?MgTApNgb!Fc+3xM;c*Ahs|ylfNK7TJxSHPYPHN zI|O>GQ;yi`DE>QV~oDL9^k^qYk!`)8>ue=_+tNx2q&25w*GK_{$fWG ztac?(*oZrJRU`>L5O<$&{g!o)ttTFY>o?8IWSLvyIy96<2|N0OTyY}gBU-b%pnl!%|NGSUWoC#YgO6U)XXzzc>m+kV;X@ z?+fejLOK4GQ^Hm?hW=n);@+rC#dyK|PPr32e8b-CB`_8ESzAo&POoX8M-;4Wf@%p+ zyXd~Xw-8Os)*3A;WGkUJG@f|(`ald>0uJm5gu5!coyqvF{%I)m}F7v`?ycCGE~7cwbqG))(Zsz>+6ZFhKV zn}nr8T?C<;YRdaRZSr}WZ&W(B=o0o*T#DZu*@yV4n;QM`o7<9Sxc^pB7G_|f08(*K zZ2D+$xlc#H^CGT>6)WT9CZQ`P=bz2jJWC)p8iqd1&00qu*>kF9R91;CHnoZn+aO$> zyS!3^h%ayGUE#M|>6o~I{iL8WcV7B;^1`<{3m$!`bJIuj;{>0Xc<8y~;&NRyoaY&} zy_Km03@>aAH@Y`pNMEb9pCR@Tqc0KR>)w{VJfoDBiEgw>q)@ULFPlQ14ij`_I7a?B z!CL_m15!)cAg;swX>O@?R7ccCBrTbM-r zaT4i@Gw~k?(4N_I4%lw zi8Ljt*0li!-}Ki!IU@v>U7BL*Q4Ut5-BeFxB78K}!pxMA01NB6rLVylGrg)6s3U7;P{HleS4imz5m9q5ehw5At{nZOd5w zxj5ghA5CUOl_+6B3c#3^vMrO^tO_{PEfnb<3=INJmTbHB26TL{S54)_F$e zU(Oq2qKy4X&WyEFk#}8J3OO07q}O|T&X0TAam%rt*J(r(jf;c|NE1f2E?*9iv60!r zJliyg8MU)(%Nv>7#<>2qgd9($@Kzla@rwi>X~n9RpurMmF`M9SVeaLsib^5X9F^~6 zL^vLew6dOoJA>o@q5Lmt6K2(PhQw|iYyV*4y?RS2H? z@t)bOJbi|soUB=U_kQ#!BGezE0+vlTq{C6>VH9Oka^L5_C`Wfca7rJcYctZo84iyw zel^rrGvQI+-#%JW801ct5^u5o3W8mhl^m2>{@1CSO*W%_G)$`7xZTM$J3^64>b2c4axW|i z%1HIho>Mq*Xe;&vGI1oyT+^8xd$3*YiSc`iE0iwSFn7CN-C91=f`YixzqLQr&%32ClJ2e8sVP$XlvMt(O|O1D5^Gm9dk+Q?s*+;0Gg9Xs?%?}>tDKPByqsRa6b-VL_H-c9X`;a4kIIihczxf_EI)uA%Ksl}(PkX}?$GLZ8BUi-Wddir?Y zo*oOag~y;M0wyBRvFtu%_0aJFV4A}ER7Ef1s{XOaNsGPEfCkgYG~HwCzPep(NAKu# z7*D@=g^Ws&$D1Fg`<_L%l6rihJU{u{w3S!g`M18mi!;Hl3VILoBVI2nbX*)xAbU4S zl&k6)702h5Y+)IIjr9&G*T?ho<Ovd`E zgzSMS%2O@II?OdYSfl`nA$%Hxar$zW0Xd<0ful|E80d-pAUakyE8#cqmN zUkyvn7$Dx#b?V%oqnNvu&Yg`;L#P6t@Qk--!TfFjYiBk! z3MBxDIY7`_#wa3c#<3pS%i%EH_B)rh&JI>b1dIoYyyptCDycrNtb9j+y1M;h-d!Pf z&a?#8TnAH^``ltz1=yO!eNuOuxif=PJo4A6!=h3f74#?cd!CuJ9K1(5FXGQj=rjrL z04WYJVS+Q*V0&ej`O`w1e?S1oVU`1>6D_&YKU|SavcCTL91AE&k8b_T>kE-QM_@0K z-NXq8{!YCKg-T6#DVen*$KTc9X_b0Bxj+gS(4Jp zqL}vmg5w+Se>xGfV*!EPK0FPp%b!R*2l&GJ6QSry;>vO}60lP9_d7~2wJk{Mijp}v zW?}_;^#`~o5RWNin=7s1(T#}$TIvRomT^IHNIH=OVgry~qY1);?{fp<3&mf0^CQ!H zd)xv|8vo2lCH)L>0W$tdGu$FVj|^4qr@HPo9;Cmlqae5X9Ghf-=W-`#p!=}oR#!06nDPr?!J=(p#o3D@e9V2CT z`ZLT6G!jB~P`GxrU(dFm5uvQ}ajXWb4?bhULXb^q%uJ!_Lr-wD+D9Qy8pBzyUxwGA zInN<<2q&;(3V-Ufr7)?vKZL~5X29xN+uLVwBo!%XgIZ+zYDE0VBYqBw@0NkSSJQNI+G_zVh(vo6FCu6PKS8_GH;b z(ndeZD@aF2m!Zk{AGif;^H(bG#8lsjZFT$JkXr*6Y&aQ8iL@&QoFgwuG8=`tO&f^~qm& z8b7n=H=KZ*{i)NQL`M61`6>*zVN1#!R_LX*&1cP*P>9znX@Ml$DibQhk!Vy|n->VA z4f?WuY97~Ek@n^;=g5R#XY=8{#oMXSsW|$!R3{HaONb)(={p)NoGz*lQk3^YoR0Ry zv~(C7t31&C(l!J3 z8>rvq$|ZL}x`)M1qe!eTjz`isW|9x%_q6jZF=&GEb%8#t6up;Tr^{-HciuWO4@S0$ zXbL%Nekf{4w#2>{(N>Pk#X*hTTzlf4a(2Jgl4g=A1CUhE*q#i=$*`^~ z%Y3wD7~){j7GZ9KCrMty1IhYcRI)ard^Nny`*DiY9}+F6$02eYY{?LdtAD98bz4l9 z>|wJ7gvvP=I{W;@wJJ((l^#ww?Fiz1X*!P_3h58{k^YUyh1#nyM+9rcIJ~nBM&GF@ zuh#b7=BacA2oj=A zVjtU~D^o~Upg6l^fG$988x}?l4a>k|Tv97*s(=3aSV85-=_*)?F>=y_1d4Q0@SfRo z2>|NoJh8_~^0BJ+3Ahtl9SS@GC<>49kVyZF*cX6c)%ZA%1Jno!#@GgA$E=Ag8fvK% zzt`GQsZ8;AXRAjMPLA^pfwK6T!ZIYp;%R}<%=Em0o3poahjES~kF z--o(^;GDf&>pDBhNNT}vqsszcMVoRln*Y@`gpQwdycSMAc`s*e|I)$?TE%61pguys zUi;!-RIZ`bF7K(;+o1hjWG+E0BTl2@`f8THZg&n3n`ciLogaT>G@BaI1^|vQk?;wS zr2!qx`q2g4NP%eI6-aQtW>`GPE!vrri+R%>-ldeQ*>oImj2Xup-KBjC>u)Q4X3qf} z7~dZKtPz2!f4zEQ&wP2Kt48>dp-x}fQlnL_SqV|SKMu4j`1DEMMyc&t-uO%A436X| za*vLcGL(7$Ch0g@!A`T`3n_Z4gW?P3xq&1L^OQ5)#cH#}X1>wHn??FEn$m*;N&OpE zgMVV%)!Xhs$^fsnRKFoLnH@(Jlj7mbTrH1ZhKekYqaCGTc9wQvsYDeJy)iI?z@}fK zPV*p7*gG|nMMsY3zD+M5)w&PhV_dhxY`mxea#zxmiR1+qQLkkDp$QF59OBx0Q)S?N zSo*gE(elOlPh9&A04@za zF9;QvJI-#Bn1oXn%}TVoRg8&cq)6FbJCRc}$i&nY6vEP~`m6MK`XzC|IcaZrRaz6k zbMr$P4RzhMa%n6B8H};|H=YBsV>`buOC{20@36le3?_tSEY2ORljG{RNgNczUxa;$ zNHZ7;`a)EC^uovmVe*K$J5G1;aso-pP;1haL$1+_T1ZYY%Z%`9Y>EtX$$C+PxdUnK zv6b~-vk=H^)7r!&mQLi_;c^YJ)yb(lEi1b4WoNJrP?Kb3qE&+i9BmdAdAJ-SPoQ+% zOc?pAueU4_>LG^s8CD#OX3J}uKfe5A^7{HN!1#1@m@&8Pyp$TTzO2F7SXF>AMun=4 z#xK_=YyT4f#FYm|;#x(r4gY8*EMn|YpersTiKJF%QlR&SJ<$l;efa<8tD*DIQ;16x zdD&C7i~UW#PQ1=-7}CSyFbBOKQst4wjyJAI$_nlT*$QOWNd?u5#7(F>`ipyZ$c)NR z=!@@1dSORbX<_H;hEhYh^L96{%SZ0o%Dn6-BSA`!X`v_v`6$@9J0x{_blucH zSu}{$`u+vg5GEs`LgcnbTG+(;*o#kPiZf?FDO_}UZm3zr_JX=vp;ZGVScAekhd8k| z29eTztF^b*8sBEQymEDf423Q2sA0E-)*cQA@3gk)UkiJOesjShf$f$Iz0r%$Ymz8S z(ut^Uhy5B*TF8DFyDbfE5=xM@K_$k}SQCkeP^|l1V4jVl8>M(U>SNN>a4;@9&CoCv z5s5A1WxysEn2MrYcjQ#5F>NzTv0@NK9wNXsVLlw2(;Gzng`502Up?*9aG&H{GB>+B zu-ij0p5;wzZI5F}kbt4T*x;GvMUg1^)hOrt(LZ$zOdn$LH1)M}5(o4{KfL5n+iorS z=b-t5EFw08iG#znQ@$_d?EGXnE!xr+uH>f=1|~+-Lvy1fAnc$Awp7{@{E-xt=yXhl z!p3>WZ@rJ+WBMtL)p{w7czrvVQ94_d6@e&Rx^aPSkSGfpTvRN@q(!hzsSL((!$%%N zqi)7q3hTR+$!I05qU|8`u@}kO5~ZFnPlG<~O8`BR#sEozThDl7!6riS7IAsbNa;W+ z0ija!;@1yW#!#>A!CTklZct=!Y)2n5cN|k@5$2JTTW|sm);_am4^EJf^sFoO@YX!Z zBXP6|k}T&|R+3FyWX(`>?fgG^mn3Fm2R2@~IMN%6@x1ly40=ewxgT;wL>!J*(T-QR zs@oe`s;{p&2n1oRhu3EV-%OHT&!m3!qF=GxO`@?WiI--%w&reI1>zCva=l+a9p>1Yq z^xdb#D|DcUD;?iXecZ-Uf#HE zvU3017=8CRPmGruu1JdaI`;77D+1xqV^y3`CxH$?t^0`RJ$zQdsa~31Gk?$W;#nP@fjfo+%c%cbDiYSZb%w;A z>J!j{xUexm@$TpsoyI8z!Z8EgJqe7?zB=Y(=Kj0-2y5^=*Aag$1p8f~oKlOk)N`n&eEApTq7SfPg&zNeA~RK+k`+!x-3MD!Z0k$_Cf#djUp}}Y#Kes)LQ0FFw?GG8%t3ye1 z%@-Q~D$v~Q3Hqb?jC=Ke^toJ~HvP@R%t*N$8_{9`;P?JRV>Z+-qzGhac5PYpMkka1 zWoqHQM930AONJ*UWKZXu=-o?|=CmPMvH&Vz{>=Bxo+CIxDAJR-Hl|2V<@zcKkNh8& z52J!UKZzDSVy(s!X05eFIxJ{H zN2%p;Id)f`;9D>$Wc5KeU}#^9wf9UuF8jm!-CB#6!L}VpSwf()DRdo=aLIVos#(jb zsUV6Hz&sj?T34qn(XK(4K#)d%74jo1gSCLxGFekv%t~Kap~^)+qOgxQ(n|t8>&-5o6@t)_w&UkltXFT^z6}}CUE0;geWaq_KWjFQvl(r!mmn56TOOMbkM^f{ z=xq-C`0^v--Pzh~XB`vz^ z_ci#z{&QDFq?i2Ds6fEM7L1M##gquDf+gP8$@+Ym63Oa1N#$GU*_Hw-&sdfcvK=T~ zmJW>LW?6xWr1>Jy@z80wnB!pVQ&TC$c`~QDN|`LI=(JzZy-I!edyIRud6i=qmJ=H2 zBWg~&E355SC~9QZu44}{G$ty(st&bZTXyWfpO|nuzWSQln)dceOt6rfdJvsvs`zU0*rdEz zf337o)^&&s1UcA2!2$^fLwKp)k@O6h;aRILls$*tlZEEz>T{x3Bo4urvnQz=e~aClc?y?n1jYI~Kl?VyZcQA2 zbo}go-7@d`xPyE9RTk!dm>jk}zuzjm<&?VN6+N9ArB>M=puT(hFdkeF{)^ueDXG3k zlS%Rs8}Ya?mhs6eB2ih|c=wVOSQgzPqGwW-uG7CMQ5A za8S}1XQmq9LBn}{w%bJpXne?ar)`u3_J1a8|c2^N(zv0JHx3Iz`>P4_02 zpP~hZ24_eF8EWS@eIiXK#7UEstyd{zdj{?TK-9hCJH|B@g-q`D@RYQxCXXGiLn}IV zNMjJZ0#!oiN)F#8B6SL0wO19}%d66uuCO_i1<}72Ny#fSgB4I27 z=6SDv(b7f*uz}BncA_M2k-ymdqw{dGI_l%(nNXM<2@5JA#`q=CtvWAeSO=$7#f_Cb zpid}M_JQiN>Fb(HMRc_z22Iu;$`NZL zYpD*Fagbm|RI0aqgH%ZGns*cQdj~}iRM_jV7<#^oaU3Ve>oO}*N2(wJr-s+D+LzsB zloT;Ot%MJDelh(iu92i4dNFn}?n|7~#g#n9{lm93O4%u&gz ziHT0H*2C7*_?Jk?k@ZZMd1Z|>%5wBGa8NlxwV2Z(ME{O!lOh8j2o!?W?TUD8<-7}K zk&>3HJUPW~-@cBoy#4*_+nq1;ao764d<7sNI(+skDdLg3K7?mP!py|Z^8I9p20wUY z7~p?yV%S(|2|vimIC%Z2`t}{-+I?bUz3rWgB@BQPH8nbbBl1AS(oe+f7ljjR8&jQ= zQoJvi9nLbcgDeWf&`NTOz$FA1ZlY(lFlyQgx}kYl_NzSB8kXRRlZyVU<2Y#aPh(9s zO7zjh8n_&bOK=_r=2u-cDF-u~wvuF!D{^wP++|A6Wz)ef7WB&Z)a|iqVg5|W_zD-~ zgbuSNuZ#!Y?w!oF`+sqQ06ifZDH1ZomL_0Dr3NWjKFY^dEK&0`R)6-u{Nzm|9$5CiMpw8UtZ>D4s z0rhb|j{)>={KiTxce~-5EHY&vJ!arb7d^?}wY<6lxH*hYV$*+sHf)uzhO7c~*0z13 zDk-oz#fD&VI3_$}ip_=LAdW7a<7$!TH%{$58a2Do`NY8jFa77K32UvlPp*e@!(H zY4Iv`wLZ-H6mG6AW?Oee>8l$1sNOT&Wdu#R<4-Mkm z`tVA{`SP1w>pAaXr%@Bbw9nr=U6(?xeZv)jJ(y3(;Af)T`MaXTTXz3W%Tt0HywB_N zo8#J|Y_)|W3>TmuVo5ayNb0=bUn1q*vr2w*4VCEitKfoqt(dxMN=o=bEK9~^uuOMA zVpU#&g3N!iua1sgTeaB?cT=9(v-jjzLVL0syV#TR{(2s8L46;$ztBC}Qk{;atMe8g zNuOfni)4u#Tn@h3PoR3`SuH!rcVf9FdOZwFaY^T!oTwZX+Y%e8UC1>-i1_NL-M8c# zvxV!dKdiTh`BTTlBZXt*dNJejU zMZ#T;{9H8~TxG>R{IyPFD4r3mK+w|v^YoUC(lEGpCl z%nVZc@kYHy14A8#rR7=*04QEw(RET?>6+GhZ@;i45$1Q&y~ykvLhX~d*0P8CRRw;Z zP6MDqlCO9j@)f^gmc86W#*`k~2l5u`1ZHj|0su zjf2L?>%V&8tN+mVUOz2k@AmHwo7!9Nk^~NF2Lh2%Bz!_s+$8$Q0dTf_B;|D_(kp%Q z$sGf4THC@lofQHxw{V*O*aIgJei?lN(b$H4<$9`IH9x=Nj$RzI64irv3bTT(`zk(r zh4d>m8}_YAla@iEsni(c$qr(2iyB?{(N6JZr+%SF*nHa={^5hcBMY7QGX3V~tmq#9 zK-#F$-9!0~ugs%(Ng^53o5B3FEOflYMo z??k(wQ#3a;dg5bIskTaMtEnGe^JXxyzJeSoTuqJ*TQZ2>JQ|b;1IPLkI1wfOf@eo` zo$dlr1QGe*5%yNgL@xNqX;PtkRGsYY8m&)s!AU|mnKguVEw&9O869JS3syLU9){s>i%k2o&3pfSOsT+o9{1#md_cylDm1TuFxmC=4H?nF}!+g z5{Z48;|A@CY?&pYn4Kkfvakj|L;XIYu_2PeSd^3fw5F^#rt!p3Jqwuv^GyC>SROP& zb7CA9UkjH3Hu#@S@X2X=^ZCha;Z^{ssC^X@`{V1Y9W?hj51g5?5#NARxzqC>&7-`b z*amjxNiXv=b=mGE^5#6d0^UK+HXqkY9qMC|B}aL)zhO&0mH0k+O+E;vJ}QkSyUzR9 zqqXn70}qSZp&@V0fN!#V+BQ$M`hi^YPvC`P<`85}~N91fNa(^~iu>CG`c}$4_s+c2x}fc%~FY z(n2H-Q2;d&i8wrNuXZyzHN18zmg9t0Owa$B0-9#g60!|7ZQWgxvJFtnhIBJ^RB)Gq zLuDeQo%HQB{<3;JhuxD;TY2}%FJdjmm z8$+F{!8)Wm%V4CTo-osw!Rf zL{5=NCPVSUStf?!3Kf5K`DpD|cdbH4>&nVqy0s7=Imyj{2ae_ysT+pR`;$*+Nge}| z%lz%s+~1N|S*lM9U6$a7BOX7Ejg?x<+#~~jGyF)&5HeSqFaRwffl{#St8n{2_VNgt z%m#ioBr^|Gz^Cmc#8!e!qg<)!(Vy%_y@`TXbOioxbQ z`}$+r-=7cZ%?^4w@zOcBUZVFMW#!tct#C|r5?d?>etC&)@Eu>^=wpR#2t9I+FXvtf zRZ7PU^gWP-A#@0Dz?o(1Flv^;lkOT{S8D__dwQh1!Bg_rM*&!wO;d8?$}8^`VQKyO zwzf!fa!wXAPQtUbl)pdM)!aKsGCxXXdk2&&m?y+2-nHAg@t9M6dfW8-BSLn{MYg`v zm=|#!P)ze+2q{L*vr|_k=0qdH(b3U_mG@5R7}pm?wVz-}V8)c&CjZOR_To>DVz(Rf z=+{+9U4e`?&>JZ~v*!>1)bM=<0Zc)8A^enkC>K#Mr0f=vy@Q1KLxM+CfWsuDng706 z@PzC#?|QzjBkQyJ_&fTW=lxYlX1?dA*U6)$0z1S0DmCk1M-f5of<)3jv0Ws5n@IZJH#bk=dX*~kbAl==zsHvx%2sb)+KM*w^y&FoK!BM+B*4OdMhng5$ ztzBgKza9lt;(4YQNzy8>m6I$kS$7-l$Be$b3SW7&I&xU59px*ww2qIlP;(6-eTg`( zN8B}gA9mL9C=d`tGX6@pdQ=)fHs-1&Y{k$?#q`w8f;nw||1N>fLRTjZvJw@NlZxpf zG4I{`Z&-a=UaoaNt-jq9d1;?aTX9f155h^N$`Xx0H^&rc2?jTBe4<+*dee#PQZ6&y zg2hp4W{hiU>jo%DEIzxaL$@_W6!Eg546O@iX^p z9`jOxIbNz&YQ91D^F6->7pWChT>LHiaNrrmd-m|*VYS(dzcL{a7@>p*!15rDXkq9y zfmw#7XcF_UoRBhDHpFIea+h-xn7(yaKw8|iEB#_m)E`_gYcXUQm00%BTmMHf4uiQM zPscLiIqWXrz>Mf;Z?`#N<+D6;;*(ZgK>Z!STKYqM2)XQpp)7Bf-9*>P$i57>vHj#R z*F9ZUu(^AKpY{Ftg_~l@)9yLo>5jU8IBE$u0XsEFYAeJeqsALb)Fi3fok~ohocixITM~r(g*25OFiBS43hI zMc`l-3GfkGZ};#RhlJ6qR~_`5CzPSQkMOvv-1E$E3C^Ga(kK(*;D)EOdGV$iGctf? zI^5+4)Hv2RH}5{b!)J&EV(4Jb$jn!wBr?Y*xUl*KRamsOPBUwDb4o|08%I$1m=>(R zkN$Bmw>Z2)HQT{8^mNde97y$Eiow8>8ihBkfwd%a)MUq3DW${cNqes>f^NemHp5q+ z!|nl2pz`108gm@dUk_op>(Z^Dq8vGt#KQ@BjkmAm$!`8E*yoKcek{MYe;l7&Nmrte zfLk(hF}qr7SYh_k+TfMrrLmhwMVf&+m%@zGZYsyLU(s5)G!3Vk*|60|aeHYv2WltE z9d@oZdWj#Z$N$!V%UF(Qz8^c0ccuxy9UI1-iKD1gxAgvYJlc)^rzBxNpPf@k%ltB? zet~dUu~jgu=)?c(N=JW|0ba3lfZoI;C*NfL_vJCWF#7 zFB*257TAMAYGWkX&nQlm1p8G~=IMmP95cK_r+Jjd7T+U-PlTG}&@18mlWI9o^Ofz< z79qNG!4Zj0+JwDd#)0gt*j9Ox@1Dw!iH#5PA=1getoaV(f6e zE39n=(GF+9;2uPpe<-Hcm9%`)(e~hLjIR9>2A13;3nIf-vi5P}_WoP%4pvD;>c*Jm z(c%T|!gJ`?vaSX2PPnMdT=jto$Y>^kLuUtP-xG+DxYYj;Ye&uUL$AAhoEO2l&+NH} z1I=Qej%K+PP=UFhdLj|2``(L__y{SQl5;TLuH zHJ5H!x^aP}Lt47KTUxriL!@Ds?ndeE4w3E#5h;wo>k{z-K~UHzj><()E8{yqpw}GF)BkyFV`9p-lbcbTNq;xP*$C6oX!ffN!ECIA6SRY38o}M;p$Ae4b zQ?*OwZPY=6{j%X(MCjeWWss~Vy}vhmZma9PLqYa&GPbxqY|00-_F-nKy9h42)x=fH zpE_dM#Z!?%j*}y~w2)Ge3QI&Hk^(KiZze#&)5+I@t?@H@eLF+vhF#@nb+3cRuTjip zQ_Z>Y2a#16yor%MMjA{h*4()s1WymPCGtTr%Pkzs5lfl58If>#fc+(bvhgVnt#@z4 zx0<7K2*cgl_mwkg{jZtvNf}JSCja)jnl7fblxJu&EExu-dCDJ~LCAh7=;!dfK^KC1 zW8vrl05O76PRVqtNsBLoBXFJByY%yhJ!OX$-RL?qkSbk2Q_0tHTw=b75c7I|+C6}+ zGV!McKk)v!Gu{ljfK~hz?{lB_X}dV@U9EDmR!mljWN+socIb7k3ZggWGCQsve&u%= zKKVmXfCXpndlP<~RE#=d563w79KIBEAdVG3GR7G&48TN}T=2Er`B!1@cF7DS%62}Hv8I<%n*e}@g z`D9LTEffe0^OFy}mY{|fJRqc7K~UY%!PJ37(Qjh$h}L8vt{T}1F3Tha z#p)U$0(ex-k@XItf{gf?6eFSf{)f*=&lj^@zU=}KWB}2aB!b<-z@Ak&caCfoVO^C%>j>5mQE#M(E zd(`0eGWV7BdIj>I`kxISP7LFM@>!l-a$S&agKD*4&f$F_ZjKgN##Bl`$>_mC)WYoP z111OQ6x!^l{qM_#&y5eK zW<84jQ8)EQ;F=zJPC+sG%*%N)vN;*0ybD|2em>7RXx2J9n>$;NNpMz7#TlbO4=wvn z(d}3yq>!qr$+m1^F#_7@Qq35On$eno%eBcd46IY>%@5O5|CW~7lbO;S)GDFg>Quhz z9he=h!nBiCjx0v>_^2DNqUOc3ya>2XiU%JJDb)VS`Q3Nu@V@x?VHamKQ7=b9~rQW+o@_v3E{f97fCyY(PdzjW7 ze4%-K|9k=e?}A-i2y`k-G{}gKB5~<)*c*XP16=7YT|Z1T_i`Hh`7Wlt=YxTPpjo~g zXjDOBv;4i(VV89&KDW!8GO1x#hGb6)wnRFi6QDT{i7H2j+UCiDG8TG5mwW<}rd$b; zr&4|njm;=X#W7NXW$^xBNSd*~iF}quR27F<1Ob@`U1O>J^n&3yXg%GhWD z@`a+9>=x0<(U#_Vne2uI@R-w~5%ED%a5bCOph<+J29gBYNsHVV{qX^gjwdr8K5m_F zc4xH@kE1A|CvTBfmEa*8D48TE4Ih?af!}(J2>4L{9Pf_Lg!S=vC`iN$sD5Y%h1+c83L7;QV{GYK^j^8gEWQ0(9;Dq#)w@H;~WUaP}p3^{kl#rPr zk$t_7GGDc8pHdCMGxH{HwZ}DI`f|#m7;3eiX5anoED@I3AIn_|ok#BBF?Rqqb4*51 z$vn@&!Uiny+>m9{wD+OObAmk)9IGDP7>Sb)1Qw+V$)q}{=j3`0HObBIGkx_%gs7Bh z`=9Y=OpF}85l}0(Mo+~Ry{$WgK2e^|U)3?pPuMt&1?RB2R?ao+XWJNOX4!@xKd=R#f*WSmDt)Y*S{DFcMwh~+ zsQ?vRk}N+30d6FrC%l+43uMJyOUZ6@HmTFoZ2_IQUx}x-XwG>2eR`*BXu1?KqqPDp zz6{i31)tG~Teujh*@(=_oGlQov-1A%ua=vJgmL0BM-X!nDl@^8p&EPZ^C`XA@ZL7(IPm<@w-x)G zo?8DY@Y+n9EOx@$=vOj^eXk>rQw#Sqc2@gaXNMa5>gvn9xP(i7LxLroynj8CNNuG8 zVD185w8W{_)$eJ#Frg@y(n-bOvPFU0hrlh^dD7$4R86IyA$tN?l2Nyck!okU`X1;` z+%!#unQT{+Nrg&}JX&e@8~xV;x?}BjTQTX}%MpU}J-~&RXbV<>SHFX^vj2(yF-T(( zX;vpGCbOT3n^B>(7%z;XRBoPaUF31{Fw6*+Y{d=r2}^jMb95!Kj9wWHXxtmRv1k7D zUgpQjb;rMtEE*v$L*9nx;StUcaI@-GkMZ}%zc6@rSXozB2hJ<>j>~1|qj`(L6(JTwzs)ft?Ry3%pT?*J_ntd*2H*v1)yalOU84cJmQx zZdGUU&WaWaXA~-nsvcLK`*~Vjk^O;?mbh?ApZ*Q!!K5yfxbM35Lp?#-fk|FNSlYo- zJw}~Z!t1TBG%ximB|60@GdW-_L>I*St?t)NIOLOb@?TCmsspRE-AkHMx4;6mZWp%P zGW-caXohSwH;QoVLS1}Vz(Pbi%=4IQzgz63aMz&(QlwF*jWf!WnZMzAL^)oBn&?-G zuZt5W5zxPz?W0&rQK!)Bo1{bwm<|u|TrWD&lT#VS+5SEn5Y1?P4*pWY^Qk`o=63!1 zGz3ol_{>dD=K2P~rTP}dp~%Vpa(Cnit~yUr3x>+6jiJ1NI5{cDJB6aFL^}I>bB5-a z^AlH&cZs7-JyvgbVMFipH3Z^o5O0^w}f#Aa`d@m2bv^C(HRkvdrk{4A6ZGNe#K|7_% z>)^ge#)mm?iN)u!o=vz6hLDqe<<&Gv$e)?>&-Fi=Cx2}9c2^{Mr}Cu?_v>X-(@K&4 zTq7MBP`Po}_~zSf!2ErBU~5tl~G!o4XW@TK=8q@0z8kjb{Qv(@K@6ZU-2qirbx)CIv_3I2F zd3S3JYpWw}>|iXB><(Q9E$SlT{k7`>cH0YjjzfXHIB>qlX^?`#9ex3CJ1Vn(+{;XV zS0~KzY0_M6mm@*mShjrddu(e$3Y&mY>kY^`N96;|B2x(*Gj`u(#X0m=e3caTWvfTT=jq4VXMY#xs$!LRqpwgj_t=qJ2D+B=H360$aZMBl zQ_Udv=!GmoQ7r3pH6c1BKGYN`c|+)Pgt5txdM2c>Aul(*ZAW|FCfW=~*m`EB4#cYrfyMBc|w`{1m!ApTNs=9!Y zvTf}m;~aKU>mTghRGLcmi`ytMkJ+6{&DZ2g;lH1kcsT*22o;@Dwd_B|O~0 z;hDmdk4d?ImuG%a>EN%)#RSMDhq`JFH@y_@4uHRL0#Bito}{Dt4ey${5oiV+Q3*x` zrM|O)z!*L8sgy;+tZ~e5T?rKo%*xt?oDGbsCN*HMEB+;2QwxPhPplt`z17^$VA3N% zCV!NGU0lpuTs(aa2m;$9N+WRK7cs*lEqk(2!!=2xy6OaV@Z1*LdK#y92#wik<|p&SXsIG)Z*F&)e`d+sZ<%_rIPwKy|km=32>69 zm`%C{ETxK8a4LG1CFiCmWT)(_lG3qMsVVY-sIb{tU?m}M{F)7WJwONuWbB~_XkoJ` zIH+IA`Y?|Huh))L+G-aH?UYeIFf;r^=3HK&KqZPsqCzfaPPY)=3=T?+Bs4nTiRIgw zEIa-;;M|~JQuM}p<&VaI4*%QN*GH*xg8z*h0Q}Gs_)>9BnhmadgnRkp{5&Idgnh2} zVIftoZcc`Ha5gjZz-%pF5<@3I^l~Fn2YFRzPjlzssmajRnIU4fbATSn-z9F7%UekQ9gu(#0e4rw$<9C1fabD45KrpxH z`T6gb_#JzCKeZ73nbN0sG>6!$)k}Wn|Npf!)ccPuM1TE4b+9k<`E=CYX099k^ITbb z#r{2`v9b*tFM2i>X%GeJL7zXRA1jekFcNjP5;>BTOqhRrhp?dUiS=o^E7zBG&m~nh zIs`ijvS7|g-`9I-b$qZ4vXWm+57ky)lO^!@v1)#^=iT1cEP6of*)rqvn`ojb3 zQExoM9}^A?NW4IsSf3J68G3)0vnIV5Qn&!c6- zprWhuCP8vxfRzBfU1T&@M5`SAv8X~R-FnbGY$>Z&AGPx4&78o!HHp0dyRw}~ zlO=*}8_tyHv7c`K1*F#2Xi*n#X`HY1p=Bpep5ekJ@Gi!wGLrrD;p8iAHb8ilArK0O&*qGdv#UjFI zJO5V4w4KpuPI&h`=`L@RfBu<=4z}_bhCnQEn!^|m=QOMoN-0bIxOhY0yu&y~3 z4{|uff>J<9KsF4mFd6aJBRj&65(Xz$d>5rUMcSH9W{>;gJh=6i<>_K`*59qPu5~1t3MyE=@|#M^gXvydVEQRU28;VQ z5hN@CbPVnYhh7{goXUR~XjV-+-(&Ccv>KHBIX%LEEfeoC#2X1u1fl|}74ZS6*bQm7 z4Xw%i5AxFl$fu^BBaQx+PLCPl@i zw@i(PSKB2cHF~m6NBDvscmT_`Pt2*P9U>dce}M)p!Xh>6_c1y(7WSDQ?eAXm2LCDg z?c4HglDpvj>BdRj*EZ*W%KNMaUXF@YoOta0yAgw2B4Paf@iYfmkUGq;A|v~)F5J)6 z@ILOODycSwASMN=9-)eKmA2p~=oP4wyz%!DVQKFi))I5NIGKV1-OW-L!H8dbvy8VV z3zq~jrHU1Ljhg&nYVB`dWz!NK8<&|g2}bl28r#F~ma2DtA%YI7%<@!$?et&X(T=1U z1@z@`b*lXPCnH=lr`q>!`cGQ#bAE(V26L&DrO0(pwZ*#px?&2lytxsU`ao!p+7MO+B&fZs-9ggX`*vII7pyB zcOg{DJfIUvIfy!veL)Xg!)Q?UVnmjHQ~8o3;!e!JyeE!Nb6H;d-6R>(#5ajjSx9Pd z`MYiti}<6`c8p}j%zXWA;0@>b#byuG2`sC@F+&4gXhNL6s`qia7P*uH(~pDLacLSzE6j3{C=;K zgI^{RupoC}J%%e+;cZ6*wB%FxPtzW2vCrpo8dFjcIF}#JO+3NAtWT7`d&mH$ zvj~QgW5}9@Z!kfU)etmv89=*)W=Tk@i6i*G6weGXqNhr8)#BZhUf*#o*B01nb1f%n zBjq$^^%P~G+3KqrIg>H(-JXzj4%u1(GUZ3rxTN>613%SGZXQw1weU=5J*GZwu)IPt zz9Q!(mZNuph8!JNjBw^8sI)BA2>d27?s@3ru@q}+RYrya>|IsCF<2-TsFJaYvWerY zAE!{zou;Ei0X`~G$y_8#muhXXCDQ6eYvIJ+s=r665dm@w0~(+=*X+M@hO7h{NEw)N z-{u}~Sky%+`o5qCp7)p#_2O>a!7XljiooUPI>7s^=bJhBDBCN4K=0~G7ES4Y>LSyL zCS!6bF^v*7arq96OA==TmKrP%BBcfiRw zjMBv!rT4-w=z-^m2o*$4gWU%%sXgIc^JYC?+g_-NzyX+-wW@pQfIv`60m~9wyI;#v zsJbdW?%FD0P@o+{&j8Krp###f11oxmGDYpzw%IA5%Czb7zU};UYofww*Et!PP6mRm zWWpoAY)C3iuwp%lRg~u$7j-mS&cCaZJbW|2>K0(tyA(bMPOJc87MpwF&@*>z{y~o- zp&KDploF{N+$(04EQz0OGV7ft$wf)f|CC~ES4LMFI)I{*haML7Lo$s@*ie-hnMjMO zJGELs0xRVF9QLE9%BfaziD7~ODVA8cDncH&Sb%o8`z-jM>C_hr8=MyQ5UV$o3=E>; zqKDv!dAs>+2d=8WYJ9*_TrMq+@t*Zz9CcKeyZqKY$ZmnVp>riE!F!UGe~p88DX~UU z+QTOd&^IsW`5THKhV`Ppk45;;;(5DxvNp1^I=24P-~Pc!siW`d!TWvCMK$aUHdPZ; z<^o73D^TL2=JTWyvcX61J{Dfc6cMt;^#>7?QDo#wn;Ek4jSbj*>*c(8%e&j|Y7%** z=qgCN7)z*Y3(!ZlmM1?_gA5kXlS6)5($VeH(KGO0$#4LM-d<<@o8#KrGyERn_1C#H z-utiq^PV{S&s=75DZ-uTVOo3tP!ZUz>mQgYuUNal8Y>@anjjzyc{>UhBU29?7!8FM;U1mfA7^-ECgkpX|uprti zWGGq_*TF?57Cv|aIn0Y~Dr!XxV3@C(+u%*9Rp)W$wlj8&`1RJoO#e{#RdhjB{ARcV zM#XH;{K__-yzjX~t7q1V!7=~t)nq#Zm@sUCYOq3NcSa7jp+dyQT1P4U5&XR! z!aqm3uk9hm!vx$!IReaIlg3wX4wC+`7^C|9jtu+zWU#*fp~sZ$6XRn@Px4voS$gKp z3woa6f`)f5iG7yLa6tonE#x!qw*yQ)EU3&i;+fjY>Gm@OJA@N=vU3sapCKa#a7mRa zy^kDKj-4j={p>U`n6cEaMeA+?KpEbVp{b*NRM;h0w|XPgIH+!V?aM^6AtQ+2_9i&G z<)XTmH+yzAfN5(KltxZ=Y`IgZvP0LRN{2+`^6uNrnJ3L!Z+afRZe@G7?4eljx{+yq zrk~qGaApPLEAWNuCm8SP#c9I1-~PsATXQ>SWVg0IhzQl6uoNR4gBC?>j0+t)m#qq25}S)iMaRzQryTupym{aCby=fV6Hd*- z!wCR*U-uJEMaKvBD6Zh2ZySSlol}eIEKd#RDZ};vJ+pP{9}Q>C4K6`PIlj)5HOfWF zwql`|s9$#xxz_BZ4#c#|xO0!6&(^229q5?>xah7(3KSrRWaJbF#tkeB8(K|A&ha>q zq>aDQ9dtYX~#Dz{i^Jo^QBURZPN|j=+~9T#t_y6Da4kC2dGzY_#N8-Lx+k z@G*dZK@D!#Y?`F1=Yo^;f=TB@8S>ZF?ELIF$LM$M%r#HhD{#g8ue~mnJ83*0g_-YBDJY}`P2@$Tqdx7$INuV(-{ctg zeMc`Fib4{4n2gMA$3HlZ(%&(UAHJ+!G0{tl7N6MqiVV*;>NX?8Lu4nhLV_v1>=q%s ze?$ze8l7oehF-MQkR@`rQ-8cc{~YGTGm)roE%}*0GwU9EEgQx_t}?oGHW82(kP@^gsLK0N zxQkFtIfa+zkB+VOrTO!&xBWQkOJe=CeB;^$%sc)C-|S0y&ej}VUk)tC=9{<&*hXry zd=DH(KW;_5C+eE}1Uo&ha&fi?$P7;F3rdD*%BCmbV>>dtp_XcUGg7+YL&UtiFKYYK zAeny;2@UPSv4JUPl2GyK%0vSx-m52UHbcfQlPtV;zNUvdU!uaAft&Hrw8|e>N+uqEsO~RNi0fTTGd>&HhKXq$J|FCD47yOdfN9AL&`|}F zHI)P!_t%utNmcm{D!c7WgK%qo`fE6#{lG3c`GH@NTxsgr-0q4>U%I(;SIIhu$#sM@ zIQGP#<1KXYd%&Wx4080=IOffPw9f*6?SMHF=^b7%4w8m>vDi4${hltEQ8CId$L;}u zr+Wb(R$Uw^8@S=0{J-TG9wit`=YD5$o8RSB#>AL zu2yc9XIQx^^5Vv^{)PJCv<%vhozxW4mS%h9wKk$eey`6qSIaDyJyrY^L{>kW@1)0* zhl|+0g$_mZrxdl0m+Ea@bMNHxm;UaPn8BJUqR9@4RzO@@IlhgFt9!DmTOeI_HojV? z#~|A4>2tJF@@8Qu@{Pv%bp6_qw!q1S4gt^phRT|@3>6s_5@AV@+J^w5>z^0|@3$l^IU?ZL2`6_))YBn-+^#jx{+5l6wVbvLBc_~C8}TB*h=T;O@en( z`HK^Gd2+$D$^4Up2{~EK=?diz4#1Ytimy)N=oweViwW5kEirFC_>Cw+V(x)`0U zZfV*2)Nu437SiBZ{p!dmfwvktm6QTzV>K*0EYiYnC9UO7P&cPLYb=oik9~jHjp46S zhn<#sD2sD92B#-n#LU5 zRMf4N`;6zut)8k7XZuuXQA0u&?Nu3sanE#S^8^+QOgz-iD*17`x)hjCS*vxGB0Q2< zFwK%rnNypWkwDr3?Z+)y{mQ5^vH|@4q*HR4u`mRvi@VRbmzTOi_p58rr9S!J&*w`91QYhJyT1+Uy@4o?-9&7_zNWjY_IPKIMx~A-Alsi|38%kXq-|2;^x|Sn6B1gHpITVuse2 zzRe*!XoqgWO8WXb7%e(Hni0Zel`-oerCd^B%5wZ5pe(VSa_@)N%rY%>aB6>pPDl|n z9?qGg-_^V^W=KNNY*NcsXzkCej7|iieiKEJhlW;yDDSNlOyzU?5;!cMPV=Y zCprYG7eNEaFhvomh8sf{?qDNTQhe%r$H!L@hb4nt78U74EF%?q#p*enh&!66*jW7T zp|5)D;u)@gD^V*pOK}7(QBedoMj)pv3PjoSU9(ZTP6?rP(__)m5TGKVgC=%byqMd$ zxP`>he~t}tkCUg#vw!O*`h3(z^Ar;Vosqk-2r{^>#l}po&=Q_!r;zDI4co^4CjXuV zA8Z?@w|cZ5_E7s?oHPf6Bz>YHb*y(q%*<}%U`jX-k}8RDh1kd?gU#JUts;6ej_)C1 zlonq4oia>2=Ppi#2IBY;rB`EGXcXwqC>lR6suVo0RNr6NeHsc+9sX}(?@Ifx`6FU@ z5k~1o&E9_1sutoeny_eO59iG-_|A&BrDD#=e{Q{@EM#xE%*n&O@VZ(#ATzyU?3Fhi z=sfJ0b2lW!st!E=Q#Fh>6_7Em z@_JrUcb>vK&K!5iK*tBf8Oduo6$7a*8LKQY3!X0Go?ou7g+ITQKxQx*(yOFk^ZLl7vji zcVSECtbk8NGL<<_UBQe14{}3@bQvwOJCC`aV1WD0u)%{ohj5f#Rw28{^2gz2zYoqT z1r{6|GtphFpFIXnh6S_`v8}=L`x6-@uqFjl{Ayo7HzIyq}^ z_A7Ijn-t?CBnN>$w9bQ4H|v}ru6+|)Ny~aNf-x!09}^NS46)9V=ad_ozUD2S^7JdB zg__9Zdd(?j`T>Y_B0pggzx=+J_;S?vIX*p2*Hi>q%Z6fOBXH4G&hzj|$%B}!EQgdw zQ~&l%3KY*`i{Hx`zBiI{opukPRt3vbk0&!%VdVz;rl1gXY2?H=cV%IJ(yX}rgfX6@ z>xL>NnB35%X^3DaW3+rqE$hyXC(RF6`KMAOdU|MgBc6{EuXP%e%*s|P1rA+$fPu?TBhN_s zupbXo(2(2a;ZP=m)j@V2KGbA0B8-xNNSDp1`j{LpV};db$`E8^dt-twl9_a=PlVcF zEA@WYO;6Vn^mge4(@+R`d1WhT@MxW(YQ0fy@G)#n^Jo7ca4I;y2F0Bfuv0Pac{G$9)Rs0(35tS|wh%G|>f}V2#Pzo;Ogg?pzW_+~b?kst?dA2u3EllfKSF?(Amg*#l||v&PT>so05_@uC6X*f_DWK^MZc66<^x z|9Egfg7S|`tMJUOx>$oz%&#r4PLJQg{QkJ8hB!k>lC3Zt5iGFFoXQ=T%gle43(q^V z)>NEXDN|D{Hi(MytLTmU_5O&tn(md)x;p6siJ5hoc#KatL|E?!9-}3BNsgfqD-iuM zrA2u#N}K#VUPOwgn6X2f65RZI{k6zHn92)!?n8k`+)?oRDjb*b#c+4aFnja(%;Tt@ zs!iW`^|yvkJ0%IX?fL1vyDHe)K3Q@c1ssK-m6^=NVChgD+2Im^JipFwlh|rlue@3s zZTt$NGxJY1P%;|%BXV8pHQM&QUo85ZdbwIapUIB{#~ps`Qae+tCC?9igEsND=+mWE zByT6xlSs4nr|cBKawDz>T5$(9Zp+SBoWV`}PZah$uxHPBdKxe?P7Cb*%^w&W!^bfy zHQH?^DggwbiL1khQ4pBuS}n?KIn6W$OB=D@T^`l0zZCRyHWv{aR7;^z#96?4>D-W# zf#D!>S#RWhzuwW-vx>VUR!2c^d%8mZQiL-A-pvqvPIKRW;PZrc+Iw#Lej-1Yt$$;7 zz)j1DtdayE^^Jr2V_Yusr3@VDoU%o$QUT9O~e!9u+@@CMpkg4*!iYJp0U6P3>^kcnXfK< zViQcIRj0WciPd&jCnTrutBsW82yzES#gcC{%H*oJqO)-_5Rt-WCgBg$aO#>76J;~X zSuXe&YF>7-en7*g?i8?smDD`kUkeoZWfUu869kqQlj74*sy9YRPTChIEK6ogcCg#h zO(1SJlK(Wcaw~J>i$YX9OSQ%elxBQ6Li=zeym-L8EJ;YY;r9p>zyBDADESv777Dwc z&l>@3a|$4ReAgAf;=h`~X#F960hi;$T=dR)qqihOk=AHJ9X{T^Co1z=JX`W z9&2p)gF0w%12#FCY0QvNn(0s0fs7&Bf+tz@@rthI!%~b@o*5yVYFTa@_Iua_CmZu!Vo?tI)R^x0=|UmsUs3qVBAc z43_A{h6lOjv(h=c2u*1CPreSt3+Olc{==x03`e$Iw%73~!&|;nlEOCALE|dt0u;}%0*#ssJ+UvtWsmy`vws{FRT^BJgl()>1G@9EI70E%+bJ* zBCIa(xD~?lSG$)-@f6kcBkb|9+y2`y1k6svh@e>`K1Oyz}0RQa;!D%~hdoF9oF&Gk?`MJz7Z za#Yq7YU9BokHmPu;vsq+skB^Cq?BUCKR_aT`MBiWx3y1(E2f)3(V4T@r~wfy;_-ek zZCu@Qi-rAItM*kgb^&YGViJ+F0-4`#3dyxky|ucFcs(Q=pnb=ojLrg(OK$wvzWlMe z_ls)rYXT#Ov*87lHbq%J3=>5n224H1(Yhh*!UJq!?xOh2BK%P{#bxpR)`_QYGMMrk zYjAgOEj|{r@Q!r24nRN^u~zC(yrh_v?huRF^!f0bh_2zFZVgx^i4YFxe7BuZ;eV4+ z*jRdKngHoeIss>=O4Z6WcGiqC(7 zRVmkt)KxmK*nx^tU?$vHCZcu2(&lI{5C_A#yj0+R$IBLW`Q3fp;qrK-+AZtke z8dG&nMS*c_ygB*RYiXrI?0KG#>~{bX|I~z>Gt0E~nilc;V`7^GI>2j5%c-@7G-UH* zT_yd|qIf8|i9u{MoGtthJpuS|S)CiAXSZ8G1g_RrMLZKol6|y!%(q-h(8fZ0&ND+4=wmg$8*J$N=VljBn6KoAM39Z63l zokq58r;=M+Bws||Wv!eqBPd@xMIiIsqdEKG|3z`QJ{i@}T=r|T-SzV2F2@1~-KDY> zO+6NKxCTYjXGjyJ=|e7=}I&UCwz)Fe3K&`Qm~%x38IM;JAV#I9_VECAjTNbyZZi>0Z9 zEttVnXZay{l$(hjgVZH0MFn&+XFxMXu`ai!{9`1O3_b*l_ zNPd8w`3mwVR$PPHExQCQT+NaZps2UU6KVWTMnMfc=Wfg*VKCc)tjS9GJ(T~K@ z%_jLPI@w)0MNts>BRyhc6_q{@r;Qk?mKXcR;Vh*ky#cwz$H}SOoVfK*$gC7e(NJFG zWGj?td*JBM`TB0ecBqqSuM`#91NNjz4B*9-&TczToV_bkuGlX_6EcBH8S6 zl)vvV1fvq5hr9ky^WP1Y6eIT&yIDrgz_s8!45xJFX;Ub3bGfmu8blDN0FM~_kaO`s zkc38tK^(8G^RtS!deX?1m#9#DMM<=5q^KX`(t}9RJl8ahxGC`qBlAx!7i-}dhv&K4 zIky8_UC|)xgi=0TP7Z`%*;qa4DQrY#RtB=z+HCx+u$$a>>el9~lQnv`xPs!#Ck~GB zQHlnYta1_a<(ER>oE5-`jKV#7bRkxW^j!*a?Fq#{af8npI!9hSTNa4pKTINkQFN$gHth$Hz;O8X*7AQdu-2Ek&CwKYa!bhQ;?#e1m;y7kIN52--2sNh?Q zZ|a+-C)JvNG4Ii<(PuSvwL6uic9&kEzYQ$UQJ%d-W}TBdS~$6zP&e`x2*^{GbuAy% ziTtl&48^N_9q>fTvicskNjTTpynDrVLiyHxi;e%8ND3vzxig=^ZHbKI~o`wCK zq|N-}{A>#Hu7(*Pn+M2zQeT*-RR-WnS}e<9sFm#0Hm~GZ_9IG-e~D9R%&1D;Ls`i; z^KY}wll+nq1}5p=y|>|?NN+R^$6{^3fy=f#e{RPpfQ#|eCZ-I=$CVD8QlL%LhpGid zo@Z<$(gtaL9?=t32h;L1*9YEZv!5fic<*Y4u&r5H6z;??s=KNytow8UheWEZiU`(m zRIENx(aFD>hr`yZkwgN=1p%%nlsbRL02tHbd2pvrt}=D>Irm`VWcld z2yS{2qJAktI1XJCoa*?_e8jUoGudMxVoD{$+qhq24^fo2JJ%>{U^#qn^)3G8J)T>7 zYx!_;pa8D;SJ1(hn`I~Zm{4LmqgbTopl&fOK`6c;Bt9^Oj(Q9`J?n}Iv34m91=A%9 z+M^?I9B9&(LdJhKULug}HA?_QruX>F1)Zm2+R7|Uoi$lW0L0w5YQn|^FmzAY;yvJH}B}jIZ?90 z6=ZFJaloTT6cq{SnJumLz%&N&CTg*`j)R6(18H&I)4_x!A?(w&@8@UGb?lgz!oh>P zxwGILk((tiKNmb($ULZ|r!4dLzdrtdd3`(|6~(Mid){Zi_xygf_&OR^_IXrJeegZ; z+q5_lva!zQyKe#QOR(pyr?c~ut?qIc?}XN<)Uru)9CY1ZMpe1#%-yxOv?M2c&jX8D z7+HOZ8`)8JAh`-7b+svDiMHzMgmcL}UK`|Wsd~o6Qu~O)@1P$#@RuoXs)qjsBw)6v zP9D3H@8j+_m%h%ymrMNgiSlC%%-_-Yzeq16f`P_Y_sxsVk00aK#28n7zRj+VG7$L={4 zpBn8Y$~2sk9=;JFw+Q9K;==tulCHv`>8=aY(lI)v8-&r)qeeH<5~I6Yx^r|$cQ*(E zN_U4!2qGO)0+Rd2`~3%S_x#R1_naqgiCsgCyEHyqXY&jChSiZ0l;Ms9!-${$oKD5n z-^>FHit#lg-?z{4AY7_-6X72%r2uQ<0m&R|#$W06`Ecc$*t91F>pO zXRB#D))oPQlbeP_$iyCY)N@~(6D6Fd2q2;JKpY2OUdJ0CeCM!etq%2Dbw3Kq!TNi$ zi#Nz^G%WtnqeGg=iek9G(EYsDlxEX8xnhOSG!c1Gk9A5xKk^Ru%FG!k4oIk2)<~FN zrix8XFFNf40N|o2=@bhVX4;~v%I0*EAIdJLw2OdNloX#!lc@Eybim&PW! z@u8#fWGeBebeb}}=VO?%N)h1O6=B$Is;M#ZCIMeT!@irX^P&=<-0&;?ZB&E1c)kqE z@QW7zlT6`LT)?g3SpiGGL~U=n>FnrqiWLVic{^~JiS}Uc=Hk6IbAwLk?rrQJ)}L~G z3?Q-yD0uu;J=NYoi$`RHuK;0uqD2EY;ac8+kLazVvSwXTV~Ry(u{sy=*cTL#W8*yY zjg5*q-SSndbEu(w`>8bxiD+~cVDJNRkCy&PC2vCU-Z}BRU%*{WX}pJ}@Weo>4Kq}h z62xskBprctBhb-}!nWS#8l_ktPwQ*g|Def1T>hAR zm_WFOY=f%&Ub!mUt!pHDs1BW=0lOC?NPfN%7;W9%?e05Nl+e9LN8MxH^HO`x;C}fG zFQH7B1gt>#pv=jO;jq!}?w#b=9CYbg^7Bms`khGzUf>`qBBBV|pmf)^vc^RfEgrbK z{#E2|;xP|CKw#Dt0zw^U(u-7RL$Epw^MTnMrPErFVS@wpKtvmJKV8iHIOIeAhG@Y|EU&BRl4VHLdRL z;E`wTxYNnBK5kYnB;S%1d_kHbHC#P;_wX!vYN)z56~jks@xc~vTC%LBZKL;Y4R}^o zUjpVi$3za#6f+5HQ=nV-N~UFRcV;dys^_&J5WjLt{Y z4Q{>RxcuakhPGpb!Ev%31L`aQ#$UY_jM{-yDT!Y!I@M5r)3`ov#EeVQJAsSO+=Do` zUBil`Fg+a(BSPa=5Y_@JP&8rkb*h|kSgBj8@bSLWN7wZzUy9p z`sYqAW+4?e>1(HLv9*Ie*k(w%d>Ws+bUt|FI_S{Qh(W=Y^e>ci5TP9?gVW$g!O0<= z_nJ;F%6Oo)uRS}d8kqI-^#Ci3@3V<-nbclXuqbrj)905iXyg836D!6@=oHScD)Qa9w!f@f7&CfNjBqg$F?HZ-y@<{s)J*Ww7Cu%%Aj#aSU8z`>-H?WmDE?TS5h&r zxlT1>slKrrAw(fu5iO!F;zOxK!shc#PUO5`2*MB&EehwSh$vp{J!X(mBy;G@!eDW# zyCr>~2ru49xt9g+UHJlAoB_QQlXUcOY4WeunV@kO{G=E3z(WJ(hhIh=m?Sj3@Y-W5 zqZs&z%)wBz>u2JJ%|<_&F!boba(I)qYG0pc@2n0bo~<%24&y=_m?G70k~-9wLm70! zWYA7#y+$XR34U&W`m?d-tHoNW^|N{g)m3Z{IMa*VpsZ8^T2Pq z-xVi^I07lEf|GP%EhD+Z)qeD23HEWb2=mx~C0`};D0s-_*8l!Asl1c}m3VV}RF zal*Z(#gsXg5hcu8u0ttkJU;V%ia&MUds*pITn{`~Vtlx^dPF#Y4f`NEr3ODgfyV|D zTjsB((pPK!Dp=-$M#Pc)!XcNp|Gu)KPW-X(l;6( zeEMq4E1)HaL>M8;f2+PVQQ*_A<0=Pr60VvD9LyT4*}^PI0J6s_4w1RFRo z+IW@+YY5d@Dt_Ck82)gzLwP$LSL_|>L3Y`c_-5q=Jx2)mj>rGKx$d*!nTq7)cpw4K z8E0&4G~-ubM^~{ZwmM`QT!9je2ecRvhW((2z08unYYOY9xu9v-ll|t&VQ!`}qa7m@ zj39@LmS8wsz`4`)6%(=F%9X3)9z#{gUj`5lPDMka)5^cJ!4Zrp7U}R2)XH`@Od!dj z*EW(`N^j=xP^#1~)bAo#s49q(0}Z0)Er_lQ{nDm)tYX(@&fEFv=W=1Nuykd~A}G2b z`C7?Kwa-4@SlHNP=<9$v+aV+^8)Cf&xfQx;-_RYW0H?dkonuK?fbowRW14?xq4hdM z8Nt5?^)By8{rteg?GF2hi4gNQsoI&UG{Qy3{Db#a{*4xpu&2u0@3!7a!^FvA%aVqx zEzDV$!U7h!&I{lVliy^G_ekUOyK3vd%8S5N(*IHMe#pEqLD-S<|0~)ehlM<%KDHTO zT6tW9bnL!7+dnDa-};=j&SpWqRyWtXKl?b9JCzt7Cc0IS<71)WYg|-Q6<2>qQy&!b zf}RGo-ZDiX(VBhom(z83S_9*wZ{;v>&^lG1>yKAWRob=bl9%CBgS%g0;*u&VR#y`+ z{5d$#_~Szt3iTr|;{EW$?*U?)DzhpMX(&)85^*~aWEpvrTzIq6=KkfR&1c5xb@0!} zKTqwu*Y_)DH>Vq|PWiEIxJV&b*tD!X!c5=M$lr} zNM{f^&c$}A>|fA9w98V)lK4_NJeR$`Jl36tjos#~XhT@#1_faEfs+yj9xFd!^Yae^ z%V&R1;mQaGTYO#Pn3^d%BW4m|A_#-QxMyyh#S`O>L)O4?3upeidFij=0xzMqc! zRZhx|*T>`3dbXlQ-$E+8bUZo%j8euTRkZCe`GW^I?s_a4}W>Q(_8YWUQ{LN;p{W4=x`&2~eo1 zBbv0K`=bx8FNA+B9k~A$T9%~Ah7U8TkIV z1UYM7<@gbYbG9ng)s($)nyCiYZoHs}AblhHq|7Cbgx?K*a~&x9H;4TKGvS>fH(Gf? zNh&VgDI+&pwAoJ|A8IR|923hT)6MNt*ao2HGuS%%t&vg;Vs;9J*$+NSRtJ@&BbNzD+b2nthwB&Q)KUL!-Y&Ln42G8 zbLTj!{F`-mu4vW2^UaO&PklkpA$-&k`aNQB4HAQ zcv%i%66j;iH5i;w@|1h#fOCBPLI(#VzRwvHOMh3Tr>XnimTh7(t<)gN?GN5n6OEWoM$SPwx zeZO;7U+xm3`PQjS(wkTOK{C!i_vvwMsv;OJPSZy>kt@T*v8jVc50AXdKE7= z_@)nUeV9`?iY#PqX~&EUIFAa_kgocD5O-J%w`3tnG*8fC1Y)4%34+^HuwJ}zzu}7oCU{)oiC2E)UdI=C z_Izy3F=;+TSj;T*Ts}K}`kWi&1O`OwY7nJ6p@o1Dz!VxpwdE?iTmm+NuIMC)qgpzC z?1XUz-TC_r8lxY!A@-52i*@-&DKCftHqUFVXJB`;6BX>}G5NG!p%k z*}XjE8XQcOs(i-fZzuMUOHDoXLShX_+82*;t!ZpXU{7az!B$EQse%iNxY!y|81$Qo z=v8Q+%B%L+!PIDaG+yZXa-JGucyycww#@nXAfyV5pD}l9B91Dp)CHv$I5vX0hueI= z`+R3jzHbBP4BrU+r+7X?AP9Z+ACVIso^S{6ns2^++;}JrMSxVVk9k+d$H&t)A$!C} zOrvP2HeIAFwZ`IFe^uK3m6hZ4I69DS^1XYAw=4$|HEBK}LL})N zRGzAK1X^|r`IQ+x=SRo)#}4sb?-W2zjR?#wWmb%ji6Ygn7xvcO_S*Ct-G->7G6y`T zeX=@{0iM%7$;|E)6M+wm_0_apCJEE@wL)7<(9%|xMbpx_wg3k#T0Ux5f)F%Xbv%LEI zE1r<@t6DfYEtg@ijnCCie-l!5#<1~sy6}n;iq1&vy67$1dC{#iQl*m?GtZsd5fC|S z*W3+LONZ9@S8_l~tn>;#?uuPn7&;vqk^fHp{4?qg29ye+Pel z^3a7n&(>xKlz~HJFd6WRP#lP~F@2O7<8W--5->I$91rzhSH#kVAAwX!N)(ZsZRc&q z1+c`h@t;%Q+I1H~*zEi`TSU9Kf}-xNY6^CgvooyZP)4NANA~WWjCbFJt;He}g}oY7 zM?nt-aNEljq4AUCW!cr^39uRh#O%UY;;*0oY^=AwNfk`x8dESxfqN0Z$*~(kRcQ%r zy1aouNuy}>E{;QfU+)s~kyvz)#jcA;X}Ag5s2o))+8m~5yncty$ZKt;uEsqF(2b;F ziOO#cOvL+t0mcj2gu83H)u5Nahh9kncEl5akASo|=R+mBA-*a|<-6a8F$&nBGdAxz zyO~23inb6k5zW(x{yX`=Mp2QXQg-uR}Ldv3kAnAjTQPz>YsILS%lqB7p%bhF8?s*{0~3T zmw$rB*(tqF_yKC+0}&0#;pBO+nl3GnqTbOccO^AvPk>iD+rz3&U_85AW^gt~sv;+c z)gSYW^bZd@k-;u!r$h2L9g6b5iuI+5Hj3G8P+ILA(UIT0ndH{N3^h@Acp3vpNfSBN>p}$u;)LB-^*b zU<nzz# zluT#H5lwSfRdJI5cIFSk0JW^pP8=d()aA$*MmEVT2@B|v z97)dp#S^hd_fBofQ=#~9XcHTTvR6(xRwsXAmLfaWc#M9hDuu3c%Wa41!K}cE_(JhedYT-&KRV{q`%| z3>z5)bw3A@2#&utY$~U7DzQC6)2j(}9HSkd4snAZBD}`UX?w-bV}Ye?`(wwmc5kW0 ziJIT`xAT<3N`lFCj>e)VP*jqp2kK=I5WqWed!6*S^iE3|t?*WJ%jk6MvuW@ntnIaA z@Sd*m+XqG`Mhgula6}03vF5KRE2|DRv9=Ifz{G6HNdu=EGLfwsIKl2x2~{hVFlKH$ z20HC&Kj%fH;o2e0LN&xr(r?d5^HDb1ODxJmOE|IiDhQs-Vc{UG=eMUfRhto(fbDYZG3b(J3F1M4l0j8 zFbFXoGt~hP5UMPrBC2Vac_^}q8`s2;078DBr>MtGY96HR@{SSZYS{rT-+g1*7n?YF z{J}-|y{r^NOPwe53(!EW!n^b`lVGL#EWjK=qEXjxzB71$n@EwT^BKO2mK(={f$Iq0 zm`p~kEsZuC0@dL@tcS5{-vF%obiO42sOgqslEO~q0!rDlJ5Lk^Xqah#bqQmZh1^)N zQqVcha0qA$PrQ4Mu^NW zk_`8|q))6ymzL{-+I}&sE-PWtdSKTzmH{ldI71Ub&)K|a&Rm31OJXvKAB7V9G1tT7 znb{Td#Hw>LcdJ^d79pGL9iXQ)F;pYtQ zNn^Vfu>MGD1$xtzt&nU_Tp)ItRY*AF9CZ}nijT~e3eX~JB^N%HQlL9kOz(yp0rF%a zThfXi!WSl3ipMku`Jt9CaGH5p*3SJ4_1rU$s4o>QT5kDl#bdF~MpdZwI_j`wzF(WkBKl)O^PPTQNM-ugDn5L*SMAmA0gZh!wBsYy z$i=uivO4S0B2_$DSu~IQTVT+AZD?pvXYkIbwe4(JY<_L!Cku6XJQP#TfwEI@j^7($ zkLH)%WfoS}_vG&G=gk|TnqLAHeaCgku#KmuAlS_Nn`7sCs*}VrFwhpqJt9GPh<^x` zsVws@O<^EhH%7QWlnCsj@tac>*Md*iF6(cxC9|RRyyh2oPHt1t9}c%Qv*$HtL-GHu zYwi#L_0^&9x$y*FKHT0o@yB8cwy~CU7!{Cq<&^>uvXoLmRS<)pFB0XgMG`c5+0^x+ zUZ#Rwi_lo!k}vMC`>kmrq2#v}(Im;G%_pW_!^O^iQNN(8+x9cq^p6}PM@4*XY@T8S z-YQSa{`Y%KA`_>zv~&wrc9}=&pq)4S%PyZT#t&x?XffTD(-Vau#E}+z6HG(nM62|s zgm$X(bB{d+3@E(pYRUR@>+^GCtSrN5F}|L9M79t|YpYVTKwkrPEC!xH37a6hyWLf5 zx07YN^T^tPa=8XWcUOXAQkeYn>9dNc;X0JDF^&XH2??qqjND*$sNci{Gd{9^EW%OQ zt%vx9mISqw+05VBy|fK?uXe&shsM8`N3!4` z>cZGm*Ae7=>eJn>Nai6MoR@gG8ui(8Q9O<$n63Yk&u1?6+2Pag%?DVJI>o_n+TyuS zW(!%K*a9El^7mpDv&YJED&E$A=Cc`J$;s&MyK&_aPSLHSM!7@Wpw^7ga#lI|&+}&w zfq>ZQg_KE8R`Or%v6faRgN}*h)*Itj!|_=EDHyjS|VkE4S*r> zP(D2R!H6#fe={mQDfci`5i~pfh=|pJAKJmRbIH=Is=a7V!g%Ve)Jqng{}u(?7}G75 zRELT4KhwDf*r}8Xcf2QwyWU!aaNwHKV1S-nCB4<{VtB3^LU=zZ*>qKZy$t2vG ztQ1B4EmB>Sl13M=y`QahMc3>Z5v*v1!}r+PxB($N%GjYO!_vdJkh&Xh;bZVz_-?FH zhoDu17jmk-eO(^D#K*gJ6IrY-Hb(G3m1cqe)SI|rW|fk+=heix5Cg~mSn=>65o(W@ zgJZ`na)b9hj5otgn3`^gkwVr*zlYSQ#3=OVibf3l0scSk?))MKhN${ww%j1Pki~C6 zR%GNJDAw~TarMKeOdW9u0wske3W_pw7}cCY*@MdvyG|0tkTg(S&c@)poz2{SjbHWh zL4OA~eO+lArR}4#W`;g*7zoXt{qumHLVrD4*hE}W=P%A+W7my^a%G@k5VoC#!D*96 ze=U1~E@8ywlM5uKc$dSif%BV${amxG)mMXE-Trc>BxmsijF{>r2jHv0xEzW(2#Xx) zjbw1kA8Qh2h!dR$OH9bo3{E#7qU%3HBtC8@X z;iS?%FXOij4$WRyV&fUBVS7cZZGd9({+jAS-9lCE-bB^AtDV zfMDl{FS@*^1!=9RUefx3HIcER^}|yMzY1aO=A2Z*(AQ?&_l9?V){=(bJy*%g)&d>> zGI-BQkWcn-eo1p@Iq1IdL?4)qKtWY2c!fFT@SNebJT*F49D{)H=CU8{Yv!39hIA2s zN_Tmlljc?|HqNlyhF(8)ro=f;uIb3)SfNLXo9&8!|?dhNdDDV-MqUn$Z1i_g@_$42Qv5Jz&6X^S=x7 zsp+wt_{1Xgw6gQPZR+h?#w=XN8ff~;f`Bjq%<+?y(YchDgS!a9FSmqKTO0;vd%5qz znSIAE&6R3NavTHn?Dqp{I%axWK2}$4YM9=9?FB3b-c%Ju0f~mb%69X;RiYl(T!&80 z$3(U`;vaOUHJ3W8v!HrwHoKJbb-Y!KfSnQS=hg3~Sv6&T$P0#jdGQdsetw$yT;TwJ z@1m$knLA>k5Q$>tQIzPF*S=%sQ|wnZ1kFbGpQ{*rHm>E9U!B^n)70-ps>guSF*D^v z=;M-;ERLC_Q@g`TXodHj`RL;rDx!WQerp>th)eK_;+h1viKP0)Uaj`<^F6A>mcRd% zNeoTzEqU)G`V7lS4QFo)p$Rpdbg6aOW2ZA=(nlCVQO3@t&LR&kMM2k${z0GdNR@TS zV~8h%a!i;KD@zKnd_!!aQDXN^ineIHC1X98jc_`>1kNaf6FCv^zOVh~QO24NA9dg~ z!~ds07gP9#`vwLvI#L5OtYuHwwbvL|e891}gv34TAET$T;(TQ%GVFIW@*|auTl1;A z%j^-)IfUMWGx(q|e?bG$T1&rQwyNg#660m3PiNJYK@2TzQ_A>LqF<%3m^9u1zEL2Z zXa0KAY?_izPDmmMrY9n5i>uePpk&IgIeuGhptBC3kdG?2`}UU|nSV^{RU9?}Ag?P- zxFVSnB;|+&Sn|f4JLQ#+;oIBn%ATkbg1Y6wX1qW>34D zD>a?})IU#6Ra&i#m4d;;cj)>E$mIafrkOz`3Et63^-ZFe{?z6)F^q+|B3oXIeh&8aoMzK!sQG5a@d;d6+o zH#%gIK0mH?`v%oREBY09KX%9Xk`-^UBI~@7b};&k(==$D6=^4YrqB;sx`Xd~}-rQ}XB~M#~W@Y^rb#KQx4@#xNtX5ULWT#+| zbbA_Ilq-DjrMBfLUU!a&{+{d=d6wA5HWC~A`R4tX2RN(?pPrtkKY0f*s30JgBbZ1} zN~u^oS}OgPW8vi(Vo><28rA=G4uPALfsN3Op2Lk<(-K@~-ZPLbM_jSsM6E4gH@?p9 zZ1L8P$~wF)VU^6dr5e z!P_{NpBPHcjozt+KzG@k*E`sr>)}IZKqjLbTh%qTch!3-hSVlOrY3`gh*7hS8 zHY-2>JG`xP8ih#L_hyY_{TI^abj<_R*-&QtpCerOTeE21OS998uUw8tdcKK%k=|u- z8}6A+@Xa*gE!Pa?>DrTRc>CK@i&JEp;H5jiMZiA{f`=u!3?Q@c_QH8YvAM+BAlm+B zv_LfB!-`k(BD}&QbR0=a@#M7{k_{UtF3keZr#~m6U7VWRLK0CzkP*>Ar&1Isb0@zu z5TNmxpY-@ic869$2!3t077>xrEjqq2p;f#X7hK8}Mt-SQpGq5=iB8d#JtRI-7ZXis z&gNXhB!W7X0{W`YuSdIGN$h@?Srl)d!p%O5{<6s|K}?Eos#?OmUEN((Mk9sWP*T7~bof-$=OOdY#m)p=YXCW&bRj~Zsy&}%x9nig-=up+QS*o|I20P>o%rEm`r zeL5O>S1n&7LSI^7ZJh*4v8W-3M%4jw0uaCq=%=Z*3No4;^dw64Qd`u?ixcOn45!Cx zeD|Z&Uj|H-%~hTQF5jihKB<~TQN#Z5KWr*FpMCTCasr#|@@@f1F;z!GEK*o^3*1JD z_!)D!{Tmei?%OS7aY5xRr!wPc<>|v$WVw^tZK*V4$CVXWp|sc6XbZ1+Em~azZD(_c zYHlm*gO^Xc1}%kcIURcO91-cc0aCD;YEzYPJb+)KJ`q*I5nj54~&x`VT={<$kJeI9jXxr zc4_8d>T}xT6hXR#0vel&T?4}*f)4~9M-{eELj&zZHJ8lbrXO6woti7?Kt~Z8icGa@ z6kgV`NDme~S?i0?(I}4SoH)MTH6cEIh}Xiz7f*SQFS99`G?Tfcz2mR>sIyR|958gu znKBn-B^pm_VPCxWi0hz01XfmA6-9;RP-Hf;%)eX|+EpR-%b)pIw(nFF4qxj-{r%aR|BIXphmHwbnd}8Ua5@anF?_D%hDqE4->fE4jV}6)4z*90oh8Ro z>U?N!+(tSa5h(ed>QrG_s&z_l+LeFU(cJCSSAvS)8ZFkjQNU-C=M$t zdHd$gJtu5>V?5f<37%dT5m6)EEdF(Y2rOK}lNHIkob$PhP3l~h4hJ(T$z5`+JaXL@ zBo5f~R!O1%VM}d8EbQFH^H-(PT@+p9%l1mV2c|*Dfu|==jLSsL>Ixe~vmit4J0W)G zw^f=z@dc`5A_>Wis0oF;AJ{7cd9L1=+{;v~TUA9>)%fOi;)fsdm3t|_^mYO!Pv+ZF zEKpc=ek-Cx4Dnh<5yi}C`ckYR+ME<0lv}Bh1CYuM;zZr^kC-DslFYw9vmaQAyzQYq zEnn3Y0`6a@W1`0rjjf=nK?StF|3_%JMIaz|gQLd{M9%0I6pkwfnMvoYfbue{ky~Q> zAKdC*#l1$N>=XAXe13v=j%&{~r!!C8RYCPFj43Mh zj1|mU;+P1o+*SS3#mUSRmZBVJlg>Sf_S8YbVQfe=A#6;h>H3wLHz{>`uL}N+SW!L8 z(`>@sKbX%4;$BSB<*t;GgM4uZ3$3%F&2!=jvXv`i|*r?0-bX$7L7iX zL){|#a(cQX6QpT{eV1OKE$s_G0nt{T^7n8M`K8jrs=y)RA*Q!19 z^TFx0=IYHi(lzWkSdfqb<>Fk1fBvI5{CAmrI_`}MfPj$*vD1}@0ig<7vYGZHO#Vq(#CxfTL`+rH)K4IdGk6R^%Wsb#=?0K}1$!xfO|Nz!4!ZOj zb2GXjcUD}Kia|#CiQlC*%gfCLkNGn`gcohM&@1{ErJ_|M9)8DGMf=|)S&e_gL`#V} z`tWzL3S#U;FVBYWuwwmG@b|*|3^=`^FUExv+Lq#KF3-!ca7z}#i1L^IZ8R6^)QUb< z7cv*v%g}6BT0CZ2qK2$TqA$?qPn5TupCA-*j!y zTGA%DVH&(nGg=+m%a|bdp(_(4zJ&r`l-pY+~ z5Sfeny@yuZ=*2&+tf{^n0C&S_Yv9fPy_MHVfav{byvi>Z^hFX=9bE}W<%g^FZ{znH zID&t_yuI&=iIO4LKtQYxD=jjom72&-2s^pXk&T}zugj0bW12H=_&4RnMv{580&2zl z5s#((7s#5XDpX#tO}G2Rls4wmMv}H8FHz>vbkIC$+*jD(w*3+c@nf>wRb&TIG|3`&DP^0f1Du+3@T=mmWPWF zjOEiay%5=6@z$l zNuJX9)QM`w@7bMCzfap*+UFobWe3Uhn8A#b-pBDM{T*mqi5a)3v~Crq z0uaA?C?@o%nV1mqUUu)(scB`c!BS=F^q)?V{U&m?fX}4W|GK=mO>Fc`yZOpLFS(3E zcF<%0+KXBMn9$|P;Mup#io|pZT@g1$*idyB-Z`pvo>I#XGR6GfIDO-)Va?^wMYWY- zyQ$B?yl=k1_K$C2u-O|?hd*}9sr<3D2&4$(%;>`41Qj|k!vm*9ivJ$B=)Y=CEkQJG z31UQ?w06cI-#YVQ^0@U{U8E<|IP!E+aV=zWnRov3X|k77HYngfc8XNF0txx~!g76M zOm(6=nGhepmwI)LK)@yfcW7{kT`&D_c{$tM_+^0A<^zcW^g?eC#N2gb)wPC_{p{}i z+lf^AUoP+$6YmL9n%%zL=Ht|4)%*5D!LU%w6l_HE@~=#dahUWapfmz;qTxg1q+`?A zxKN;$J~m=8;Kb}hEP)nlhyNd72jM@1N-s?Y$0=P!Vd7|C=dStwJf1AS)x6OiKCs{2 zRNLGg^E+;G0-qk$772*oaSm8`D`z;AS>|4aHC>~sWkG@-Gyqv!gXzLH*FJ0Gv_n%c z5SK81ai&^?5Ml6`r4mb!5Ys__CPvPH^2$0)xZ^*HakHrqd};tgm6~>pnKWsK3^|*3 zG3Hf|pfBiw_e$vdFSnf%`x{sIZTE{EY?ng!>4L-=U^X?iu!sogO}hQ07> zJ-?K+{uuuodSJU}fHsP~^EW&93LHg_ z@zhh9wrR0FqAS?vtCk~)8`)HCjmsFltgT)47>k8;+WO1y)^>VhX{hHxWFIXCOOd{( zjqVktt)z#=HZ@1(%VILdDp1J(z$Xxm9@GA%{Y53AY~qle=^|7lt(mxLt7$=`dQ+QD z&iN8vuU^oD?ehN7=OT5m1ereV()Z?ZhRUtL~u$-JY_ z^EZLP{;XvsJ359bt>P09>Oj#WLd*@HRb)^6QR2R8XtwZ!DVPHRl$Y@+VS0+OvXBA8 zA*;9ED{|#a_UHt^MbVqy2G+HGH*0K4Z=jd^6p)H!Fh1@%d#(JQgWKM^s6e?h9FcnAx$h?7 zzGS7hY(v0@QS{p_?5E@%45svSH2o=B|F;vpEQl4KKcPJ%GA@Vxa7*#Jh(|X1!`8mM zGM%Xoe%vuJ-m7GQJ@i<8^`0rOQ81mvz{i@XAv&`$+99JiG4ZMI?<)U;f;C2Tfzp9Y zTu|~3+fcaSA=yJ*6RV201VgOJ?Gw%3(@Mw4jL-ESVI7vBb@hkmhF1wM%kXRZsg6Ii06(zo7 z`ALWI4729n7^OKoj368WNW+*ScC+&VK~cHlk=4S?aI(jSl4wmBz!=ERa~cNl2mfcD z3nyTCR=;?m*;CP9h==3sD$JgNkbr|V$T4+k7cS~lY~skGZ34lt=fX31N|`R4{WG4K zT*in1qH12qmV%~Z>9Ch^YtwGgC7{$#-T4;ehJ=5W*k*sbeI1V_uVDJ8*P4n~LO+KC zn=LlmZCz@cBLW*M519Z5CrP9~CP_i%WDkB(LK?cx;B*-Q$z!7|1xJ0js)XqeOOVl*`%6Jh&rsMvSgMxBoWL+d!InsXgZi z__odPl&PsWjzah$;2P9o-qzm0jIxFQ>CTi9l>Zh|Dsp`Dsny0Rv?Y}&VmrEGE z##WalBt4qHd~RLdZ)Y-Fi_Q2DPdBfZeH}J4kz@Z`C4`oMGZehf0cNzCv&N_?U`5Bp zoR!^I(E-ed5o{TM&=qH}e^YXkS!q7fEpOZKE88F*mpVGJ4nTp6ufs=(ZK4xZoLGgb z*<=+b??G-nQ}2e|2B}bB1xYFniUKRCvqLc=`hP{Elz^o8PLvcA#F~+Eiy83S8WvQI zdaS?9^_{@|M7>vk7^yOSRY4SBms5JeEYU`(X;D2~awoAwOB0(w$YMbRrw2B?R;=(|{k`f8IjB z3STCS7St6l4_yB2$AV@e4?)Qdr?+-*By%7sS<_t<1pl&57^rO&sn7~k=IQvzvQiJ9 zz_7Ko&;H49QM-IgWJw~BKqMt)YW`CTU9kdip_BD;QJ5uqcY(g`S5;dRi*Slzd%8x6 zm`?K3szYrMTnBbA95e47exon(#9`RisTab-l_Tr)SN~_YhG<>5N zfTfi|54MWckJ$gf-v4TJK9_+Kqr@x)Ut{(J6M4Qy3vrKH#hBsUXY{rg^c*7)5Rktd z0zD1qi*`fUYm%+$y8xG|$6(Yk3)!mOJD>7GDCKt+U>_Tv8?&|YR1BLoL)yys%^l@K z+<}5|c4T~k(ba!_t7e2cPA;3bhPTSk-oZ}~lIOSZiQ0NzOi&rLER=~FgpqQTNd%&7mA^_XTtw@>X}LE-=64m zJGfpNa*nT0yH_&AVX)&9e7mnBxjGgrBZF$0O>_3k+VaqlKrOGm^he&P13R@4_9) z&}Kn^>uPy9Q75YncxW$lzo6Ou;qB^4cyLofG?(^6axU!XVB;pac>i$?_GL}?&1p3N zlPV8%kc9Ceo*F@U7}shZ+@>dggD@l02f&P6M8pQaF8(k??tPvo=zpyzQHcA~-B|hG z;#_?@u^titoiGnbz{YRG?xr*2g)m*t92k0VCA^;Z1svY2_VU?1BM?}HzJvx0&^Nik zxssfLDvh;3YX$v$&cA3^`1XhjFs%y!&A@;mY$jHU*qgrpo0>VwNL9gu~Q9BSx}A z(I&582uMz>$sUOR#C)CO)Q7c;W3bJskKHSEY|cBNfQS@>B0XHy&xjHuVEI)6hZCKO zM@6`D-9t{%5&7ut)26!1*|UkvX^kAwm{iewbbmT@V30)KP9I>g3DiQp#ZL4imeoKppDY{0&Bdhwp70<^bT8JpE? z+TvKJ$~1ql%9EXtjN~ZTJ*OgI^E7F)^XH5Zs7#2xief{zG-v($FJWY8FKcaYuaC7t zjY9d`&F&uoiu_do_`4Vp8fF8ZU%{ho)`Yv zUAIV>K4lKvU!sC@e6%&aMaD;te(TQ6j#ou1GdiVeWs~s5MKJRapQ&$wtN_FIboHW8Mk>fOv^l)pa_^ zuWovbiY!kgDF9f-RHW#I_croOCuIM42@YG%8&(Ar=J?s=fffoLsO$R49euxL2K_PW z3HW*T+;l`f+jnJe0xbcjO0hz{Q=uYSTiFeVHlY?=U%g~T{JES2yI76qa8%v~VeAlV z0U8uiG4Y2^Xus;7ZyVc$i#AoN)PRyYbZ43&xYmJ`Q7?x850=C+fwM>4fBnw96pzj! zu2ZEiZqCq3)}x3Q!o+@S0Y34wga>XC7?{}K6`YS>!{{$t_IU!cH1ly6>KC0?6}};* zo?_<=V;PQ!`8#QBEB%2zPgObXIN_@xC~MWdmL|&~*HNa{g{#SFh|TQc_fU;Aq#V^i zSa$8CioS{uzKap?c#J{TYx5ggK^sR=Ob=6VX%%T4U~YFd)j&FzU3$6yQ&r2(G@5w7 z;7#85x6ba#mbdrcoIdpSV?J`LItSd8*}gkH<2HH!o{yK9)h37*Srwb7D1S*1fq*_f zA=x$RgbE_9qtYL!K&2!iHpR0ShfslHha>ZYlA06Yzg_-r2tijQJg7}`La??;JUZcG zKUXS7k&HE)-40j0BVO=5@M&fk3wJ!PSL1xv2!;O07!;{b3*)0BPdX@x1dtO2U!u09 zYgL2ZI=#gy3mH+^l4~fdkw#VjjTW(3$4lvYO?I_%)n{$QBf^1R;v!9jr;-AKio|_c z%g&7C?m*C(zXf2Zg6QMu0<-+GINMVyY9bW{F=P(LQ7z3r$>BpBszN6jOWkUYCV54_ z^G}eK$a!&+8UTdtSJ-8QsR%9TXk0@Xa@a-tcqdkAG$n@1T6kL4p6E(gavtbJ&!7zz z3PxV?UX^K!>C-Fe!U2FirGqyKjxnMW80;d?KQ5_gEoFz^uR38T zX*-Hc_awBIb0}1d!7?=tBV`E!MteEKb_bZ~R!1r?wdXJdPv!WfYi4)sYV3liYsPHv z;1BEBcKxrr^L}cg|Mqz30qH#yp8%n^&^v@GRq0ZcCLO5)3Zf8t2~9d8QbMFY(gbPJ z5is;7ML>ENsR}~w;`iQ}`ybqy`}rlA-OcRIf=a+if>;C8G}(cL1*fkl??-URw0U~gM7 zIoGW@TwHT10WavbUGQzh;7_W4GLZVoe+0RBgxsL1l zQ+14LdWV1el@7yb0qzj?rW#v(6KO+j{-IgK_U7SiSG^;$acz$tXReA|*aD4^RTSbGia&r0%=K^2aQwvoYPmt8H!A@X)0$-a$9G>J{{T@GB z3s7#vy=!^8DOC}STqSr# zFYtpvQJ|iT!tG}@Zl$LSbgB~ z6XU|~k8=}~tq!R5ynS(waA+$H-4?vpE(Bng? z=T*rPvRdXZaF^cid06LJVMW98o&F%ODS_^7fk(A#KTP~^vIleFBF;^$lT2T;$K&iG zr!kZt7*oHeF~KdLSQWcNx9b{GVm+tP&0Db^2|yy6ArwONoGVZ6&pj=LhZv2(hUiah z2{8bC7=XKhXy`YA$?C!F>q0kydrnK zI=;`(aQ*oh`ZOtobB{AdT&IVQgi+gIx&OC+d)hv;*xln2kypPJFYRokV<9 z{aOFxuc%2CfGvtQK0)ozs|ZSAdbX#S7@f6W$pUh)FCM06 znI9H*7|K32BA)9lH4_eg5a907kEJsI*>8Iyuhu7uag1M3}8qz*lH80pGa|X>vWTnDyT3=tn{3s zwx&N#C2JKd6TP3>GXjXHaZ{P>FIlSmqc>`d-vGn8li`BQ0$$!Al(Qkp- z^9}ZfhOgrwyyj?{vf^;j7=G5l1bs9=h?KC3OyC6W_QakhbxPG~TBmY`%Q2RW*decY zwmw_JlFhX7wQgzg@xT0Eln7tnQ<9D4Lk2-eOzUQZ&}aJ3^Xpl3wX8Ar_Y_Z~CG}KpKK9nUJY_m$6%)Mple^Gur!T zJLqG9kfo6lS+MWMaIB!WO+=IYteM;LUWn0z9VmeMa?WI-R_cptc%?n}TZ64pf_;Ip z*H`Sr^LdL$K^=b2cg%5TW{bE@T!rNao5R7k#-&_p;jh3!JkS~vAAeuY4u&^K?OfwG z>cbb?AVhU!E&UyxJsnPKb&3*pZt4#ViW!4V)(=spRiXN;3RPR!MM(NdAJo$HBmX;k@@huQx1r!Vh3Dj%oZmqn=);*o#lxGxxntZ%TI zRxMT!^rdLIcjE4)kJE@L22DBUoy!dqNHhUtWlN4eJ}&lgQnZYe)HB~PM_6#fFTU?% z#eCe75y9qfvYNZpR`wXiD}2GrcASl|tOXeoIqg z)#DUR=yAat=JBn{(nW+JwV4szEmv@W+D&W_Tn{jl6NEyRgJ{+~)f>8}oSaB`)hjZK zgHjG5AG1?47|UwuI=3Ccd5uq=%DSIe-#_zn81`@Wk?~ZB4%{ErRi|kPYCX05^ZcN? zvC^yJ7t*YGZ*<2oO(|n(v84%^oztPclRiYEAqXwRk91UBMjS=*&e?EZ-t)kwZg}}^ zq5sI-YWXKMS2ckcQ*E3;5Box9BCh5pI4fCS+0~w#VV!@fTI=OX36~*Ufc;e+-UXEO z&VfkVSAaR)S1Fpi!_{qganv(PtJ*gT2}U!89!5iaOzptW4vv_=u3* zcT|TzsKId2&L(FhpCh$Ii*i#)iNx%kka0`VvGU(P#J9QXce(~K;T4=alrxzjA74(+ zk9~J1PLLLqR;`b1%4p>I*|>Z4W@hc~rEUA4GgWD;m)0w%w4qI2mpJc-tCuo?*JlrF zcO4Tk-xHyF1%*tWkGlvp!Gf;YLWhldaYLpsVnSn|4UXUwW|h^%rV?E53^%R7aF)UTN>r=0z{ zk==!yC_Owl^`V4j*|S4_(c6QU)&ze_4*u6nHZtT?ay{<wJHNk z9=jHA?{gm8NZiHZvXbexa{H~95dX}-Jz5g2^+>$D#?^)LVE&nBfu%vCqPbYNV5GFI zB4uz}jCNR}Wab%R`69j==u@InbRL6(9QLQgBdkDGS**hxr*;Xq->t`54kHE3<|h8+ z#NxMy6Z0&P71QE|$Ry{8mfTdcAV>Km%FiyZzq-QK)gY^q9D{$Y2SjbebyF6yKY)r| z0Yk-dCW)r>@WxUt9=1dB0&R8{G$=s{Iaz5Ex_!j}5Pow5JssWX?}c-Bp!)vF^p|&X zHm$JNoaU7O*J-rtTSEc`X}3nn94}N>E6gr?kd(40=jFC2=}1#>c^CPtdrx^IgZ;Y! zFr;6nV*^=QA}JY?55eEtLGuQf$o(TKUAHi(v3-F~>wLVFM%nL++wt15_S=@rqPga< zPtJkrdXnPBlGnbQ%kC3P(+dtguf=dM299fonG$0tJFC!9x<`WmA~!M|!;pUTF_6$l zBb9kWgmu%>Z%#4JdS9K;+~VY3=6J6^pLcx^%E63qNbAOW08J3^<_(FQjIUIz4QPUp zcz9yQ7b*FOBbXL+pwhjVBk=2}3qzWlnw4KHp{7X_I25!H0|&b^@i4hXH|QIVYws$6 zHEn8id>rB%QJ;3YwS%Ot4(6L84d40M{O5TQlB^)%wRbiuq7AD9vq?FBkeeVz zZWcre8!TniE_j4eh>x9x58*cU^n0|t50Ejn(qJ*c9Cj2q89CX8yttis8tUb^-=jRI z!=j%O4Q^GG>emmllXLaAMRDj`0Zr|7x za_;##RO&I|QR)*iZSFp@AB-%w7E&SytkV4$?f+WOWf;x&Q=oIrJDeR>-3G)x)&1H~ zAw{+2Y*&59e)oX;jGW3?$@*eTyj%L&(Bnd%XJ5(h%%12ge7Ig*XpZvWPQ)ZT7|8Te z*&!p__YeUZMl?it&@aN)K3!25!qjt5TUX&KJ7iG_53k)9>2_z_#hjvF+t0)YdC2>i zBrU5*h?T%t1d9ax{^_oM=2zNRKVF4pkm$XV#fCn5euZ0KS+iX8l7Q&5(6T*o*-oh$ zyjwt*tTv@b_R)*sbgD&7pd07+y?~Y z3M1C7xG(;HBHOTOafYCO)q}M2X&M2gDD{Mx$2Zoq1)}b00f5>A_++nZfW$s@c5G?Z zUSvV$xdw?djC>1e&F{{o*VJrT#`>p?i`N{zHX)tMbStl23LTOjSN5`9H~)?xqe}&5 zeR07hfrI3N?SuT}hl1G;F7FNw~}Inrml|p)__OL(5x%3>Uz=zmXzVYi&bGPZQHg@AzCU-&cZH8@AXL z8Fb0ju+{?dFiDy0upEGz0W^7GREj>o8FY~QSBi#~Dm9_&;aiVu-ECb+cyC+T{||sdU#Xeq#^^Ki7RrcX!lwMn-6oNsf9a4tDNX%Jm);l|LnK$iIZ;sUnmS*8|(P&=LL zmT(PTBDonu2#~8Q5?KpQQ)%B|#-=83B8^-$ntUAj;EAc0i{kMfZ-@aG0+4y(t z+swl%>)d3i?T=&(vIm<2A+;~O7J}D}@6T!KmH87WFkiy%&uf%ZN?ey& z{GX~~6B#@^MyKK26~5ng6l^9*z1Uu`v5t{F^FF7+>{YO|UeBcsRv>EQgIYPy0&Hw0 z1QU#`T38x2ZEV(8Rq!6BPt|4GmQUBLmCqcV64o`pi{YFY?|;({*wD?oWIE7zKe8EF zS4~mb{`UwDx2uJ2sL4(5^XaR~Shka8qa-3gB0{J^AdrOm38kX%p>z@-#XYt|sb(z2 zR_gJcHxme=AGkv`cc<@Xj%2t?fQ1dBvD=S1jRp~xYk0Lwgn@wU)Ab|QBga9wGcy}K zjS6t5AyF%e+erP>a|%bBq4#lrZ$4CTF%({8;3r9;z(GFiLdG8oT!_OR3nr(rQ5*|` zB-nM;3Dmo42tP;2SS_~SoWtruu{`ADBy{>*w@}QKSUE9rVP>KjG~dn1ze{*KeAzxO zDkxTiKdyr#8u~rbfdg3pK{|9s6jn=e{Lf{;E1a1b9;U!XiXT1@1`0AH<|fj|!+#Bl zaPUQPP$Q)63Z(4})j)Xd|LY^b+s{ZCnw%V^%dM}$rG+vf?=B|o>F8MKq_OBWa_ulg xb&AvIs~TuZh{(x_NSOWKFWhBV&k~3SQkU3da}9i{k`ZAb!vFin`v3U^{{;y<{n7vc diff --git a/test/assets/whitenoise.wav b/test/assets/whitenoise.wav deleted file mode 100644 index b95ce95776fafd3e3cbaf670153f8d73167dfab3..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 441078 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

CSAV+5*9;R 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

70z<r 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∾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%0DPcrvB_V?H(?12bv9mZM3bjb-c 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

Cz3T@ze3!6w*(fHW_fV9=% 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 z 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

yHBe|3x;dhNk!n@ft$& zlITkhmxKse>dCv4omp6^C9G#^qpSV4#ai_ds!{;{HKuMTD^`Slb1YvEKb?yELo zBf%NN+?9fPR}(cqOMvXLijNW&IZ4p}+KGP39;9xp3iqk*$^Z8swMEdt0ryt9!pFIb zg*rf8o=b&da|b<3tWJ*aQp8|ESM)TY1sLgX`*A#w_ugg1Ok?3ZCvNtO0ha_qD_Ok6 zY^cRsZw;~95$04GUlga#E;lC0v;_S|q+c&dmS4mYkzE(^a2iz~7eD9c8t0;y=O#1y zqR0`X?U5d^paCRt(kj!^w9YLxQ4}DJw5v?`*<6)q8DV)&`u*fX)adV@cPYL8e_Vd3 zGJiX?VCQtU6Zi@fc&wWTj|5De#FtpxPF z4@ly6VnCxM#y~L=REO17>N{~Iw$$EVP#XGKt3VW3J0<247?gCMg;9Mj*7)b#V(nN; zi1qivbD$Jl7_TX@1{aS%u9c^KEP?{G|AD+XNGQXw z{W1U+DN~s#b8iO=E5RP<23Ra1@>?^IA53#o7B3FZ7IRH-n_``BZ(ptc`3OqH3P6vh zBbCNZX=YeRXAY&RcCUg=$owO*xJxng(Xkfa{vJSTSp$D@czFqc=&fwPr7L;slc=q%PT%)4G&uLjTTma65lrHjh{h zI1m#Of$~ZyhSX#TQGT#KhG=iib#W&SPDu-q$E6Af1M&#!B@^qVOG^S&wox{UCmsnxLyzZ`tQS4lo;pac<=qAGns1>2D@@ta zYg>a>$mww?{|Jq?U6*v=TpeZx_zdR1dbCz>4z`x#mxn2ZILf^$Sc(zY2>qnzYru19#NcIAc zIEaCW?Fnc9RCxC%Gp^{DViCsTPk}==t8`XRoS*`5c^y)Mu)XY-)6#|XNP&p(aM@469)FV*)aD`h^nMi4c5yj?jtv66h=$ir~u-S<*bZl(T8WPrUDZ2*|TH@cx++oZ2_e36)WTAdhM(whmIJj>d67j`<@C#~55oRy3klOlB5R2Y?%BHhr! z)lkqE8?k@a-j-r5T?F8qbW4)?O6YE`j2!3ehmR`KYT?gmQrbdS3+pJou1Zs19$5B_ zCY_Kiab^t`w)5b~Eq#vAs{@KYxSA0@9|i3J$4~HnE7-V~&zlX(-H5Gch&&$=W22JV z7v=2aD$(C}+TGT9EAJaNR`F&f=dG}Y5dVbev}@^lTQ=!MS2&@(oy9K_ib0&uzaNfE zz1o#cpc&-=BTQE&pZDn%#LAV_y9%t{@VAP^1b*n~7$6pjHnohM+F66`md5R90{pt< z`XK$$LJ_tRyX8Aendx}lr|dcMBb;21+)H!EexyfY?9pWb!MJ$Av`LnDn9s0+^0cdU zL#+(k0xLH=$ud$&M3Ba0u`rK2b>FVfpLcF3ReneUN2A6sHkJGturOd^>KA{WZ^Ks~ zDu(UUnAC`6wb4+@6U6{b*~0Pc76XK)5gXQ=L|XmT32U*<&-d9iic!t8;02ZZrt zhSGv|^;<#uPLuNZ z#2iM03w--2Tcyq6MM_pGSC#hn`t&Bc(8-{H$_rd0d7TE>Kc}B5?)1&?6%32eJ1`Au zbrsgu-jc}%p@{&$=iAFFk+ALFT5y45_JM&5B0h{9(g`Q*@+mZDsXNO5jJB%ZD|c<= z^kGB;$~eJz#lOM5hDWY?gyu~|>D`Dq0sQK65U^|w;)b3lhlHd^rEpM87T*EJGc|1s z3qX#cA@mPJ2karQ|HH=ik%n+aPXd;RXSq*DXmcN07 zGpPJ`i}aerss%`3lRHB5-Jp|bkF+; z(5p3t<|-*(BaH_BLpR3U{}bGiWg#zZs;s4K$&MmP`St3TU5 za`Fbq96~WgQHg^zsWv<$zBy3_n5&}qccbJJkMyN*#nRG~-CT4*?}eja^}q60(YAdg z&S$^e+1|)p=zLgzF7o-cWf}P2Rdl?>OgJB-prGRqu)#29`+bWT;d;5L7us~f)?&VS zlo2d~%OWv%p9OKV%B01%j=1*e<~}s@s>%cSVHT`tp>qmT2UxRdVpyeAl9>OZ@XpM* zCkaNWb$W?iuxr{5aM{Uw7T`c;$?Z0(Qq8G#^XxA|c}$#8z9or~!Wy^g>a=Y3--q$N zCRRLv)i~$Vu|o>(0B!zHl{QzkJF?P#*U$$L%EiRUV)tbIgmmDEi$JfIl3Dzeu~=vI z5|ak?$7@C`1J_tY!P>*)Seb8CG_gvv3^=r6qgK9_a>1qqmo>?)GzHdgCOpEL{!a`6 zc32DunORv1l>x$*M%u1d8X~ordpqaNe2i1BHQ6DD>&{y?hZk&eb zhpU*_jRXE?nceM@)$uHW;d!N@MA4e_#dE#_ZU++jPw7jXhU&#zJ9>z(!)e~o1M4_h z1~eujatw$y10s@`fmAeTUelWbrKbg;U;zMH8y&rMIl}b4(HH6a(d=u3kpQopqzc zRFzNJa|HnLy?%m)3dE3*G;**%wqx}oeTO}W!G;`%<)f}5VyZLL=q*oA!A(XNJ4eaU z)UQ0LP%PE6hUbUecc*+|ZC;%;`b{~^fG)#`9AWvSq3i}AK zGraQM@e-PgM|a~)YnucSwnD)=N@(@jcLd%K}2tRvnL;Kj^fCkFcSV}5&S1&ZLad&rh$+~B@U@f(0$Lx z?)1ksq_oDVD$GwA1_WcvLzuj$`??KV(B0k&kG@)^fs&1J1 zU-l3Ia|4fy#$i0!e~<;^!5c`s2xkDZZjvK)ISC5!NR4nPv2x{*v5FZK6Np- z`ZzKY_67p=gNBfTc;Sm>*jV_9D91eFd+LL*NP(28-)U4doHByLSQZZa<+IRb7t4dX z_$*SBjM=Y5Y|)wpNqMtVQ_9mC3SOYo&dpqUn)@aBgPFUJ6a0?{ zgc74sjnp_0JPrUJ1%qpC1@-sO507idWvSB&Qy8sDOrR+-p=mvFV~$pO6koFZ&e%%v zlQ03VdioMH#Wr2EqOSzd8Pz3N{nu>X%p;bqK@%(Vb|=23Bl5d=jmNxQalz5?r@$dq z()lD$un+?nj;xhp1V8qgVD8#FGzZdUN;ZS8ifa>gokPeOpBt=|HkWl~75JLfbpI>< z;mYE6SNqWGy^gs5{kS#~`o=T5(T{;O41_~D7!b)%C5S7U`X_#pxq{Pd$Ib7Vz7%Jh z7I>}oS`Y7Hr)4tbXlCw(SR=2A(Q@D6#$>($3-p^cXhU&!`9vTg_srflg!{F$rmy32 zUB}HEU|Qy$&iB{P#6P|KAj7E~u%F7!H+9^$jsA@yx>RRIy7NKoE&tk2MrdkdliwDN zhf@Jt^)#gIx5p_RjdO+@nv~b^&sgbd`7uJ{pfMUeZbEFZRSx~ec(!JCf|~>BRR8Cm z5A*MrY2+!s^5qn?%1}Y4I=&I>B)eALR+J z6hy6zQy(lYwp`DyQc0cP#y=|L=?xL|a=_V!rWnxDwi6P>X+L_y*_ey?n!!zHc`M0n z8lkUWdxRF7_I8Gy6;>T)D-0S3dP-koI_M|?6>DncfH};b{8;Au{=G*^T+Ft8uDo?R z5igdCw7VWw@5*hvh8Usq^WOlne$iqC40*U1b*1lkogPe^cHiK&B}pQk?T$C6JxQ7! z?`>fN!n2s+F-*jRFi!t~IrIU7Z8k%h3s+X;5*@TUMrsX1CC(RxO5gK`pYEQ&0Kx~F zr#>x!B&!bja+!g$WkS(fhJG@L4E@ZmS_<2!G);hqb6AkuLxbI9T25fD_63*MFE=nfATC_Q8Ag4f z8wtuV6diNFDH>OY*6NTeb%P-SMf(IXgpMceCIaB8`Ch13EZY(ah*XkmAyN>vm;)wK zNEYrUOie51z-mz2CE^z6@xB{;K_EI_BM^`4yDqO(+MgCfzn%o7 zE@}g%N|oJ0aI)dGL6n~;N4_xlJOk=>#n1Y)=Iz(f1+avna1)7T{&)BIfiw|Fbi<>U zi{S}b-4xo$6Jj8hi9Z&G^$uTaq&*u`CKsNULes=Hc3_j?{sVerayXMEk`hCkmH~gRsSuQHX5g&`Q z*+LWO;dy?*f3s7L^aFfpsEXcEhgU~@jJv=Hfun-y#W0oTq z6`H2Ra(1oMKQ3MR)^-VtXG-kkw=@F%BIP-_jDls8R&(;Nv2?Q1wXK3%Qdf>QSA%rSS5GDuc=i!A`i4MK>uHTJQD4#FKFVS&pm3a!>Uq2#2q)i2~(&j9x zeL&KHHA%|;Hcs1Xvpg=8z^n2 zk&cfC-TY@UR{v&CgriR?8E^L1@%7Tf`f*3I6Vi1Na}<~kNS6Zx{j9~kWxybn9)GLR zPBr4_s;)oCRR*aGrgH*hiPWCuY>HQ-kV<#P0%P8zuUiOoJ5iGF$FV(mQj+Nd42$jSl@2x z_9?Jff@La$T2NRB%B1|QsFLZiz}Tqu}?7M06yNa2MQWpXWh|@ z>|3WU!(=>MGp}73=2obDHZ`Ll>=~_%vSHv+<{#+R5X8XKu|uu~Jn=>xM7jEy)IeeU0X)ldLk{e`gX+)`^Uc|&R=w$U(v!6`jXlSm!@#)nAsspfAGbo$tb9oyjb$`K{uCm-Oi{}CNQfecBBu%{Ps|G^ z%KH{ANk(-WSgtB0_&2#0h)s;2kVRck!1Nl!n<+)GmrMF7d-edJa{MPy(NdND>B+AX zKDT|%xa{P_m_kG|goaD3KFbp(S%cnA*^xkvrq++iUB)o~O?69sJ?YlNw?xUSo@jl~ zPFh1~eSLguaAd-5yG~;BS2&i8qp&%UX8D5c*72^R0x5!KQ;5TIM5WhKg)}j(=^)*+ z%Z*3}bmK1rxq~ZkTpo-DY2>6O7ZVH*oG$bTrqND1n*1H^e*Ny8wY_N3mycGoASAz>y%bDbw33AB{Vv;w{lZvTMi6!ur7XKSeEtJRwZfbyvUKE_4Dl_a6fh8@oew?n6hj~^AxyaKfGsipfAZP)`L_qX(&cNIPrjb{m zXP!{IJYEvehX8p2;dgyMO-GdjZHF=r)z8wmJ4J;IbmU&(Q^4OuR=nRq6QJ3Wc0fU) z*VHYHA%OV*A_gfg0a{ zZ48OU*c0ryQ0_$m8}G2PMYYu>+jU+w%+9es_`0{ac6yn0YAIHCe5lzOWqAyg#DV5F z_f#>{d3hZe+A0k*R}gx5_E5Om_>7y*G^gyndpdSV2VuakK;%ptMo#K38I;~LfAD>U zHt1adpFu{~b?Q;c?v5$N8&NyO*prr}$JL3lu;>aXNNYtvZ4hu-6qc7?d?cw5D5_#c zZ~m8eV`*N79zQ<5@ZFZX63h(Hu_?S1MAV~Sugq4-`D(hIPhakZP-df#ys*p}F(;$7 zrCGSfb@8skn~S?#e3S)Rc8w^jESVk)UbT`eS@@{r?Hd`eTF`)4v6(@ACEu7 z=|x&#AV5`apZ?ol~(2)ifKf{l0GlSDA@6d zhodb&QnardiwT?js{n1whiNo`V4ZBTkpQXwf7yfFYla_u%bK=#IOsrZIpLJVs@y? z;g!!|?_Vw*9+{O_(dGw?Ah(>*@)z`BI;LW&b$Y8CYn#?&EH&mo2d%54=%~;+QTbF8-2j6`^FJX z`3a3>{ADkATmDuGLy1?q9!W{@j8U*@Iy?t;xrg{JD9;KOP^r*N>YvRt09Y$ zvT?VR@9QBZObi4va^4_$xtED0d!9$C#>GLm!e3%sZZ3= zA9`?uetyc0_6G5o;;w@|UYcU81vB=iveBNjbKP%K&ptHjY25!oUOW%T@BQjH($g#b zqm{KE$%A-k*c~|R{Sc&}oSG8rFYn~2zoH*2^*3$-TD1t37&cL2sgcGLVkHK+&_uCx z;ir7H*t9>LN9BrE>J2Q|q#aeM3pJyw?=p*AMNCrns2tWs32?<_+G8+6a8Mzkd_9&$ zP%_r3fGG2%v(s8;7nQNb53*=Z22bFvn4|Y_T zqTfpqPA>L-y7s8Vlek_2D&|34EA+0^j?Gc+TT5}>1cK5Su2dDIbpYi=2!^>h^T-{4 zJa5u!fprB&Nq`2yws$mV&XnO(_M8AfaXZL%V|eR1!;`0?^YF4&{tHtFISkYM2oHvL zXYpe3L=WcRX(=O|1`H>+3pa6Od&g4(mff^Vw7G$0FXTkCi=NT(BZqAvTHJ<}Hy$?y zUhyuf;vL~2)yv3&qrfCLkqW$vnx=ixhrr=Ru7QE%afL^_-!hwIIpN^w<(~Bzr9g6 z0D2^^P!!tB+3M}fM$Oa}dSkP6dC06eaT#;t<2=(#?g2+2ejg(j97Yody|pp_LB7Ky zpQlM~9~@N%=7?8hw$Ml%Jso1RE7A^EDhx?f75h%*d7))}>d1fp+j)F8E1EspdrZ-z zD2h2_^qlTcjXJyoAAVrcOh-_li!5Z6H7r?_t2&OWa;t`OmOIE-qe@+eSi7_}5m*i-_B zY9;gnRn`Bk>c8TOr|dZdfPOMP)jgKV9d44yJwessQ4BH#z?2gA6!gRZ`@--N2X6L& zz65h&!~9=x>pDfp`dqPas8Udat!~b59cbv%66kj=g88!sS}3|d+pe6|0lAD|&w+`` zQLTDkj7OSe%ws!Z^|(FF49PB5MSm%v97YZw3JU<${s@S!j=)YYlz7FPQI(bwg$Ax| z-=~hPVhwshntbqTqb+aGw1* zNHghr^?TYmOxf1HBkz@#GMhOzYn>msE_t}IlGWu6VcNI;<=eZK^AB74Mp|GLVjK|V zhK|m*QTVK}E|I|2nLvr#q>1g{J)eCdz;XDjkyr!E#vx8KJuY`I#@WhIt7%$J%^Qz; z`-)}Sui@m!aUM^BI|YE0d7c!{a6Sfi-=O?I9Uobyouj|Va>*{LLgmQ_Q(WS06?abj}njK1&qVM}h=!e9&sc0O>)5=O&y6;yXPLKmMr()Is1w0XaB4u)X z2Cfcy93u{9TAi2KJVtMsqGWhaB-n8y4hKYDCda*BjC(sDw_ehYwK|}cq`;%fU~YAx zM6Z@TI4&Gd8G-f=hONOU4$jFBkaZmtB>S3vbMmW8PTtG&(?rMa7{8zf(OhRW2kYZ{ zm8A4;Z}#ICWVeraz5X!Qz|%NZpzOLtPt+TTM#^YTR7yg^otR|I9@_!48DAA@Q+Q6L z31G#tCnGIHjcUS(pGA*P_Wf8nGS@CMxkJ{U&9>(O%fN6a+h)NJ@9c}()RZ-_Hvjki zK!=5P@nnRB;lDo359C1q#2&GvDt)T7FL+eLI6eXE%C*nr8>f#nn7Gf>?|D5d4?q&? zHnBE52kVc&hf^bqoZ}Q24f5kP>bLXWL4KPh1;~9Ubas?Ih!wF7`lCuo!aS-+!dxL| z{o+H0MuGr0xMcN*7hj{M1Rc61tB*xS57``k#0xc5N>1*>B#`u~es1332{)b;KTb9V zNDTvzm%;6uF!Os-Oygk5UwExAK3p`S2IGV%sG4#;{ytqj8unRI8fI;f6&-*5U=Nbk5Fu^21cC7*(tJXl<{=bDL$-}`Gd-ue%1 zPh#LTV@B!!KlxElCMR#%iL3aKT|OsOH0dn-v!hbqbTLYPmKmPas9TU0l!Kye88%ZA zRGiyCQinI5bL1T7Q$$=pu7(ztzk8c}o7oLVrDq?C_nacE*`8Nv ztL7AI&Few^8Zyw9NCflFtk+h#&I!LH};&?2; z2MF^7)g#Sw6Bu*Sjj*ng=7yt$`CSCVY06RwO^3u|XLG7x9)%tsN`I~-mq$}2uh_3% z?;;n%Aw@4pBk;Ya>|wy-dI}t!>Q~Mp76-$cbghIh#x06l^^9X!W6?4en%^MLocxWA zRTGH=K9AtSgcd#kCVkO`F#JZ3;k&mtH-V4J__JzzHB}^MQ&Lrzq`EaUcdfg zGt=Qz6c2ipqay_$t!lB}T|F zgllaad+HiGXyNo)3dT!)Pt>V#`Hui`no8( zD3vWrc~_s87j*L#NX!iMD>Hj#urfwSXLZfXzI7 zDil3p>K_VG?WMvme(Q75(K)@v2mgLyZ{ow)`~WKczLHr;_>Y9zZ_q?8UVIe76nR6# z!W=3uWv!I_JhwB$Kc5N(xt)H?eY|SmrcW56f##tokW=z~2?<(?$1iWP-q#}qNJSX` z9X6Yvph#{fVN}88T>65GFFQn)9JCb@^XjhH$h~>mJAXv5eibG7qs6wugO%x2vb|P| zy7p7x&H+S%d%?$P?h!bYNXZmc-1N{bAC=?6tnlwYSQQcaNT9dmVA+ng>p}PEN zk7eRdBG4?a?|B6-ycnKx>^SvPJG9WUo`EA0ji%smc)r4gb{}U!9c!mWQvQw+If&hgfNn1#*8C}kk#FK67yqBMZ8SYpxtlb~0HHSOxp-6$NpX#tS(UI{_GHpNUO+*$GiWf3e?N_kg5T2jH*vJg4cd1h%(r6_L{@QGI z6;UL=-{N9GppSmHto+BsO@; zo!!5gB^KlyO zJ$dT@!O4g<0ioL~LvhTn$N}j6bO1Cw8XBHB-dm?JzHwF<O$Z|FQ=F z`t%FwN96ARz~>=}bkbYT>E5AYV|tx=T0$VGXQweTm@aW}^5snLaqYAtG`mDK4u)9? z5BoaO2Ku>$T^RJkjr@)wMa28-ZKwHJDT#7FivsG(^zoR}2beKFlXH06oX$=zm8=}u zXoiE=Ys|N)UBepn#Jp=$ve_v=tOPl})I~{>HZ<1PBG9cFsMwiUzQ&r9;V$j87L&8$ z1#Wngyg*@m96Np(3JsYbT!MgW!VOTLTvFctsHWznPYXXk6%Z zxZLwGL6rptFWq%gt4wuD*!yi974zQ%#_Gs}6@Tb>l3UD%R}Qe}O{MniZ*7iYq%ZI> zBWFXCB#9~XR3ccw(rD7n{sI_-aE8{&KWA?n#>?m#i9VqaY&kWFNjF(E|EKIhs)gdQ zp2i~u5b%Fkz9wG*8g`b50y-vTPXRy1_ukjD=eMVh6Kmbesb)pa0di#_3Rt{gV$fSn zU1KQsj2vmlw7X-6j}h_j9IwX){rGM0p)bO;ZcTuwn1>HjY^sOSl2%!ts$>PJ8kqRW z!kn^wlu)p zmTpy&+0RAH!6LMn!It;xS4lsF8q{^w^F7~9Ls-)OX;sgL_*7#tZ~IVFR-iTmpjAD;qbRQow)hWM1<_++CyS5nz>W?X4z zm^BVjAj4Okqf7c4Tu`wp%d5%-71R4D@kVCR*U4>Mteh705s>ZY|9iQJ#B7iSqr1gf z!4oX>M->C|Q(`b69TvsU+LV%P4?^(N&rp9)smi7aqAQfl zoy#-mUZn6*`|~@~sjv``0QwxR@E z`&mI3*W0Gf&!pckU;Qa}ZWavxQx1P;KA!eX)t(X@l{{$#LCqhM+|uF{-d~Iqp(dX( zgN_lKp>4Hennv4LU&X&z6?nJD!)d|xg6efCIieyQRc z=Zl1-y%=dN`j09{Ghxk}S|92!M*%xRy8OfPp?l$+w9k<5fnjtc^g3|24=}Ats5F<7j4mxBjqxx>WwL$lg!Q0(v6l1^c8ir@HAx(7^}S5fMFxnkUAGxn6tEv zV7L~xlwDY`t+LRn1!r+?s-0%>2)g7bH@i~2<)8f7DV0DwwCA@5>pwGnc=T7fvBXp- z`RH-bgDZ#fs;19n5A-(%&6HjZ=l)hf6Ma6 z@vBG|W0uM8nhfq4E={7MXb`U^j?AL8o>eqwJGz8bd^-u1YCn zPFD2&>qybqD?NkM(`7{Wda@3U>XIT0_z=Zk)pJncyD*uBV^*y_TF8zNv+6%69fz8X zf`_JZ$O)=Lb-T@hU99q(pGokmvyBDzMsk@7BB>E~(P!Km zMkhdhE3+ZNi6Jhmic^pn5_n3)N2RqJ=Mscdz1tFbb@%bk$2))Rh#I+mE_l#b?oX^j zGYpP1-6WXs&^p4DT>jC`xps$XQFscaKN5?<;h#pDa{=kCZ#qz{hE$jM-79t3&=Ym# z@tC5ooilLIX11l)=lV}ybb05-xIJTRZx&tXRes(f`?MzxBPbg=VT8P)M=(6qJ(q^Y zpOfN6*rZ2CPB_yH>*Rispr$c=c#r7cZE$OB%rM2gJ1Xl*R2fgLVe97oZ|D+62bvc}ayW*e*sZbJiRQ1z7dl za=*BASq{S?nbz9aY>eZ+{AXVc70*_o4UZRD%OCT5L&fjRdwT8k77yH(cc__2a;?5x z?E0?g$X8B7A{ZGH@@H|h*8^jCxeGp=I>r`eHkgdt z*+DlynSHrIL!Mz6`-?-fG$AS2pzpit6ItR62;W=CFy}H+a$n>VJRgUPH zm6ldWf-?`4L1M1p$a)DOtwpSbme~JlEdRb^;=FzdCHx0)r#?WtE-EF_%&_e2D?XOy zH?MD`gbsNo{*evhDR4yaSL|F8WK|QaMfj9pDSh~unDBG?}OEW{av_lUmDcwVN zigb4h$k3hAA>AR}A>Gm-9TL)w(%Z z>Y*s?zwu|8Koj3YIdV`TY)tVYR>Svmi^UV zaWKQ;mq;j-(kcqY3RBSVgpEyI8JsbP3aD4Z6D%1vWJ}QabQ39Fn#cR8G{Be=OjdB| zy{Dxrb7lxQU6y{dp-vS8Z~wNYtDP?lewA$7Lo1Hwvt5;*85uajj!pw5fDGc8_coMg zMK2X73M2Y*t%CWZc1dHJToxH{Iq9vl7W6W$ViOpp{>wd3z}(sEkUkKF>7p|T>+$&V z{l5oBxA>^P(}a~Y0-hwBS&`z2KSn zT`~km3ug0i{RLVzrkB&x<5qvWD%=r-9w?#oT(Ttc8_V!Ur7h|a|5^t07Ml0SlQLV^ zPC{(mQk8mq@h95XF^e%EX1QqEK6>stoSmP67QFIP+vG)vtB8fN)K!FzD;}ERbzL17 z&0o6lPsxk?zCWH+jq`U5egXWb{*FznzTJN(((G`Wp14FR8%zq2q@dc20DFbgG0dv4 z)42SI>9MZmB_Cd6?jQ(iN5&L$`wZ;}`hzr~gf>llC^V+J9C2YNXF#HxY!N%%E++c4 z!oh%4cx74v2~1?HHnUmI+>mYCyZL#>I9n58J^P;!E{qOi2(tzRJ0cL|zIN=!7}2-N zv|NK*H$tB-q&tg`+(1LzkVX0?Oe{idREE&U4-`kwF$t{-GyIYorY9GR{J{?lA@0KAPBD8(EBso3j?Zs@Q zEEQuj>RxTt^tY^7YxFZAb{=zlizMR|*%z*e=vVaofnpEWeto_CVJn4&P|Ud<=0<|P za|~@*cY>j;u6X)~LXEr~TcMHr;o0i^OFL)ILppM`jJ{#DAL0|vQpq-VcZ5s` z=G5a0+}45a_j1M`kBmJ9t21u6INK0Yx;}GeKAm*GY`nZ|_^)hadNS{pLFHNVoVEfM zF(TnUg3wv>@Mg0`mu5$EA?2VYzq%T4+2|f(rZM$)l)f3?DI+y!3qRz^3dVZIB})T+ z4kC@c_?!K5ufyD>5PUA^%6p{lkF=v*XSYJHxd(P$Zb6U9-TrQf1___);Xq>mQ4rW@T9x*q+V*?P0NMOsiq4*n+f!rgtl}ljqzkX403KsB zJouDaz&}-%_GMtuoY0C;<=t(o)0~-VfGDYn*+_?^NKzxzD@YLcpvXaf1CLV)^#n6e zunKv?LY>RPLa~c=U0m}4-Apo6dz>WCERj)KGUFXg`$9nW=I`0DnzzDT5VzRepEVEL5sqP6ifc1%x}?kM<$RM=8Kbu#(m%`Hbl2 zW(LxCVmA-tW2I&KyUvBt1>9IfK*Jtn{Kn{sbo%Yu;v)=?g8Gv$?9AaJ&V^*qyB&<6 z-k(fNo2k;Z+yr?EvBc0_pZQA}CAIcsESVPJ%sTuSD7z#A|mq!6Z{@C$R@ z6rAaHe%;TiA|pXXMb*e8Uq{WS?o??0iXIsIJ_beuhOzI7bHOlu4=SAv9;d+o27d!1 zY_x!>;pipJh@VIZ^nspgUb@IC%kftXfr`F93K`+=Kl`d~yqt`u`c>M+OAyusIKyQL z$-gNj4xUuzme-=WW+(dmVcf_HYq(v5A$pe-u@Z$Bn}$P0>3e}mmpd_J%q&&!tSs#K zqLr%@KO8PY82`scLEBYCSKCWNY0-841hqw!)$^C@r8z&N?xWeug^lJ_r`z`o+J_xy z>#OCkKMR3Ml~ZwAlR$fdEktkT(on@a2@Rtpe)XxojX+5;y&I6dXi3MF1emT!;K<>k3tUWAq2@gzC0&yJg$y} z`LNbDKovj2TSQ@s1E`kj*uo`8W)MWt{+OPRSu!S9D%rGk=^BdxM^}<6w~2>7m*j8Z zVKOz`!HD2@xFfBi+VA-^Q)SyTuiC%mR~5y1g?;M?NOP*oYQaW24^?3&m5)_KH|IZU z+GFes(2*)w<2@_esC=@HJAR0PkxTxK#_gIGvl zaafQR()-J9Nnno`Q=&;RCKjVCq2V7p9TZMmvH))v9zUD5*XXIie})!Z>DxHAv%3%` zRgbG4^d@vhd?IY-m!hFduEMiM&v%=gDv4aye23(=6P15u9FVLr`TkfZ-&Xw00Ue39 z1}ghML3A60?wef!q44go5c*FT1!*kmSZD+tnelbcMaKapS>>Azc+X{wVv5B%!Q)mV zQ94LW#nOZnA{EagZ~bG%q;HC)^^;{WKKBloSjBl&gq%igI1qiK`&#p5qpdYn-;NH7 zTy9EZfZ7k`o}ok#qoPhNX;)9|W1-LHw-=uA-@O@!T$T{P_@+Qjsz2hN5;d>Iha_(RdS$^G+A>kqMpMds7xnJ7c#IE6Z1 zm<)-5vNZ-@9a>{9ABhYdITkZn)r>_dZskyVfs=nu{2yrMWjC@4c{O${>4&s=LZ zWW+RToyOG@e>sVToblhw1qbNNgB6UfG(d6~A2H?+A}R(lR&Xd4MJj18^Uc`jju(*{;5* z$84;&sO*@PvF@KG3w1xI;?0`2?(fnIn^CC@YSt>WK9a@l8QCk;!A?UHS%9uYg;r=k zQE`)qYTBYqaN}ct{8-c=oHO0;lR=)qDXqV5euIWeZ`E&6mB1VFX8xKs{qtcWeZ~{T z%xtxXz1>+v%T?yb|5eS_?_aBC6HM~gQ}KqCz3G&nzHd>56}t!|*KV#vSbebG3<_~o z-Pg~bHa_|g1|l~W>Sy~ZJh~d1*n*uMSJ+|F%H1z#-OHy>M=6xztXkYRMSEAuXn029#>vrmDe@C{w+Z@5#w01K@RCA&fl4U- zr^eAb`$KE>ix0!&WoCRZF>ZKu1b$8QRb)^N@3&yZP}0v#+-B33Hf6YBT8Ok}D9QAn z(heu`vjPwDnSs2cfeTL8YGmz&3^$XBQ-?vM@137*l&)&K)y=Xh46JpSz7OeoRP!y% zV?N_N9Za{5Nxp>GI>9FWU5V-;!W}E|Tg(fgfzpN1X8edQDZT zJbUZgf4K(=@S1)NAp}q!_$fH11!K{T3!O<*HE(?KO4#z`hWw93F2;+tQo;CPQ2o}w zZ?KIu3&p!;$NBD$GDF5e+r(#m8N{hM+}|pB+n@9mJ#*ImFV0R^+tTf6!{g=P(7^BQ z%P?@^9x`eS>djCP&T7mG-Xp z=Z6a3?!9$=^hbA;m!-A4Mpa0i?2Kf79_q|y(oVTpFtaOem2hQM;|89a`6Ws+vE@ut z9TEb$s+03YO!1a-tislX&4}BHD|#3!5fZS7%)=EB#rU?(?C3gsCnN{AH`2!t6<>(& z?iD?Mp+HCv>}K`nC@>ZLl$xHn(mP~_>OJCN{o*KxcgPujnGtj{`4!w# z^#9ZuI*n4Mtu8Z!{Hv|U@>Drpq8wTtk6|k6WH2)X3jytF3XS%aoi$4OYdIOB_ZuGx zMf}&AZ8ttnsxO?rtRJ`dR7FE&LYWW%V5Dn6E*z*lkf|<|sPbz)uGxi$M4W`VK+(Ih z2%g`R>+ZA|dCYd_b&w7n}vK+7|4GIjT?~;!t zN?&qvF`x?%_1X#fMjm9yQ{Ju{Q&_e7_%$>?G&}53S2^$|s$3AOh^hdY5VMLUWo7Vx zd(E&~59ztq{L`Yv#3x1xhKpjoE#b{-;-6LHc1$-;_Vf_`Zp|fZ8g04+J12ORG6jk* z!Gs1TGKUUxe&i5iSQe8b~&UtBib4XE@xQbHx+h@&`8a`@L z1nNMJk(v_moeD9~zlBaazEljoA(0##iy_7!8MJ=n-YpXINrM36G+fV@$iKH9cC#II zoT4BdVmAp^UAFNT^PY- zaurrP*QgP$n`II27t5pSNhO3!2aR${ zM8R-2RWO+xcC*(m>3sXNp^bl1RVSG!N*QA<4OfP9{Iqf7Gb{pBt zaCq}o$cY@W*4#@8{3JBA(cpyz7JPsgE3lTHDFjpzSI28oq%_u$&pnU5d5;thj93xg2$Stb@GK-dMf1?kn07Pdr zrFsp2ZZKyUPU|2-*HBcGjFHEDw;|~8`={pJo^Pf7M^Z6lm@3|@mNbC84>s>{6vt$F zz2fO)vF=qSoI}(_?qH-xL>epP7Cpz|#m4}{jUa3eldCulWT{{retb@TT!}9AP(Dmz zwbA~HMG%INT06B@7F6@2CrA_y;N}E>O(~K0%#~PIWo^gdvOw$ZzA*!U{!RgVV&w^A zFdbSb_79)1$P?3GZy8z4Q&|)zGESYe^G2ZHNya+e_0jZs%`k=fJ(utAmC2_6oTA;= z|A^7umG1dD&xgI@<@6i-g22qb&ube`;}vQ8mG*Q2@ifG@M6yh*Q1FP$OM#1WqeXwC zA>rL}TqZd=8+01se7;QLlGDMjBxy^_1FMW%qt7gz!N&dYHH2W26Nc$9UbC|aO$LnD zoB_xSBh)PaQ=%l0G$7}@T=Bk&=8iw*W4c3@fcc9Jewp!+s0sxql>oO;FI^GL?^G4& zbR&u?XCWsa=cph^aQ3h|9Oh#mQy6$+SFphnNs?lyuQ1v+sH1D?eqyHF10KfyMOiZf zFF;*1kAj6sWiCZb6X1@gY~|pO1R6gWB^~M5$C$qTVw~cQP&hTo!b00y)^3ydi>) zdf9tde_6El70Y9qqTvty*>{!Npxg|m;!84fr_vN_$R2L6nn z_?|Y;gkK5%D|zq3%b!0l>t_=qF()y&S@}U|aOA~0hP<#X>Z9zB0TfQ9wfWw~sK!vr z?Xi#AoFs;|?gK~yYgD6#qhQ~$MF}U5KqRzi+3-*s)K~Nz!2zYhU?F7R`!<*3DU@V& zi*rvjn(x969ZUZCRFNAKT`$SAC)C`RH!a9@l4a)$G23!w=D)Z1*xxa}pvL@0YJN}u z?7{pkL{m^gA*B5D`KhDK-_8mupJzGz&oCFzOPY|o{XTdo0QaQzy+=7B3UrE5r&0i2 z-`TTw%au_4$DZ*(H24v0&55#Yk=0CTnkeGXSo3yvsH0@0Qj9yp?`XnbQ1^qkWfnQ= zmnOUZBHrhAWtu>X=7MEqtY^Mgi zyeS!-^>-XAY`)qbd>*I#D|&tx^}fFgw9dJaw2daaoF980iwKn=lTCz=WKG-N5Uo?V zq(w(5;gQ<@Wl7b4AI~@5i~eQP+dKlop{2k{Ng~LpLt>pmm1ti~7;;$HRF;&@y=&hD zWb6HHQ8Vq#aAFDXu0&yw>YIK01X?(O*BpyQpjuJJ;k+89+|;qbie)%QFVx6Yw9s>E zvkAZ`9HZ79TkCQp*?3BA2HXxW!KD%-kmQ09_ROKi9i@mSjGqnu-eMT#O8!7MND}Gb zi@lK$6R6c?Gtr%v!y}7f)bzw{6aKy4*Mb|}{fDwT- zN|P}pM~jB>t<*YMMj_TbBrPk?+bUD~t3`Qh+3&3)@=v!d5s1Kb9-az%62MUgp_S^W zkVaSzyCP&sj}d|&UuNr4~|k)&Bk|_|Ui*khi!r{nx+U z@U|C_`a{)Hp&OyM@IT$kB??{8B)fh16peYPLj=j1XMRD1W^`yb43^pY?7!NC=%;@AR8#= zA+zX|MH0lAqQQmivnX0#HteP`rUWeuulWDg0Zt7KrWi%#Jc{@K0sskv;f0Q0%FSvD z&G^`)%B4QVn}G5ZXV#04z*w{xxRPqiHwQc1*KV$K4>E zZNM6<`RB8>_Aq+r5 zq^9ab%!}9dKKf1$=WPTUaFcWfNMYf|VxR^aZ;KPdoxN;4tTd~grs~qjA$; zQy1c(u}Xvx+b{UdIMX)O;Fqls_Jud-PGcioA z)B>ODs-H&uGJ5N}!=AHq$i^xZ=!Cow=0*`Y!8E-!LU^TmY4<#o=XPb z?B{=+m1Ir)gIaf_fk-S)MvOr%4qUIf2ez*1eDxr7r9n#J5DrUM-hVjfdhKepEaGyO1{3ll!C%GntCSg3S+!i6!3ynB!oE`zxgXD|(j{-&^dh98)@ z>P>&K$HcVpxLy%%vm*(Id9IchiW;rbplLO-o)<90Oo#Bp$$?1|7?jB;ij#7?LEF30RpEWjh25L1Yk+aitWuWy&G|-vu}AsJ{%o3)tQ`W zyVEa4>f0uzw88oTv6PU#ZRkn1RGmSh=ZEX?qKSgJ&61Gcx#^ptj|8n z|MYA!P1*NNEnS=6ZK?g%RxqolsK4gu_-FCa-hbuc<@s%*sT;y6PiqS=+z66V1A#_LOpTf?cW{}gp%rkbM%>^@g zNpjTNzs-M5NE&Mg6HvWA$%udK=SMUei1H2Dy)agYXen~`FaeG3F5h zQ^6pDPTk7J{2%5gZ_#+m@aON6u?e=NtzWqmoyTn5X_M;R>WIInhUHs;>q1>4`zty( z7$J@s=g5UqM};5i@UgWz$$lEizm(^$kzYmwJIu89w@objzYDBq2XF;EF+_(5t){ z))5t1C8efRYJaktOWsKca`|Q6xT^Tc?ch0wpJMK`(0Ah>^PQA-m+1@kntSuh>d{!4 zy_sFSbehqgisY_n&KOT!B35WcSYCF$`>`@QeEL9$g3zBj%Q@5gcWXi=zd7Vn{VTF) zjpCHD$qD;Qbs0FY0oxx)fp-E#MGN5qK-M`f+4*7KioNBHw}0HoKrXQVfty%~9oH#_ zXXHzDJGbY{kv)ofuo`VK7u`Gq?mq&a0Hjeg%Q-QnetahePeO=*Z|r z`sgdRdAteYj86(;nu-Osg91?K?HEY`0dvH@b#wog&sRSZHS`9XW5#!N7B2Uo}5hyJ6GrBY#P*$gUZJ1J;I z3X!g093fYx!+5%Pd$aYDofNe(K$0&=$6TYsW>fh|f9>VvD|?kaF6xNNV|>LlY|75m z60w`E89rJTkG(?ssJU*==S5VUjFG4JO}dwNNj&xj{Vkn6IPi0%&}E%nxV4wO`Dc1U zMARKwz6UL?>^TU`P38538@mN&fd%u5C(L_Y_EjninCM#abD7>d5kOpV%_#p`HQ9%wQDQ-ky(vVbhNWLTiK z67^V6oz?aGw|gP=D|s}Ej63K0gRd#%RBX@$4lN1>I!15c&~U8Yn{RBJ0dL4$lQbd) zuW%l4BX3_^EwWRVSF9O>boKI7#1&AGs6xifO95g{_P~#)5yRmqinG;kv246*`%=cp z1LXez0@3tTq=$_$Z7@A$zy2;~qn>Eku>DD|cEZ7s3QQ(*#E}tMWo|dwA8~dwz@Z*1 z+35aj0ZvQyB3E^IMb9%FAo}dTOJt1i&Yi(A$F3LXB-!T#QQxT<(s=UvMYC9yN$-vi0|K`TPN1I5MJbcEtR<)(QJ`_caLwV9-( z1BkX{Gm?IQIoAmDrPU*2fe;pB^Xy1?DNA&L&pQra2XZ?@Sk=^lrWgxjN3|ww33&gOq~#p4 z9$-2s9KPQTaPBhi=O>=aTVbx%_6DQwzs8t-WZ`LsR;bXF$6CMLV7Foy+0<;5z}$NS?xo+BP}BI-NnWEUCjT{M&u18C`Gi(7 z(3}hh1xPvm?$e-Z!6z_KmY6R~=vN+@+2pU`aM{3~VkykTuxUh8AjmhU2N8s3RB@{? zL9Sk;R^+i97%qs2I*5js%VNjtF*FqfM6a2P+&qx?*q|GKsvJn)Z{Ap4MEG7mQmKzr z8^TP4``G-7o+mf}T|pE~T~q8Rl@peFH;myyyoJqb)V_wrkyqbX4_)0uTL$mF-T5%9E0OWm00RtKgyo+(f( z*&|JJw0t>a8jUZXao3FH`RGeMID!>MOKUDI(EQn~|XTpNlz~gLG zo}+pA*y!~mz>2@Q2N-%>5s+c_d%-a$l3amAYN5HT;`NdOWY zY~O{I^=`F^(fiUgds?}~_|0-!dDb+8+;aNgg-JAs9L2|*-(|vg+!2)nb4X~I8W9H5 z-@R{UmNX$O74rc@T@W~;)0wgYm?EY}(`!l(Wy8{w)z8kqmy`c{I7n4ik@ivFnmrSW zTKkgIFMe-u6}O*azLaje&#F+_`W_289_x)b++EQR^>2;L-G3k0@=2Lh(90FYQ{gbJlKt$5GFq?sjXCtteNr^XR5m4gU8JruO8+ zqjUvqbYxo4#GW`RQz(e;wBv36HiK8V9rxh*^0aaP{9M%Cd01j0M`4wyaeyRBKm{sA zcg|xG5T&NSW1sn;1~GC-py`E*1zDxYq0eLx=L=Pcm{iP?o9j}yD`PmyVL!B ziDH=sU$DI+ru$#mB-b76%Ep^zX~k5r!0MBz7Mrtke7uUKIaTuSACj7Ox}()I>z)(P z>05#^L}pA4BdtJO-o+IUBhQ)GkB~+W;cg2ihJEyG0mwXqJuZjRp))iPPtD^#DSAzA zGW``ju(3sY42+{}k3dg!Asn1{VDxe9Z|cJ>MS>VUJU0a(V4Wm*iXI(4)AwUW~f zivqO$Zpravsr>o5vNTki43sEQ&P_muhnI`O$r}uh4JL6~Am~t)o&Ak&F*Rp_{Y9{a zX?j17f8yH25*W2GMTJvCdxS9qkc?8C#m>J+m9nQ9aiAd^*r8_e6+zhu(QZ4Z4w=3C}hqI^k(|Bb| zn764log^G&N(^pMub&o}&_PH>C2fxHtV3E@+F^8Wfi~cNLLnsJmua)ns=;d4u~BIG zU*mZI1w6ibFFTIn6u#bOfn5ujSIcM1DOow-(Te0_0)I*~&%L0NSeETZ7_lb~mAdYr z|6EEE+=13%C@DP~XOzSVEKmqC!ePXGQgNfEQ>hTk6Qj6<{BkE@b$@tT87=c6r-M_Z zMkEM~qxM3PZ3&oWALTDE?<@JuWyOMm;cIK?XdWB9<9>$e9)T!HesP=6CAC&!NmBuK z7mE>{!_Te$C8#beV4*Tf(uw1+S~FhAa1F^+PhICMr^MVzghY(5DAJF5k0spXrPuD~ z_-4u)u-gBwPfmFv4_j0QTU-f>;COk(OST3e^h%*r z_tpPUL3yVz84-J`@b#tk;iNqyM3E(?Fg^)NcPjov^;e!sY@#o_GaTvH=<$p{r1U{> z-t|sj8u>%oSnfI3k_d@)y6=fBPV_#6+?+ATj!QsBKG=8k<`?2ek{j>hnMX8Av5`_5 zVp7mPLbL(o*tSGbH?rCCAIw71M8Zr2$=)U=iKzMo%LNrt-Q|`|U0jN3;h}R=dF$-h zX?6@5InRWZinO;ImLQfFV)hNmk-j%$U`rt~$2Wzx7h|!m=)DqUFfzM;d+} zZ0nB+vyw-|f=8w%b!6%Ri72vi<*e#o8lRRIyykp}Kek)*BisV-bI1OM9pO zX14RaZm>s|B0ha1Lh?5EgB0qMUeaII$PI6#DaR`fqxa|Qs(o?rkRWAJWHN72P8^Kl zA~?~DB3E%|vrPyj3S|(;@BbuH|KiikL|s)?2M^4)k7BJ!`6CV|CYPjvZ?0D9&SV&k zmCLV+qQ*qTN%zSOl61|Osq(IvEbFd5j-U2x1oh`npHD-5(oRZdyJU^|iq2h+ zmoO7*99IwJ?Cp*v>_+0n5^F@n&rGol_AWz`2+03*cKeAKuAS|4Fv-ryLd8XE@v@0j z2jGJP*lhG^=Y-0Bk&O;hXxqT!BqGA6;+7ss{mO&;>S-}EKAwPRC!J&mMH=EVof9b4 zOkr^rL!%Raqd4zml^euGBv)FZR$XnjG*k1n#M@K>er(^%WrKgUnYQDq`!#996j*eQ zU_<)xyz5L@)to+2_9UY0cpdI-P_0r|^ZeQLH)e9_LZTA2G5SmASbC^1a|8l}f&3FN z94>CRJ2pUG6T?txh?V}+5L#e6XIOTjnn3vWxrO|oD)9Xqz7X1Y9P`Rg`#G~cNGGm; z2ePv3=_D82lo4X+*F_RyQe%{^K5XC8=)dPU8$98;HOhW^QC*%5%t_kjQtr&Pt{iJ- z_Vhj!z(q6RJ|JXt?LK&L{X6X`^HlE(tH};hZDE$kJ)VKm5N>UhNKRt9A`KMmtkUb` zvRDK2V3Mr3upQji5!N8w>HA%F!Mcsk)P+QIs;e;jDIQCoIf-(8IT_>e|5eTI!mn4w zG@yoaKN#DhVfc0fWUewIW@W|{h{vO(pGZ1T$zX}0R$rp=xH@jPwy(S!%>MI>R=S>r z&-M5PKS2}%!iWGCo_b8@^9rK9UV6U6#LLM@slUA)Kqi14i1qk|^4Ja6%zLg5_e$Pcl-V)-%cLMdNc89Y%WJ3%cbsa-bDatfL|G{_Fn zwJ6qMkiT?YRo*Y0IO2~i*p}n-KhbCh>Rg|p&|q2lxA<8gC(3JBt@K(o19Q({uiaE6 z7b}M_?6AcBq`v*v;&AFm7^4f0oCzaw>xRN+9b0kT>UX;8%p?aUY?1LqLGZMGJXYe9 z6`dI0->Z_FKf*MGh}%drh|7Q*B!!m|?v?9dghER%pXm+P4(tH%`A_ldMp090# zVc}vC8^ee`Q9W%JOfsBL5;k8B?$Id{&Xs9aU&?_z3jtWbNQ0>2^_7yMXij zd$zW#a>m{rOcD*a7r*9s%XAXy_S5@@d-qrK<@kP+K8XUni@}L{`Xm2pkE_AERy813 z%D%_5xk1|si6nxO##=;5F=%e!Z*~9(9Xm@_ZPn01>rDED-E+Hw)_?FkgfbqKW9Mu^ zrvvpOK#g=#4bk8iiyV$Db&&F%lj8m0mfXxe6z~#56DHy4+bIDl=D1Z973X3sXP`pF|CSAH8{8fsVclUu=3`Ju@#LP@HvC$)(q)Kt^`hmUX@%i_mj}1+r zUESU<>!6MUvMv_4>v8vlu6nT#WH+rmnsI>8wG;oxgqySO^_7>G&iWe;wlOlZM7Z)e zVum}_@a4E;N$POQKSVqplG-$T25fybdxP}XGGcY~3RbmY1_)#CXpP>7XEd#tXNX7I z3-JD9+(({Hdw*!>b)tE|$yJMrDW!3h0&$Te1h#5V!Y*=NXU%{zSki{s4wJK7!0H|< zHFz>`P_Hy#GttAF# z2$XP*pUaVmrV5uLO4!9o=osOPKcUu;R`9%*)bo_6Ob6B722e*48l@JeppHupa~i0< zfeud$T7Ds*ub4J zUPB;{Jh>wz6e%c-T?%PQ)*MwW%Gg?2*A3?A#prq24n!HSX)lyb^7Qg!D$ZwdTk$7e zd181kN@91UMew}gU;niJ%yfFTzE);`Z4D3)3n5|@Rej_)k(J@*E4Hat(fDhuf`8fD zE@3Q#mxxd%Lt|J9ie)P8!6CN`hUywN0BL<`Wx4X`#rVit3sr_K`T?;Llcll-)@|Fd z6>PvdsYr->4!W+D-Eg7z-39gJN1Er2o}4V-xJ9E$_U_mui7Gllf$`D%a!<{dLNzor zI(H@7>$qMqHg&L}bw`Th;g~{KpK|Budl#=n+Mnd!gH^Hp3CybErFnI%ag~cw*zU9D znamM>Ha69^nDHFDzY1G_IZ&o@>_q;MR07wV06^~OO9rbGn(L+wX zlUNq087Vi1_QWN5{;9@=C#+{x+jltsHJQ9uHMi)_xbFQ@qJDK^vvD$>?qyh+z#a7g ziP|~Yz*^ycSbP@LwYgnoXA}x~8u?{SY{ut>g@`08|DEe|pTr;5&~!~Y>@|HJvqbS7 z_k^*mBj=k|ebmDf{9vucasK*H_ctvk#&fB2#TGK>8w%ebQgoq~#E}9|k11K#I;(Qj zT~?o4{T~hV4d58Ia`9>sgQ(dp?Z4f8@jo>h|IpMV%jA^KjG7>sCu%B!D$iMhtKNfM zfow9>w9d#}nD28<*RP^Rh|V-9{zQt9RLb%5q|R>i%}O;t zzH{fi)hSbyGp9KyN4fm>d{+Lle$o;9h>;g z5aK-&H4AOPjvyj_*SKg*VkptcfR6<7i1Dc13XRThV)R`4_$aDP<53JacmZQO3$baC-9xa$9^ zw`#lPp(@2a%~pWw(U~*(*NFzUco=P?#EEZcV233z^(QD$%JG$3*bB_B?F^!!&q5lY z77ASzK~jwX%5DSIo)g`H0-X)93+r1i^IxPDJ~z|e_q*z8%YPh|+lg-i`*e5z*?2i? zE6Z-MikA!5f&Y>=%!4#e$~R2W&&1LuS$%(K@#9lkE7x>rxTLwXRfGh{q+@}gOKk;L zH27s<#mJ5$A_RZ?2<_9n;-hXA3r!qz=8oHT3I&Olw$KVq4=9vwywFGSyJFl0#FdM@ znCE_BWeA^qd==1%NT zq#C%eri+j+_aCYT9+NZNKdJtB&y`z-jgj&&H|8QZB)Fr3_$aNCk*r+$6G;_S{KP0u z&6?(w%rJ^jW6Ohk0NBcIZW+`YCoQUv0+9VmD$V#)s*`dZ$G$6z;P-bD85=$Kp}*0= zsJA9HlAR?<#TB09MLQP5ZHYkPU%THE3b)i*B39$e7(msZ?XPxdEd(D^X?ZD=IbDZG zYf1eL0pCrxFMeaD;H~7`@Bo^YmnE|qtO5_2NYvn=x%6}FbrRfeyGdN~F^oO}LqQk; z{WSSoNDQuI#TY!Cg`aL5>?TRwKL(Q)&juyGq6fxIC7^f>I~#B|Ecc}Uu_g+In@j4E@U@_8^Y28X(5v(%b(lZ|7Hj z`{BfArvGE<8vN?~-~P$2Q=ME}IN5f~u4UU?-10ivE!(bTE-%}*TeXG7<>&PMJ@=n* zzpl^4Hz>|dU)Iz7&K%;>O^A8`*a0;#d5;Nr#*tMu`4Z~Zm7#sn&(Q6`zY!PEDpneG zMk~HWeM1hvb;_`2wfNL6>8Ns=jgUg4?A{Oui&IZXBQJQ+H{O}L2`st6Jm!j$<4x9|v#X{DteAQ?-T912?@*J1rcJas z5^FWsgao(|>M2O-9PDD_wxuWZ#c3j#pgW>BTr&>Y6jUkGB@&(TO*`yD>I2{H=hlhg za^u%b$81W=u`EIw6U3i=I)@?YIv53^z#CG6$pfnjB|E4rZ>Eipg=0}dG`r%pMxvNh z;N$`24@eoy0UZ zSg~0!V_YDZlKf|}HV(t6k?lZ8V`3@YTl7FTj7sKj(NjUk$Ob(S)}E@Tn52!-$Fbwj zH@dcDTbY=T`rY;>%h29V$5Qe>=#3xlJ0>KLM{f(X*(lKAV2qHmtwzgHS9aw-{LZXB zwYg^>FtlmfI$Lio_p?xhzz*p2pko8lWK)`_O$kS&t6~rabgZ;7H9X17%#={mN+I5P zKB$4{AH(DG4rn~-brFBG+h@fp-sBVD%49bV=c}r$&O1u1A@r5D&hcv2UGthQCXrQq zhT;F)iXMvj$;wBfA~ZTHW&H&+6js5uPHGfGF2IFiuk{^W(AMirZcC;n@~WnpzO-4{Qn>#rLj1ushAHB#{Fl@<-5;2=T6G z74r-%1>g1=0_h_G{{lj&qj-_RN6=gJK+nrUf1#3nPLW6y?9kkEb2l;Yk#pd)lIEVu z5PrH54r_Aup;N;9Rl}#0A=<R#(&R0o&S2NQakU9J?ca&=26MNfzALAY$#4;_GTP+)p$iB7hs*U0mduUvScX+gXrcUcO z#zg;~N5#bKa*W}IJ?I*bL1v1^??2r_Xvu$mBbK-o(2_xgL?|h23K{kW=8{X~Fd`&A z-zTSLy2bPOPl4Bua57W(kaKRhjVB3mGB?m0#=mh+N}0<#K2TGN_xBtl8Bv7-5D%p? zRN`i06^X)Fwsg^BloBJp7V5oxa%}v7 zmsygEz#?AK_DyIY2rL?98(8gglCY0o5MOO=*yDhJ0H%``-6Dsiy_ZNO%(`Z6B$qN> z!2W_-E0D0Gddc7l7#u}LiK51uV^vc-L@kf>RD75%El%-YyFP_V`Dk!Ag8?+^<%P(s z1vo!@IZ)IplO3EBRr$2#dFwTkV)9z~{DegGEXq&BFqGE=7nU?Qt`t&M6EFDmzHfG? zYa$40lh(12>4?J@^&FwEP{w2Zf6~@OftGxiKyb;Mt;7Cu<&*n~f@zYh>7wIdQPS|C z6SKUYy>bvs|BFKA{&l3WxLbO3aaaKPE~q#I7irF{(cSUr?4^CRRLQ{+lx2b}9bb}0 zYAxFkP8aLoLU`qh<^afhMipiDwV6t(bfY_<{3xU4*0DN9{BCBy-O)T}VpR;;RFdWb zl-t%;jYehaPDL`PeMy-!uv~TZE-UxZPFp)S_x=|m-KFKYkV^JPSLAdHaR80wVUA-@ z4>kgfZNbCq_x6UfOI^Qeo&;3>O)%hkZdukPVI~?R$%g<|KY8a@FnS*vWb%`>Iqx!7LRES(u2W>3G&cCK;t{&KCV3BB{F#4| zz0uyf@4lYAoIQ`FDK#c=LHyuEiN#;g<0K^=WkmsTm7eykZS=F0{LJ#P2>W`JjXzO# zRdMqZ#0W*jir=FYDD;_P#i7gk9&^Ei)){jmNJr*P3nM@}!AkKJ6|%@N_k-lFFm0wkh^!s;9YDM_KXv6!6+m9-P{j3zf6+$-5yeJ?zp1CWk@3R!_g>d36V34=wufum}OYI^E$m-x8uGsUzA!f*_`@t6V4?^ z-K?=cA1$=QAZ%-FO~>yUHz)B=o5#&*)M&}opJe4G@4cm%F*`2JXM(+hS55BT=jYEL zv;A++mgaY7dmnzkemykkqgh>^l}!;6%}dy3!B(x$w-7B$lIL-s)Y1RqK}Ki@W``fc zq!s(>8cnwV7$djZlFhKr#4JRnrr~!z%$b$#kFQr$EhdVI(57q_%lB68<)8j@V&^~0 zqW)=bR|4T51kkJ)`Cs%vfTj{}NP1XQ;JoWfo0Y^A!Vz*;?VGv7GV$y;eysd z0hDIEF`VIH?-&CPNfzY_PGDZX$b|t6Bi6l3rdI6=!Aa5`9=~pvy_YhlLeqsfYZMsL zo6^xukQZdIO(x4FDGzI=MB~T$L|y$(qCkQLh~Wk)aDA>t#u(}w$Lgq`1nQZ=h=(CW z{n+;OUPD~e-QR?lrD6F%dfNxKKF0R((e5D8#rkQ3JT*jqmy8@k(Y)Sp+p!>2 zS~p~k*wGv)o!~zgImr#EE0g0WDzssQo_H`mT9hUBUfZaMqKjbneTf&Bw0Y35*fb{G zMI2jemnZUVpzz>dh2i{iA$3MeDI{Ofozp?tTD~2?P_XERgU}RT7PD0n2Ktwb}v%GFI9OkwT7;u zH3fi?XBgom8q^)oCCpI-!RHNM9#pDb$i z3%kpaf4zS?7PG@b^=LWmqI}(GYYQ{9h@n)1m58G+KBfsT1Bf9ee@$Y4P#kgu;qvhO z)T;YYJ1kvjCN}=HX-Wy_kU&6FSZhhwPCUZ#$4CBBo)JpJV~dI9aqH?Kp?rU03}J+x z2Sf<@$lFi2fM6BfB)&C_F!+C;p{ov2>$x9>HzL@=3!5Y;?&zRKjF<9KKyBA zKi;)}{--n3!xqXwiyFmY6D=9Vi4uiipm^ZL2jZn~IcXKrYY~!`3z#a6 zson$n@Q^u-f4s8r%sx$(Sd&ZLfG-7$dlYwA#r(b^o127}+CQN@zW#cZ&3^v%;YI$r zX1x51E@=!7VxTd=P8POX(i}+>laBOH5TGYf&bjqtECqIe%?_Z<_jf+3B(|Okhx12V zDRn2j*n8z!%qlUEXp4sIS~|G_POwolO%%h3;NqfYiSd_8OCiJ?HN^g(=r%O{{+jo~ z8x7~rst|;y)35$+FZ%wcZgZ!9qUEQqwVn$*^N?>4J!UtbnCd${fGJVWvwmEzA2_Lx>gK!5<7$ywv;OY=Z>ac zsxfps?~<`PC?XlX>MXjQ*H))Xw{0{r6XpodR;*2RJ!Iz)yNhooDMn2S)i=y3*s$3Az3`4=+urCX@rRzpGa_sNM(QzOTBc&FgZ*ZOX2!ELCL z;l|hxCnlSOxGWAlPDVLZRFOP!ispmwl1PpmM!zca1R_%r;o1LPOcV=rv&yu(Yl{qz zY?#IJfZKpD*!6@bgh9TD&2}ZRKg&l$_2ab+_OEDIX;<_=yz0d(ySTPuizqyJJ+d$_ zzgH3$v_B|%Br#EtjFkSEU8aQOfBx8Ae`4A+Qvic+lQ*qAp0 zFj2qTlnv@5fsrDNkBDCe^BQC@dh&C_;_6Fh(aY>`X>TCyVW+Ejp}~`tIBt%QV-LMW z&mU;t14Yt95oHtwZ3!v)q9$Hd+dA7S_t3X@#E}W5XG2#t^W-mJM~n8Hp*X;zZ(t*cdGsZvj*o*y zivr7gaTO#CpKZ!J1_&*ymQ=Y<$-%;u%l#(4!{#l_CS4v5o8 z5+y}Jz(O}alvF^6FOynPnQ350Q-s;9_d&D6R$c1++( z(0G@%O@{x*@w*nsnq8?!(0!Rqdi9)*bl*A9fzH)z-Bz1V8%}7WJ`-4k8DJp)_sdW zGr(wcNRO~$FLIMWh}}^^bOg>^i6*ZK`*hP8W~|+EMq%i7nT-R2dY;-JDcJvV4*)pc z{x-3T{3`dKo;8M3?cY@5YY&C(|d_r zK(R}4`%BSHWjam4_i(27<;NrYG`K*Ib4R~8fwN}^CeVcvkhhU95mbH#9ugJ*R|F(< z6XvFf!Pkp1DkS%jZwCZT5UWrQG5ZEm1^_hFgfV&ecJV0~hrjcYTeo!k)K_G8I_JUY z0NCJT-+|L)e?}-_z{D4G6n`acs<`E6HL%?+4BhpK9)f|7r2Lf@hNxgQ#r9pP+Be%H z#9DwRMGV$x;wyc6N+8HS$SXbVW`vN&LhE1uxTePk#`s3%9NX*Y8q9Rex9EXlf~r2g zJv&PJY-i}R`y2gvYq;gcXO^E>r`Y{tQ$e`=mHgDoC-IRzdihTF|;5z%g>D=+wwsOnn;Sn%uVr364>+md^D1kvl zIahF`Njb}2E#9{fH#S8Z=h|YQn%+G%aGP$sJ@@=VBc>Rv(@R0$(862voB@Ek2yf2a z;)IRt(B{wLv};DZe7y7-#zQ=5_FYzmj0H>Dfz7-5rILY5UE7fPsG=}#g8IJ*WOshWTNqJk-pSvVuyJ(4Qj(; z*>v_F57kc$5*5B1D#?rST^8eH=+soPx&#~Xtn+BJqram3GxSQ)&O{JqG&xSTjoTQF zy=qi(PK%RsPtPBR!f%)3!N@a|!Tj6QHNqh1jiqX~%*UK@nAI;n1VUftPycz{o^ug0AkZEAN^xLz0f?&rDK=ak)C|$Ah zGgLId(!O*2Y`_3S&aA9SU?dUw*N?P|pO_s#I9(acPivWuCbR?@uNISj^({_z_HJ)J z&v-~1wz7CX4FEbYkVnGekIw{`X|&4Jk`u#f3RaJ9+wjmMn>`B}c?wKPS)>RH7|bXQ zF=SgN@!2WFVY>EytCjFsANfd2ES61naOzaPrEqwT7d##F!@n}-xt!zXj++ZK+g?5q zGuDkIclWoX=alKdckZI#w1T_(vDD@i+NlZBMSZ_Skzw7|dj+HQw9HBSPx z)CdY0o4l{zIpDh8?ik85NA%^Wm(74TMD>Gq#U_#o6s#%oZ_n-+fP*a)@aD>dUiudb z65l<`+I5%s=eh%0(E|nwhxskcK#bo0fdo8bC0FI_0+cOY584zYt0;{kR*k-Qi|QH z6$7l_(4zUZhM#{5(?g8CD$$Uu;}Dyd_IX4pha>TCi^Ok^7?o@|Y{dsNIn0Cngqn8^ zaGI`jyc9~>9ch`>!9FE8<>PEz;D%q}1VDc8pU5brB-+|vcWz!S4;SW}9E)Vh3nS-= z)d`0nv(SsISg(zIfS7QH9Ixt5~Y5M+;W|kzA=P}1u2nID3tVrLGlD(Hx53F;Nl4^+pst@@C}^-#>Wpo}?oJ$X z5tnaEM1d!>p|ceTATmu8u~4*e<4P4!R{J#FC{svAS<5Dhr$r zSGhZTReCx7qr|biCx??}A)^*omg}shu`K9h18_tpCC!ZT9(X7772#{L)Z@-Bm&5iR z8#6w3!r<(m=3ZJEabMARhHya`DUhi|c8|HHDN7NM_~^ex55Yz-e!Ip};uW$(tKE8# zyxIDyRgX->J@hp1@M%7TnUgM*Vz~3RXlR_JIjQ0Tro}(BD45LXea~7gl(P78l}Yli_GuqcyGv!4`j>Ln>WjaKSEY zAP0-7k&ewS)jVj)RNCHnZ&naGSTX>=NZiru7`4;vhg$Ork^m;V$ap+1sY2AdGNbsL5tO}~L$d4paxjLW0|1LS}Z z>H=Mf^zL)mqw|M|Z7t+J;@R?XmNhvnQir@n4^$T#h2o9uD-OrS4o%wYw@bmCR&2j3 zW9pkjFc0vpjQPl#Inv`tRnf=FTI)M~Z#bPmHeA<4x?CNew*fh~X-t3t)QYW}=Tyz{ zjjFZ~L&KOP(U^~>$i~tq46u0yB}{vjeBq1}t>R>dxmwzabJQ|$o_Ab=I--)(Ull6n z3o=f5yJ|aHisq14BEfXNNhxBF#LAbG)O<1BWC3kMazafnn?f506nxh5gxGV*Bmr*?nteWzpe93Wn9d`9y@wWaB`(PbuFI z2~;^nuf)OKPF|fQDl8^XPc4$v1&RcqG%w4`2GjB66`xY?mwuJAaEtNMQwtf=F*0q+ z4jx!r%ONjw(g_bws{fV&5-bg`xb2*k6r`^CsP(QcvL9PYI;@jx>}aS&{Oa@R>RQ>i_UO3aPs;g}1^=9J^4LuK^+v81rWZCA zeD@mD8Y&l!eSV_q!VV^&>jfpi5Tmc{zZN0$hiQdl26vV`)60d!ll$ZR$rGR@9E;WC z@+C2L>foG{O&FnOS|s}$nd)OYJ+xKVC=0df$@%cyjFdZFmi7`+SnfrWJGS=py;!rp zIi6Y#o-n*eB`6RgE)EM!iIijCzJY%RRssDT>&2Poe|wO5$ttvfH~8KYw9mkFb&U=K`T zuw6F)9-Mt!{f`D(GdP+!qRVb?P6e2mpWX2t7k@3s^>N=W8Ted%`0_Ya^ZfgJnxTbb zV_6Cw{2??cfLv1SI@WdgsTLSrjU2N#zA98PJMXH^YM5>ZRN7%N<+Z1mP*AV=p`$5; zsYDj!JFn~Fv^~iGt|S6Q{X1}@qW(NAX>gy+DTm&PzLR~jh>*X^(3mEh)DtmK4p*os z-k63@m(OncE3}E+88yuR`+nxuR=3y3cPrTR$kU>u04%Xf)VvWG@(DOV3&cR+8;2gJ zF75yVWnXfFqD83n^d=95AvJ@WYE+6G>ATyxAvW73Hb@mAhK`99sd}`dWmm;1UIeC} zIm5$%aCqbsmAdQrE;!sqTDt+NCHLQEVCGHQ!i9k%6PmPRjvqi-`9bKaLjsJHsUvdr zIIF4n6dERx;<|lTXU}J?DL$3WTmefaKPe&+ZV@OXWpPRh2Tjl^J`Z@~xYVVAL&dCP zBljy(SX#WIo4l#xyl?FhKD#NdrKzgN9;zacz@Q*cLYihEE9ooJ6Ps)llV&}54>Eih z*}7k}>eqV}v#)vatorw}Mc7d>*m@Y_#r9D6qTn%t^<<$=ZW*t&+TC|oEcv$!^>PyX zID(M6?A%wfTw43Mq;&Dekw@Clh*`9T@gmHQ z&z_bv=_3?pmB=~M)+u6nr~j3F0MHN@TJoKHfo1GZ*D7DtS)d9Pb{ z8_!!y&JSy5)D-M;r5xDNP4G6nc&Z%NG&sVHuD$g#k;EQbt?D~m)Ufk%7wP>Qbdpcp zznyH4&gT*j^+zWK5mqUnPmQ(GF9s9QDjZp1uuHL6{CrR|M8902$6k3^ zvmdc7chbqb2}N%FP7I8Ci=HPaNsr)dC=R$|sC$ME#d&m0c{}Bv#Rc#6&bK;R)BOr< zAaE%`0DWp7V@!Q)#NbYcZ0kIf08!R${|@J4jZ@o;(2C(e9L)!2{-n{J>oxm=h+L%M zlMSDZ>X`Qkl-^e9basxd?8Gyclie#}o~RFaUr`rx2y4lEjk zSnt`2;i9-!WdK||aqNGomhJstszYAxJggMD7NG(Vhb;Tbil#NR^&a`YY219cQ1 z_P{qZ)VyLx@dmnrHDXvoZ>W6PT5E2LBThgGA?!2~#t3?cvxc)XTga6ez0ouQ8bbs> zT!Awz1L$WL!cPbu9!(bd35}tP9HjrRw6+?mq0K$6WXW>E7{4%QD|JtZIq{J z0!DH*NM8TTA&=>QRPhrCuzv#@3F8HrWp&Wzj|-%zuFB}K-h+fVOp}OA9eSV?N!XAj z;Bu4k>yGSx@k;+bGo3RVV(jur!qF@+7 z5sA2Bgi>fnoZotx);9U^!fR;MCHi=&xn|#@*qLL0KpbY<0W`&a0^W`&?z4AKpY03c zv>VCV zpC|Gah45*M;E%LOSR!EO#uWx_lM1TJ>AArN!W}P5O?RJA%QKwADbZghmU8=uRjMrGO8#@mo@_?84 zm;Uy_eKuo*Tw_MR==+_7ZH>yb2tifk*IUCJtKy5&`12ffyZ};`!`wpHz>Q_F6IusYTCpG@n zioE$I@Q#XBbvs@Z15>*>VO21X$LR&dOZ<*CAkZh6R-USB6y!hP&* zfoN@f+u&tF6SX6+?H&B`uLJ_5%3+q~Sb*>13h+I{VMcrlk=gpPIU4Hj!wufZNb~U@ zocmc8ms93Co}(3Smn*WC#>%!{iVh6_4OZ*8?;n3JpW+XprKRQMPYImZmzZ>r2t-_o zk|8jqXp;JjTszREf4utsMa)R3qviGW<^1p@e*w1~iaf$eCgQqP7u znshVyJ4WcZVe+QXu)hG!J(F?|wNU6VCUe~_Lm1h)WcsTuM<(8b9roA=uDWiKxKkpP z8nsZ`Lkq|0pIA)xf?noA4}<|8YbuAo{J_~papBB`GSR0i zABp0e)tkvs-syolh8!cHp%0))?c!w4`%_7ZdiJfoRq;M(~qZ>p#I#yE~ zn_4Dne);y}po*NN6K~8PJAy*!MFhh{C?u_dcHy)nRMpjBJT5x}T2^<6KJqT~!$eBM z(+RO;?rUwik+jqs)yI2^+$I<|l^6%Pi;}CD5b4zFEN?fBWql3t@i$LCJ%4HojUkbQ zz=}}FxsA~nao`jlF%^!=@C5ejJp>8Hu=HKrBSIUUq1WR4?7z0WAkSV0Dl`U)|v`SU;!=?PUA^U z$sXz1+q1iY059fZ{s@g0kT9|fLszpJS5tJ3$7TW|_HM0#Ob1c)eOgyLqH_!CMucLe zLZgzD(sKSc6=&V6EnoDRT_{sc7-?WwEN)qGMB|mv(ujYK*Bwlt_-!50WHtaNS}Q!a zolB4{P@ctE9F@N?jIkv*;1UPx_15F81Qs-y$w^2xsb(V5(z*DKwd7|0$rW4Qg<3Q% zO!cyc9a*TIXt%uApATrWyn80K|2Ent?|Y)IzKCPoM(yYK<@M3$nf7_pVvf^?N;aWK zoFm4ZQh(r?2}NHvA$fus3xAFA3z6Q83*chJm7L#9diZd@ay8{@u0_gEjdxJo99NU=)gf3vJ$xJjEHlBf;6iKF_!6~c}!LN)@ryC=wZv_n^hk#Du z@Y7aK5KV4jIHk;Yj3{tMYo~IWIPHCkJkrqj%+JyO6yckVt2tib8S$DoRrsY05;T?? z@0YM@PIDy;s-O1+Fyj3=)$$yaKkuXEnc~_AU1V2M(p?pi?YQDya=3B4RV4(g1CTVmnE9ty&Zr9sd9Jtd&LftdWmzk9E?b zra@V~EhFuMMnl22$s$j)8lz<+$B)S|KEKK z(ZX!|YKWobB8gC~$^PjfQB@+P#co}x!K7@R#rhz25`jG?H$M3=WvYrE={hx{VU#8@ zRRWC8=?VpIuHQ)sfh;%-04^79u*%OFN>oCWifef3P|#U&lbH0M`9-~y&xzU|ub-^c z&#NLpF*fL|aerYEVMlCd5oR#~QJefa(ZKo$P=tSx0+)JKc?B3UFXbhSr(#z0U-UqL zDm`yW87pmQF3UCgVKCT=jESl zd0jvuNj{94hS&L*^T$=F^tLQOCeniLc)j2V3-p=k-~ouhXY{Mwy4V7C&g|@#_X=!* zODQ>RY4NU4{X;2=E#oh+62}U8y*(1Muul@fmv2g0Li1q`xI2*<)Y7k5cZ9TVqrY!I zw~zUlCb9NhIJz}0!+O&RrmgL%<;T+WPI^6uFFg)@-851ZuS{-~LyQkrVNqL%!tlT) z0?uty$lV%hRc^I711q!iO-SfmcI^tJR8xx0oRx?alJZkf<$&gsHa!0cqZ~kh(XG(v z89ia3{R=%RHXe3zV5p2fdI?-PXwfpV)M5Xni;hPHdj2~E(D_V3#PpKt4oFGV%qO{? z43DwMXQj(Is4eL78YRmMX$%#Vl|Qv=K5b6?4%feqFNt&3olU|mm+!z|)gA@a@xJ34 zgOo4z3#_4T#xs0}4Eq|ADlv^Hezb8@!zK64>T@X1v5S~1#D_xJr6}vWV&=@h(}k-T zeZ}e=zIRK%I5X_L(&+q#c1ibHmXI((!$Q!t9zjENdwe#j`INwsSn$=JhazKz#Fl(N z%5fh~LmV6?=KjG86q#1E_X|zgCLyr@?@@3+k~X(()3mw#eCRJK24J$QWP`IQkCAF40mDiuK@+a2eaI^nK4_5Hd+nUu5 z1$5B~1wljzk5Nc|#%hAQR&3?mcm6_LWMQpVrvL%*e|x?2czwNmcG+61NVCvi)xc#d zBJ^?>{i%4VMnJ?GmysD6lS=iStKBd{-kKLq>T8&qq6Af$X%$R5HQ0tb(T;Xz9QNqMk(iny~x(OmOCf>p`&{CKwXNooPj3K{hSo-QEGk!hI}g7h;KT5DpLpW~ThAYw-*?Q(5<@!8m#pZRCbAK~nE6_Z&f>61h;`n3FgQ z%?0$RSbhuY9AB#Uk9LZ1mS8g&ZP1#`6u+UOZYQbivU&kc|ITrb{MSO|BO*G8SkWV7G!zNkezeoqV&3Z{@l5m8U@GI<@Y0>;h(~aF`{GwHX?p)tb+lW8iuM^6WhJN>t>8eNOAkd&hm9#2`tBshU{RPcF z^AhVMzGn7Ns!}y@fKA9`U%X|O@GM5W?(4-sk}%6aE2enyTlD;cV0UT3$R0m@27;&^@i+CBeb+5YJBvc5h(WXR-L zpqVGB3WtLsA|55mfV&`gVWgra9o_!^AHstvIRFQUg@Ycxtm%G}>>M6#TabfoQ41qM zpFtX(YpZ#nS(cLd&>`L4uFZFUEW}DI(&go9q;lYPjP>)%;XW)Nqv4M1%l<)f*WuO0 z?Q?OLGIOp@1!t>=k9>u%$jgtz4>z~g{*OLu>`Io=aR3g>6~uTw6;V^QBve>7NnRJW z=>UJOktY&Two^;Y)hI!gzwi+>s2!Jk%}>sC zO*A2a$8AH!w~=T+l(EHDP>L3&I@i)Yb(w6EB=U+8et`v~u!-D*k<&&lJ7y`(=(^0b z3DZ>rh*0OH1NxOBr`w5Ey&c7vK>9YpbQ#j7WQ`dCkqBb4`QoenmA%Kwc#Ffq;@j^A zThm$Hx-k;{x5bg$d3XP|q82hVmS5U1{eW+lW~Hu4M?QHbneWgx;4KUI`TAsa)FS-U z{Fe;sBirJBr?)ECQ9Q#&*kA+xJSa)pibiZwyj|U7?2NQ)Ibvz*;x0y!Z4|GEnR>3w z+V7&Z8SyuZ$qZ4DBbEb>l=y@z-;|WL&E_}tULXI4^;`5nDO2bR{{b4Xpd#Esm=1!# z5mO@)gaNK*4-;dD#b18-Bn+^@6=^&3z@WQQn`#N8}DSB~YVQuu3O7bkOD6=S?__FQXJEjnY$@AAZC`!Vic-K6DU}w3GW$ z!IJGIHi93?bT#epqW(1?OZU zYVMOYIzfTRXDiD4pIpNKNTx{1n`C}r`u_SXJxBFXV=~W_G%e-SlZNa2ha0OQc**Hv z$Q`DF+s7xRot(@TkJr=Z=go>#FR&~`?_w7yT0$?v#%7{QU(upAUsvq6;_U22uwp_5~5>k>*x*0(hPi! z);rPl-XT3pcuKJ4MbUdTqp!BGOtajkH#p|9bLk68#~5?j4|*ki{Y z!iBH68edBlzOb2dB!1hb_TYY;Ni7(BloSYjiykP)9)s*{%_>e`d;wi`u;1t7a8XL@ zIj|5$#9O`|O8b6zOebKU`r$UKh)wFhxs|G1j+_W_TCf~HtNlD zDi-XQs7uo6OzRe$yXtYWEKvVo5RQ(*ft``Or7DQ)&*wt1-5+2E8Bq?WL{C_;VM|lD ztz9<#EnVnx&~3A7hb*veIer@+{*8wp)@yhFv|P_reBNuQm4hN)Ok~^eiGn7M9sviH zJ!Ry47MSTCk$ykn{#|yTku?%?MO)m8$@q5h~`7v0SqrU`ZH6^xa@Y zqEpZ#I0SP=<04;*A@mBj5`l8z8)k3E2R#CCYS2Uk>W|unNkBO24`+-i@3w%s-4#)l z4=Yd`jTfjr7*wiC7Ev#61dC4Gw4g98*epaTpYWj4jL>qMe20S03lrH9o#IfFQ(|pJ z{Wo7&MK3%`k9`ZerD6FEJ%4b01#084r!plx5gd_D1I|px?^&TjRDFN;`7ZzKYXkuxPGxHWbw-Dd~>)WcM05$(Fbll*A8EH40@*~pd6kXTh zEP(eoUw&Wn`ug~0>GAY(cD|PJt;&TmhFJ%WW+3dQRBp;rg{sM{0xc)IzO!N7(t#nU++a4_|h6pgIh5Fhqzr zLa3B$$nYcRg^~C%L|Su`8=E5_p=l{ZY1r)m7jN0$_62yAYt?E=yJPsaWV>ktO2N){ zV!mpLOJsy#Z)CYT>NwQl+iQWh=sAX9`R=_{E(Y{OcIfD!IYjf#$uu)|IJ8kL-}0BIKI7mto(~T*p{-WEOr9k zQXXd}?{eP>MLYn6z&-#mk9BDMy&o9TN}vTJ8&RZ{S1_Dvc3(Vw)PVAST(=GJT^F8K zL=@B>)?p^gZh*S*z5Z7#aQLtI=ZJh7ajvk`BIWo`q0-9qSV=9QAcS>4 ze;2!nLyu?e7yw=I_&*XoHrc+vy|;UWny_d&?E{bjbubK)91~b5!V2>zG#p225BLO% zPd_gD$zqtWWM8J_ib2eF@G0WV$*4h%Pdd`|aBZX>nR^-nl>*Y%lx z!g59}v$NYHu;$!yQ=`GqAqH%F4?uvJq2R#LHH~>+1*3fY5Zzi<$=KCzDJE{hhu?rf z4&q6dAi@ZW4%hwq#Zd@q1@Xo@#P0Nh4xTRZWM#FTQ1rcu+BX+bnM_@cMD$W|;R?G3 za|#XxsqNBdZQD(I8rv!2aYh4w3ijBw1U2hN>AJB`!iod@a%r=pFxn*uXvHJ(W2X=P ze!0+BcUSIj{^}34lbskV^Qp82$|My2+3!4}{Y2i!aKNEBd(mI$uoB09H_Nos4!Y|% z$%o1Epu2rIrK9BwoGET{GuJWgP`b2l)WoXEq}%|g@-(> zPS;U^q>Rf&i8w7Snd&P}!%Qt$`qf}Vl+uAwe}8`Ck7Kg!)5;m|>(=e_>-pz{G3m>} zRXGR-ISjq$I3+00Gx>5ftu2V6jigQoy~6-ezRZlgz6<7`JD*M+DZ@Fszbu9Ay3%h9 z7ev{Bpa>pEn~>l$D`Kd?k~1{-U@!cF3JtjTGNwZt#`K-tWR3MIp3Iz-c32!Pub)vN zn|$(!T(BmTp2yr7c)<0KELVA^!!!XCwNdMex^5hz6oiK1t=+Fm9o_Az778RvV3iRV z*d>X6I%^6SPVljk_$HOQZ=c~X2b_B-8y2V}RH>Nu8m{^1(n7dX7o=B}fpqlqh`52z z+`v99x+y2q6q4aP>ll3dC0m;3a zH1FB^ho|n#?PF2pNMch{n}0;(4Ib_OG-TEB38JE&5Lv=XN=kyyD z!!g-cm^`Vb#3*b0AGr0s*n&3oOxa-X7-Zvj^Qjqh;G)AZy^7fkeQvS@ZjY|dr?i7C z1B}}%zk3N>?fy8@)-gcE3EmVMu;E{!)y~BZlZf3f1*0rLN9c&h12TeK&o}#jEL{a# zRBgAWV+e;1L0}lVyL;$P>F(|jk?xR&p`;t6krL@fy1N@CL_pvS?|1f3Sl3$5UU3KM z4(3;Gu0~~Cp6VZ@vOn=S56S3ud@WN zlcUf=Zg%~1cR5N#DN=B{cX=+cQ74d*maejwZVjWaEfk~Gj=o_wi397D3_3P9p^s3F zv$mxbxn|1!QhwW>CH5s;q;eDl?z~urA`X2WKR}ut9H{N8QSBN_1Hr?VSp4W6{oqNJuftjnu`@oJCwkOfcA}-wXbowcmc(+^E{z{PQUq zs>P-SN07--2nZQA5x-!oC()!*!VQ;7O#a>c$8db*qcdHOo#cRab!n|uGOnanmi0T) z9x-XnynWq`<%4(i5pl)NV-kJ5sZpf8jB-ZYO9c=v$q2cty!Y3jbidj4CdWtlN~QRv znLNmQZr;411i!2?m8GmrPQF{e^pbkg;~pA`7|^f41eomFn2&$0Q&WN>0um6(2bq{P zjh#)9qy};a($^{NQ?cZftPbfv=lsKiF!vs3uVls^siDLIakO42?9W0zq+ySK zj3>41NamEIfjutUwzP$dx9fku{5M_j|3UF+8D8~0jyOm7Ccgizm{IkCw&!A7Lf|yO z)#~cNFkD}|(CA{5a#nUVhx>ED6X5CMF)Q7v#+y5x?2wWw>46_x%7jMl zw@I;+i){trs#y7-5L-0KJ;mN|qT)D&*+GT1Y}R-2DH~|-6iL)-kN$jT_~4k@>6$k1 znR&Z}CE7P{XWPkkvC6mffZ0Q1&6Sh-;w3Z|BR548VZK(F5((4#4H6Wrj;aWtgd0Ws zX6y6N-Yr^ct(Wqkg|rsLo5Q$u0H=^D$GD5un|f|Hqjt0BW2uCzE`SqRGOaJaj}%fe zZf3aQ7h7;r5t@c9f%%#}CqX#DL$J5UwU?$41_O@&)pfZ@y}9&mq=;-*6P`pKe<^cA z3^Th@V_9rm*1SU{B{jl-$uCbzyQf_R&uJgydhX6+ZfslUD#B`$xv9qetDWSq4;};> z^{J6baiP!oDYq&!!sx9Vu1xxRRJ8@VUuq}g+_HRWPTLHqN^_#THx~|oo-h@*Q;MV? zJ(^9IKQf=JEErQZE6RP2e!m4!bwBGvqf8%vd%J#Dm{gpQ`NU^aB0{6uD*DpylJ#iB zTaR72+xQ)kBVfa9Jhz;E@{oLkVJ_onay(9>p6&6UIE#tM=IPVj(8kNp<(ixf%U0eM zxeM13GCi=ixucn+ZbONpH~(DjUlOdXK?^1-z+CdThSAOt`*~yPW>f>Hant@u?s{8z zDe+1LV}3mc;8!?m*=yi_2La_VV$W!>L)f_41wye+4HNkodg#?Lx6X~&Nclv$bVxW* zi7P~mFDnYWRs8A97pY1ze#z$&PW@n#QUb6WCbDvGnd5*$#2K7acYdmrI6kd+l!q%C zIDupEEzzQqk|aB;kt`Vtn@sx==!(Qm>;7GC*fOUcB)mthm12q7MD4PzC!T% zfx=waL&%Z(3^?Nrep|`bF>=7BXq>@6O|zf!El~B}%74M4>w_>Q6W!U7SJnr<;aXx& z@}{y;r1nes6ctr0TjRkMIf%V`t{TIT(HW!v_44U#C1XWr1S!8j;+yzvkEM(r^=~C^ zTCQ;G_!%k#I^Wdh+2CEl;EJn5GCe2hNK&ZQa1NP}g<$3SiA5nF)@;+&A9HesiY(VX zPFDN^=^a}JJ6=l*ivN10ARO1%0e5ngk^a|HI@XcC(VAy@WZ?L7FLG}%;pWitSn_^V z=FH~w&%=s)J^Mq-?guja=jXGPvH-_q?$ju)IR2o-dSGmr9`X!3J&S;h_>2LlMR9vd zx!$l>N#C|-Cd89)j`(O>wXErMG~|>rrkDkqS32Z2;ae;@!hyJrL6yay`KP_@Uej>< zAc08NJW7xO5toS;C``oK<;(KP@(@zDnF8^Y9Zb_W zIo4dDe8JLJYZy!VwbRB?{{mZexWHe7IAG(3m0fv%8Pg1^UYg-wEOnpZx-L;bO-|Eu zE~})>VBg(7T)B~kqw`*zX9dMvHM%> zg834K>Co7{!d|ln28R(p|L@Vp;e_={3B(h|w)tJyt}2ZA2o*MHSnf=h8*ArKhl3hQ zvtEQ?aRh2~HUvbq;DU0036;zpQ(#Fl18+A|$J+F)&$R$32eQv=b z`5uJ{g`sS z=b07jK;1D;pi#}i7r*2CcRb+!2eHRTAI8#iM{w~jivd3hJldE)D;47yi(iEJi88#B zb6I?24d>IUaP{y&S!ojY9z~|G{aiZ5s0hD5fp@yF)TdMi5=Js}sBhT#pu^3fn!Tct8H z))vKEqztbmbQlC2iF`$-ZvQ2BhncR?fIeVO8>MOfUW*)2<+;+E%O$J$I*>0Hr=!!7 z0%-q`!fgc7On!h;%oHNv6a0Tgwxp6B6g*YWqyYtQr&?eZMk>f;L z%gv<_dWL+Rin1PF#ArLoe@h}-UT`hzup+1?|FCh9x1*t(Y z%H&uqlyPPHva4LSbr=C~yfU|?29&flUtjeVu1zysTp~oA3)K}k-KRIv;g8vAdVB`} zMvtgt_K%jQM3j#kw;?LFuKWry&YwvS_hn8s&-yB~d~u+i+@A~y z!^9oFf-h1G4z6&I%Sghl(CTp(WBYc*f;dPh!NpXs`|dF913mfeIjsr4^RjiQYo&i% z?tj?>2aJw=C8IDB=KqHEJxf2e@XgTo)!K;|5bzE#T{*-@Zvqzira3Y1ZJCRJ4U9uW zLa8TG%CRWFLBEqXFjB%FDy!*pkwJ^jG(BI!Uw$zi(VG=(e%haD!S0f|JUHK+sLTwk zu5T)mNFW6G*A`n!%sjU3KNu<5Cu?;LQHr76ol1f6GxtIPuURQe9I6(l9ajhA0i;?-Bh&ep8!>0ofu6_9$ zIM|wXB=QxHc)~@^9ss+IjVN6?8h8)6*Mi)hTUvuAZc(_-UR?IUS3{zi%D=9nQm~DN>n9m+{FrmXR*5=mRMe6 z290BGnj_38O#?(rg>kjGs3R(9=(oOHRP|&YZ~lNv)@m+tsSvd=aA-=T1g24(l&29U zYZMA)qrK8G=BDf_6maSzx{D>ht-t0jdo09ouwNUKNBi`ug9CmSTIc za$yvT1}Fv0non>}qXajrED7QnaMD40fb_nV)ev6ko7GyMG~tH-#>@({8gNH1VQQ%7 z2Dm;POcS(*7TXtIi*n0odw)&+cVfe8vp2~#xxtTjPN0W%nrgEiOp@1>uRJu5ILNqs&a14_8h}AU?^Ww`wA6FEX=Ri_$eK#rGR}Ag8{0|7obz#%& z4~#qJ7F(4+<>jO4cWaVE)u3Hp)Y2q47}bV`vuT5&K+~x-ExqhG#_}N3>+qFTP7|V% zeIZ55FllNI;q)d>L9%1zOR=z%4uJ%>Kcqg4L7=9I+?(iUmrQCsNg>!_5Uk#xz%xjVJ&pK*3dHQI zVs&hH48{JaR(9b+U|z$gCNbMvW9>;3j;M5ze?4^&mdbH|DSV1?RhOOX`=s#6N$ipbx?rqO#e3#>ZV76X3brU&HUsP> zGF?Br8Nwgf7ieh2SsfV&Lb%M-(_C>1hv@;07eTdyu6i|)VTE#fpT+;+Fn@w@qkCX; zng;;P$^JU5`s4MN_A_>K(I`~(MXrCjUwg?_IvmUu0W656*8hkT75GVsf{pLcB-#A* zrgj6y!psbyv4v9ud|^E18;l^Qq*ou-1t5TVHhyv8slEBM(u0mat7D5=9grC0iJ)Rc zdTf2+yhu}jzs-7qBJQZbm@qSOE(a_!qx*E3R;DL;5T8t;7l{UU!yjX66&_>_Pi;fx zQDQ)Vmb8VEFN~IhPs(i;{$1U--a_ml(8u}2Y(;Jq4iO<-hODkllCorfKyp72l}MEF zu0)eN(k%U%N*Pmdt_3tr5Vvh>Lz0sVHByr< z9o-@VX`PI+2Omp-ZDojwPTP;)Gqt}|#Y%!VmTFO?_`;;fAmwTPYY?u3-VC?B;t_W! zxnEsdEWg#~N0X1p*0s7s(Vf=@2SyStc+dK9q6k>(zk0EDQI@Kikz0Y-tNw76 zPtSr!V`;ZVLz)djbDqN+m%lN^-7^a=wi=`*U~=)LSrIc90>8dJM{sX`)4Yni74nk6 z_C3+}PebxJZHjo1&0fH@wCWXnl^7AietJS6cHSxtEjI#UNpM2nx~&9pFtX#ZR!ZH?I8cR%RI#E6iTaf~<1XO)s1q@u9U@p^UHh zKpjQmr^cec1%gtJfbYIieAN5vr$ zfwfgSKJ2#hZ6*hz^M(v|p5JncE)7+Da{>Aw7T7^+bTyo?R;D-{1Kpa{jw_q?m&ek9~ zLYz5Dd1s{}E-#{PN4r~CL9-MXGiqm_P@W1op7tkSV|IlR9!R@%UqIMaJF{H>dw|Md zf43aX83vo;7qXGzzb3AJ_)cXxQ2gQk1IdObrZtnNxnj0xJ5qxDf>sEiE&Y|DrP0xV!D5S;?$36OWujWDJMX33v;!CMmDnfm*2}>+A_`iVRrH zMfUV5WF2-yKJ#9mBQ^A-Z+R6<@P`|czgZp=?{k&O7k%q~4ct8(j`-oL4r2^&-S2=< z?9Mowu?*9KXnP8oqaaZY?;<`=%a4_N7#^mpj6Z)YL+|#ub#mvQBIC-#mTPZhz$7bb&xh7iELh?oCZtH07-AZ&wSq?6I@}lB4Bz3^&&%(b#4aX z9rKw&F=oDje;R(Yk(QB3Cw;f#y$Q&r)vn1g=bC0#N?6L}XB#vdt1UahBvKH|h{OP6 zCrxhSGG>{WYP_SBFK=;VwniYpy5oaYmjA!a_KeeqmzT@H){cvcY&`=znmE_D#Dwxz z8E7*2Zh7pW9qOxFC2V>xaPxzmy6!3JMo_yH0ykV!GASCp1@I!Ax-!)6$(sc^FBWGx z`i`gk`~KWO2Tz~qydqD1uB)@r1sNJRQzBT35xl&m1$uq2Uf_TwMV}8dJ1jD)j3jiKxM$%(g8 z6?2cQBtQSuYr-ntY;8-=3$kcxjjDHJ7M+FSXZuB^6>R6Kh&t-_Y1Zl-(42-Hr zV%SqEkV56^Q6s>FsG?68+YvSljQkZy`SA%aapjXG79|RLhy#&1Z6;EJE`WcGvcf6_ zC^w_peSA4F)|KX9=~O5g!;T+40vhW<1v0d=KrD>WsNM8U6Rql`BGlo~NEPLc9dR>g zbT}n!6+z4X}s{qldq;n-fjayLeCvS1@h7TR5v z&z;WPm(yTq9%>Rw+4Cn_yz}QqIV&;Er%!TF9^UUJw;mat$MGrN$3rC;l;lTk{O9gz zYpV|<5k}x>e7T4zJYNTtDI}$+DrIbmP@R&C%7(Js9p}?zp*OMye+h%FF}g}5!wPoe z)3PcLS`mMH%Ub6uKqkAi)6F~w>tqE>vtfT|t2Kk8M%5E8O`%%IL1Z&~WP&utVH>VW z>t>moWk}r9qgQ;+b=-pHQkie{;abAYB1Fl|L!kh1-pL%>?6bX4xA%#8hO&hdrTJRj zE}d;YdMP|Yf=a%07WFBu8IQ5GqD>g&lmM>4t%FKEmO(TgF8zIdidOx)M(d4vO+QNeEcF6KD3b+5gW3@|1d zo{Bn*>T=%q_nX z;QPhT2pJ}P6YXFS!_?;B=ikb!^E^uNfjChOOD0hotYp(}#Y|7I$5mfd+-F5bWvkMx zT}VYJKZB`oUQw9Q*C{}xOj;&4eowSb+DS#(`lJ1lTne4(B)pwq|t;p{aT;p`$QJkzMjg zHL~Q|^%-X0%vitjnR-F=M@Brn-sxl?Gfp3@dFs{-QN+smroiDnzEW+F!PFDRP0 zlHlD@At02Whg-YXgAk6HIX5(Ix1gZ(A3FujfN@)KOmnH=PJGJn=--@4k+ibC0&&-% zO5zx$<6)O;8exXe$+3F3AH^^nCvSzu;Y|uDiAmC_$B!FI)zvmx5bM<4sb$ z7e`PnRG2V-YHN?->RRVHg(x$-3o%f&E!MmS4(9X%C4!;v-2j|qu3e$nb~?+St_nA) z8eceSJX&MLG)iO>-**IkmcTHd=Bj0}`MJvTh_gZ0J9qs-wVwZd2}&M0+f(Zw*aBc} z)JM+{rgJq;!g-o8??=UQ z`(~G0ltg14IRvsZb&2JmX>f4ZxYMdrvWS;MqoUyEsX{Vo#>}Kg>_vs+ z*OhIyRZh!T%Q~M1ttn;fI*M6xm5*>0&mk~c2H z#CJ&KrDovcW%x47a)8RCPh|kgxL9KJsy1K9-;VDQT5Kh7g6x=A^V~}ErlwnHVT*tW zO>>~jOm91;irf;lO1Q|;0CT_o(uc$3sVGDceSe5Vm2P;VgaHFDWrT!5c9OGoP{DrY zJl0GBbx;cl08G0y$Kg?c5zG6BI#R1XMx;^n`_dDSr2PDs9&4lOM>>LDv&e z8ya}IiQcGnBxC)+Ak$@Z^V=8ii*czux0WQzpsXwDuu4RDiv~|sOtADD{qtrDN47Q2 z+s-Aa#VrL}rGK4g5tB-1yW3*P(z7rm2uubHMq7x4?WZU0g$vnVnTlSsEa+vS(vI@x zXVzAPa?_5O8gbExGvAUebyHKX&9$6nK`J5amU*oaU|Tz4uTDWdJeCJ&m&v}U>K`}$ zpO-tR`U+1kPTe1TR_|%fCoZ!yOuTBqpT#BALP$}-t?_t+;#LAqGZm?w$*GTa=jcOr zwU9?wS|Cb=uKHjiR*G_=uKA?!+Kgcyo=YE2#UH^`&5~2}5v{sX8VoBY*N@)nL~efI z{hypHu{NC-et)PqUsN&c3PSOlj%H%~hgc945D(X`EPtP=DIcH{WhBX53}VU#J{=fZ z+*4D+6-4laCZ6V#utu~C-+)CgV&JLV_X*UwSgAKR|RL5@|I9hhzG%BsA$Y!3)j>17wikIynG(+wMAiFoXdr(q)78asm_l8I5)+rUxSD z0Q7hap!o%apTZE)q$(3?sX@x6S^^Qeb2_D!vrecktEbSM~RB;<%#%!@w@Hc zBtYtSw{dW*!Pkkq?!dh6z}t=1&9l?2a?d|mEEQhs; zfxvb0E7d?IO|toWfMY9&nK?JK!ioifdr#2BI6$w4X?ADUt0m2ostSDLZ2sfq-EH@f z?*%krLC^+UvnL}&k87U^7t7_`!dU%Cm$@Y z8mJQ6dyDh@95k69IOM>=U^L+H)(X{94Rli{i-=0Yc$B-db~53g4>o)bp(dean9^2A zi3WA&`E&@T24aGD){ODYjCH_S`SO_jL~Mm4Wz3m%Mx1Vt*TNh`A*L)7i<5`=PxKFR zajrTPHem_r68*QIV~9jA&leOMWOf~sMb}G0TGKfN!dk8Sw+o4gD&Ow)1eAx&^{2Tz;*_X)?v0L@`RA_W z9yR#ad^SVG3gHb$PuAam4cuc8o>zRpIn1U41g(SdJ(4O8b4Sqb_fM%lKH;@z2Z|I= zeeMI~n5D*)%lNvQM*S{!z-Ha;<0iTx!Fu|#x&H65E!@DMrdYDaoL&h#2@RKlJXs4u z5LFO^J!1#bK}5vyRTeSJaFu_Y=5Ef zIY{|#ET3evsB6{7#Rp?I{?}yI!0ZIUF54&6uiipu^~>;8BA6)DFslgiIn$mI=r^1QQFqL*qbg0W2%SSEXc zH@+8AM8(WD?sexrJPG?^+TD+rhc8_xxt9)W|6JG>IPx^u7Q_E}iT*Co>W4!iCA=C}8y0JBj8{fxx9kX{$ENb%hr}EwzJU*R0YhIk( z*bi4&jp;4DPchPkxPmY6iYJw9X7u*T}x z8MC>nwFxUa)gaC!Y%}4fE`EWas)iDX3QyTw?GepZBh{T2rCOt@1^)Z(#y>I92Zn)Xv-Vy z;ADtA{5Eq?e$5`3FiQV)_*va}3}OyU4gH-({o#a+lcZWMFGpXK^uZpA#Vn+qp5c7y8dbXMFTHl6R0Jja)_X!#^U>5@(~XP* zCl`8aBMpX~uh|0|aHC;1%ETU$Z);wWYd0rvpPs0y9M-bU~^?; zeCZwWoCt7DEKq z=blPLxzgdGE)lf$N1zfENe9z1Zg$FWQ<)xu0x?zVjcyBCG0Wt)4RgCfN~fYc(SG>z z{;{nK2fJl>1rnT|&qb}`Cx<4S`p0QFtRQx$&&P$rfaUf`RP&8a*uW0FY-&K|kBZ^s zbpZ~2RgzVjX&cm3Tvp9$#w?Ql_eM5qk&?vm8?2A@WO@UPZL|<$1wFTcq3JQ^#{4`| zUyYGq3)hC%?74>nqKmyAFU_t>Il4jtU`F@737X?~a%YXZvpmKu{%H|E(<(Ivy>- zbc0UPjn`(_lRQEo%n9?mVBW%s2M>DLS*;vT-7+ePE&GPm+bxV%`*)u*C_VK$f|ovF zBpp`xXD-;=FbmrLS;Sj?SgtU%#1wt_<@cz2R zD%D0i;P9hkfpSFitPQ8#ZHjR2)4i6Hh8L)3wJBnVk$uh4Lb|{ECi|0_$xKyRfA5+A z|Elk$*qo-Sc}AyTYjI5e?%*@(+{7}xxV#*2q`ql$+QEA-H23APqmi@XIjcdzRN4k1 zm|7bO`)m1Vf6!t^DC3jAhoh|;V+>C=Jj;|5I0*5m90Y41DYva!5+r$A6A6`!L?+Lz z7#o+sNH4Da`$2CEXOmzh#E8uB`WLz>=T8C696IqU+Pf_l)sHj1Y!@>ziHe9lj1U@x{^Dh7eXeAeuSwH__&;We|>D z0W;oG=dwirI5J;ImHPRYez;Pp$1c+GHxJ1IKJi8Nu5s<;xCA3o+uez4a(+jKHJKTF zyAz&>#C6F}Hpn&d-jE~;Tthy|;bSOu-*)N8tEcB7E}!|GdafzS3M}*mA~=k+x9kB$ z7XiGBpU*EYE}meZj`IfY5I{v_SP0kvBoNTsZ)n#LV|TJrEkplityYhcw925g^mCA|mUyUpSiS7Uj9E}tJB*mCVgHHDV$r>yl7>7e#Da<0lb3d4gP zBm?b8ZJ~BZ^MkTnf{2}8KLqaGthN-(3-YlqS&vx+zC7l>WOD$LTc+VKfjA5e?8e&| zKPXWVS>fFW#BtGuHQIticJCdP3FnCq=RI$ophX#qN&MGQsH&T!iu6UlR@vPPKjHkR z&;Ud1OBlgQ$U~C2=yhVxH{AQS%ih|xlDsIx_QF@)#YF+I0AJ&p%E9}8=Be>D9XI2Z zBrC|4HY}T}5X!^V7fi(kpBkrFqlXiNxwja#=4pj8kw1nKai zdc$MLAaImp7lTH!EW-oQ2}nP#w+s7@u|Pm_X|8K+0Kb-L1oK7R3aDDjyu(iBtL2(Q zHATuov{ZW5Uxf|{h-7(XHB6~xup9AvXEt--CscQ02tY<7hclOIc4`&t{JOiivo1i{*-%-W`4=R@{1Dg65xgrWDEJ z-MiR@3|;!5NNR>JV7W?a#@JR*J>IxaM;=%i$N!X~jZmJA@W7{h?pz8jsu(S>GxqBP zj6+WT$`-1mCaw!eCn-;VyFG2f(yVmXXq3(C8LJ>#Zh7s0$^^w{R8@FtP9PUz`8W6c zMcZL=EiZNTKu0KP)V7`t+Sp|;sqy5Z?KSbU!%tiGtsMe2t$0>UT5*WY*7iFjwx)Zw z86?YdmW;1D2qnzX(ugsr8{ypiW;xlm*_O<{5Dl(XWjjA}02LIDo>F}34maOMYLR3} zz2AsbR%C9i>)W8Mqcl0HxcEu&(s;L^#vzn&;0rHK)+3&0FSR;%Dck?n_Cy2 zrDJ=W?=3!@JxOX~edz)N`QH#;SQ&TJE$u+!tU(gWkUVA6$`s;nqXdMq+*7izZ_g3T z`Z4K&aa3tnEH&Xzyl)`KGRg3KdIl2saX%ylIKla*;r7Ty)F ztRbpQDM!q~O$pcCf2~+5K=eXZ?3$-p%MvJ!C(&b?iqxW`E12TZltG^{l!w<~*Z15( z&Wmehs%HK6dtbxobHwYN;Q> zWrgDhhM1;8bQ$|0C8Mzwv=Nh`c#aA2m~eBX5aRWMrJHuic23<90(5mxDUH{_odn@R zzrsvTTqK!6t^pBLNijx*@I08fG@LN`+DS7b?-e6=RNxwj1apDJ^s3G3;>n;<7i~gb zih(IvZlKka3zEN<9&f&+`=h|Fi9U`(e!u#6y+&mwXZZJ@F9n^QUot%8^uciW#BJMe z5O}6oerUVS0E9=AgrP;_{T9Dg5xL>z6(FZ>%<+e^Ic8XIX_h7I6iB@|y=kf%I)9x} zYL#9TM1NV2ipZ}JAMF5Tkzl-+H`5lA)_~&BkbhXPB0lh}T;S{Cqbce1K<;}OphH$s zaQ{@H+K?ls&Va`)Yrn4$XGb-Hykrpub&|a)wt7AvtBh7Oa4S~IP@#cWsA7t1mlC=+tgHb!~y>eIQPvcYPDB1Vu}V0Bv%1g@TWChGQFW98#^0Suv`8sdgRTw z#aC}3dm#9A)uDDQT|eABKJfM&Nrn5u;x^NBU=3UzfyNN^wyjrp8i4CHzWuA9%q&mY z>z7nQ9_CMmz5WqIblb#eK-ehzK(8lSOIE$J_OSEz=-JEqN|cLZeSdg_jzlq74L(90 zA|6az{(}&-BezeaDK0*o!!0T=3i-~dKVP0L%Jm^GZFKGGlxOn-QAy6!bdzxR$F&R> zQhyu*Zt~DF6g`>q*1~}6*(Sv)B4)2qU0#8TH(1G6Q`$U&>2R%tb@f2@W0x4zW=xfB z6NO*Z6m||0vY+jE^wR{k!wC8q_;$>H89)o{rAOefuMsHN&#kiY&E5qIzADV$bPXE% zR^?}BDHusw51o(4ua>g(1>*j34E=J*pC%?U^sT@6@t78XF&rbZKd)jh1O3{Snj)M!iFWU7qbbb-N+-_0zbeeZ*0izIKyxgsi4Xq5W*vl!5{A=zR zF`^`?Ea$Md%uU!~x4@B3&)%PQ$tBvg1jB3*0WuiZr2IqJm%=Lsp;ULShcA+js@6|^OZ zN%DF{*#;15J~*U$o*6LIN)?7n4)z931K)azUAhxIY;-h-%ab|bswP{;(Ic@Fq^V~U z%Ta3N2s@ZTXXq^|j6blhj%{8ec&(Ii4$g)vYA`Yf^OO$ML|FjrmGl(KH>w*nn{p`( z3{aj_Jm0l8qI{BZvoBf9>JqlH&=F3X?5*`6pR_5;6_CkUH8bE_YaW1v7ET%8(_xJZn-2mUYOAe9Sh`I$K~|f#eNgp_w3*OHwJoD}-D%gsrQY zKeiIj)CoA`j?}yvq+H6W`4d@}pR!(^nk9F{_st_w8TpP6Ywb0Au3(G(Wmph?0*LE4 zU~^hsiVDn)Ju1dv)S-#h;Y7z?Fq*r=xtbVg>&=-PSdi%;ici6%Wggc zG2-vR4yY7u_gy?G7E0=jj0STPI=`tiL#UCIIaWqEHJ3fpSBYxb0dd6Sm=PK{h1mG1 zX}Ya3H2O|tDucFI<;v0scyA=D%Okaw4=w6*%X_MrGk385D?2#c+?r6>YIanHfxRmQ zyPOK)ZP>}d`vUAXgn;)fk5!F};vdrXe4;`(t-)+90hB*BId-gwKWdTGKx?g^SAVu; z#e?IUVzsbwgV6f(c9gRu6;0)T2QmIp+Asfg1o%RDlYoVa?2RhBJI|y_8prRZfE})b zhvjEpnYh#cYinEWExIUzEDEgxCY{zAaTpI$WtaUvhrB$`h^+~gs43SG8Id@V%D21-(yjF&3OtxWB?V?v`Kfvoc~`|`Nl27Fjr zrc5`>hziQH9)O38Bg9}AeH>2~AX;8o`nZhroq9YjD=}e9T>RQux`K;&SU)RExX#wg z@KaJx)yfHNJwtJwl$35dhnbeQ6zE_#*(%tiLwRD|$oDk}FxU+V%tVgevFE6q6ZW^$ z(%R&tyKc9FeEfM`wlCFm_#y9Hr(K5Za3pi!`Q>pn%E?j=X8)o~^-1lV8vy@<5(i8S z*T}??NZsIv*JG|Hkp!1Fia`(wDk|CMdmribVJ00)xgP#4%6odQhvD~5|A!S3TKe7I zxzsk>sQ$S~o{?l5`sOz(=~y@(B!t6C2s|haVtu}}SH^FQ-G5aaFg+6szyBl-h>hP0 zgk2nA-}7Vl_lw+>Q))Z#4K@ff-ItYex3X?KJ5!f&d_|afB8&GYH?IaGUINv({+G(f z_XG6}DWLgZ1Ph8)jbx+!?RQm9D?epTY*^khF1O4qyq3@j9B@73waGNwNQc=8#_#{E z?SX$wWgDmaaYM*(5+S-b5^58*t5li$TFuiWM109C z0cQ7Fa(4c_TH$0Fmn?23Pb-=xjz~4qLt24G+7pmGz2}zbMzJNmuuz!HP!2GEm!=&l zl#1e)L1c~Y&wR#+MPDjfS`Tfq{?|L!=-P-U3V{46vV4?GiKRh;6cW!{D!Ug<$c3NZ z#_Z2C-}%aJIuFe6P)1`_P>qH&5Nb6M>gjCU|6xJsp_uH|NJrVy~x^OeZbsh)#FRa<=OYjbOR=4I0OVLst+^3)-b&Q zaVbo^>MT|yYtH##OgVWm+_3A@rr>Os`SILjv(-;eca-r*w!iz zu6IV+j->E-MfxC4labE*%rC`8v{yon0(mONUP%+)Tvx4K%9&BXx-_72e0&XUo-GyQ zu-ezt7vq;ZFQ?AHLQCAD0@DaILiS*^pwNL7$DTxEbl;1iRWqQmF9`t!Bd_R?C^X<|Pe;DaY38Ka^&+9z1zH;iN)ee_ z;yY2o!igH4-0_>%_bM9yzUPXP&pZ<3w%q3m+g;o1DH*yYeAR+<4V-)L@3ktI{M$IM zig0p_FCCNMW~4nxG>2pEy&1?)xS`$v`tslP}&+ZA?t8 z1xEo=Fk%tH6)1pTz=`;xu7WFT%F$mO#F8)nO|+FMzLkTM!p<(I#3)f31U9S5!B9&R z*74J(I)C4>z9|Tm8s2`>qI&xNB#YSZAbzgB?ioC}zKbzIw zG#e61l|hOIO>^&f;;u9A{l}?Ir8rSY1PQ9`;GzZT;wVCY#gk>`e2$yOV!ma?=|G#B znitaiQp4zd|Mb(tmKC};P+)wY%QvR2AtIkgk$d>E*6ruK-7B+czYu?_@7UnpcK|b< zeR*^fTqOY)jtZ2vp=((BDdgCp5%y6Q1l7}2o0#$vCryTOuvSy7MR|L#R5r4-`Wk6~ zqN8v$;ZiN!jpMa?kSrqaj9~&Gl^)?(@umS!_CeD2vNrW`A}8!r7bj4%#H18VInlaLn0JLs>T!H2W`VJy!PfRX3ay1r|<@)ywPH{xXD|Ki{0v`Ebi zP>1;u`EWX&v1)I_TsHoGJltPKru^^s4F}8(g)R2od#2N_U~f5RYM&DlOhl;bne4BIJIQqUB^4Gf@aV=->zipwyxgrO)cTFrM z0gqS;E~|=M$~?HPYL0(>F{#MxKy3ubOmgt1$ht%I5~?p>U+!8tt$ABG<>Aw)wMj^) z`{hoS)OzpvJg-b`%U2po{V&hdrvpqsFmaZ{yeJrDb5X!a{VL1jk~!0F=!E}((ml}( zY3gwex$}}~yq(j;c*3yw%D4N8UW4!lro$Ne>WUXaT2&7NG;rrE#xjv~j{fEWNr5d} ztF@iW3b>Z#HF^In_u|z#Dr6p}pdXB)!cFL}zC378Zg!4D`PU?shLh?S;l%3eX)S4M z(9~B}giJ4caB50m@l(1=Fpx31cw{tN)%BKtCS7$|$ zQW>Qg&I5J(KP!Kf3p5l#6M{*4{ilW2Mh6RmmpLxOE6>%Dw9g7}FACZ@l^2AlV$Tzc&$E$oq$I6pQhBaTTNQ+8lJv8{0shA}L?9dy&6;a*gy2V)XCMFfX!a-DgL=zu=09wO1E07k zu@+ z{a96z#pF+ZEmwKh1LpWS8(ldY@q77hs&*{P&_)TOKxQWnAqNAV^w_{-Fu-N#2*;Hr zO2W)%7L)z#_pjw0Aj!P08D?YMzch##_5aizMLDxM1uY)rKG#}15}~3&*GMO`HPEfj zg^tmabervPE>}PrHd%=%Zm@*U{g$1;$q${bT^ej}j7CW=3qG2E2)^08f4sbZIDa@8 z8cA=(1yA!ua$_rk$uRKp-r^QP$rl*J!&hHoh!h4`rN=_6s4Xh^;>ct*Bq`|1SzYFZ z_W7^KgmBqob>9)A+oSOYv}SNbBKGr#}6wuse7FY-=?vTX~y4$9Rs`=$`QsMJ2xJGZwIyrA5KpvbDUk`NTqSo z8%Z%FsL5=s9RS|i7uubhROvhFgYazvUo;GmYL$R`4Z_pF93VcD2I zx{R+JJymAR!q3!_!rk%r@0b;hK2v;dT~SN6T~psVT$4EInifBC!=$9w^vpH{Q55r% zHkp;i>uZiT871930#i;#!hG@3-S+#+Qj7C5M{*{W@YFc$424qeS~5G1hOK#eb}hr? z=R`f+fNWU8(wgGlSC2#{0ZS)L(HDzpi#gwvCA|sjj1O5d#8g-Xy=$_Vwm^)Y&j``t z%ZEvP^4#*rX}I@FMVZ~Px2%GlTmGBm!|N+SVu{@M{FA72Pgu)nXk_(nx)Yg zmS9In{#z$G3ls0HhE2ROq_6TJ=ou7yv zKSmFf1_&i~5G&z|W-vhC06D}d7tbyt>Z`G8rog7s#B<4(Q z-okv`^5ZoTi8AZ|=A{Oo<*hN*(!QDc;LFBa=dc$TNxARTx>NYP=T|35FppN^W$r&N zzS#mlU21afo316sE|%8VGh8+*&5KfDj94GRwwh4y+UKhXAMI(*v~;D1m_oq848o)< zt}LBrp&b6fi8>}r)ll8qeJ?3cOZ^jczMp@&R3NXFD&7lH_L_Q3EdKHvxN2q}VyCkE z>)?#iOP)}*nOIdMaR>ia&=rNAn^2&sFp9`2a}REk%uHGb?JD`HWnHMhz29&vY_sWk zz0`6?(rGT``*9;6|K#z+b0k_emA&M!+}>=*P>8o?tX0SA{&XTcMs-(>T(yks>NBVm z&6~RGIYp|37;BXiyCtl4*IzRE%G!rFPCq0f`4#-fE(borrsLa&70ol(44hqMkYT1h zyqn%BYdn@$sVg@o!J=E}1EHr4bho{i-%oe#*Ia%5(DLm!RdloSW6N1hVQX5k3^>iCnDHwJoe*5jE7a2e4zI#ItJi&r?}+|X5Y1@b2d8q#qiX>ekb4{z&G#yRYJ|&koYf^!u9ya*u;)2883*1tK@1i?U0da{>!G-{00@c z(2Vm*ajq@XDMpOW@xuJ1lXtM~Q#o`b<|794uXZAIml8XE-V)a#WDwWGUhUoWca{7> zl7;asg=e&ND<8N$$F^cm->5uZd_I@>vLA91;%2HU4oPc`W2r;KB?2ELQR|@<8z*xNkpkDbI^RM!5xDl@M{ zzSy?LzTgbG*|%Lf*}b3J7iW3YpFDRF2?0IMY<2oN?7;!(gJ3{LOlc-MW0w_}xCAGk zCQ!J>nuHF`jEOz=!O1oH*;+zaA~k&-Xgi55tPpz!1Phmrz(k}Qju!n&d(tvsBd=vR zP*u$$k$CR}OC!fK*ieOjG7kDnRlLPbE+wc$iTqhNrF~Q8#c@*ktSiM0lGA`Tl)K(b z_I2uLAD*SPrV_+qbFt~ME&Qa8KEj3l_R`FJH@~hEh%FUkK|}sE`xA}VWEqWTwhp{> zkDbaO-l_d4`ac@*F#tG%g_JG0D?hFOFK^7%f{ZX+D_WnR+CcFs^|BQ(a+bG(TAX8u zYB|0uhqHu5%>QbF-0S$GPm0y~D=7gk)A+0nU7c>tJdidwS$HVlk0pg2t0CV)rC`1QUbYBgzu}YsZd4 zo(OaVL0mk96yX?L_9v)uj)Yvj`MkO}EQ|~dkX_+I@5JEjA`%QN;fUjDgYgV5XjMYN zQyfJg2+p`Jx4*?wJ;(s&Cy~~9RpLn8HJw@To$WpJg>jF*z~PT-%E?V@*awI9`lZ?d z4;&{5*%K6ckV!9U^vH(MWtY1CKfOmHO(*ZTZXJO$&DT`=VtHUN5%39F>4ha8c|Q9< zzYHiAUS7{4RIkr}AO?MSc-)?Rd)5R=Gl55j*^m3-)2PM};ZXAL#Z3$;E`|aE1?iMa zspqnS7#d=>^we}4Vp)o96s2QAKs_37Uh#F-{V?6L{L~DzpOP%>FtfCq>1`2)=6ZyC z$Tp~Bl@NFsM3dHL zK*}Cl_Fj>Ykqwqxqw_W@KE*R({^6$aB+f}iSsx_P+TR|e&DIK68MbNp6JberP#}9? zs;P^*dyuy8nBS3f7*8uu4pK6eJ7*?Ff4&o;6u|-}q_&#Bm>ExcHCA_t+gaX5MU*^i6$oExabk?~ROJKgdSAo!Su1 z;hNF!zI;hP_^b>?nAF{@TuVpsMGM8V*UW zhriuaMmo5FiaV1bV72`Fr-EK)z@En7DOvmL-6@XGr|UvT) zPLZ;O|IBkmK4qXHa!8&a{qm^`1J@tl1diY3jBqNy{C%iNReU&28YdFSl7f)cgxY2gevBf zWC1S<{Kv3#=L;IYIw6kml((-P)GeWjP%Y0^t4Je%94=dm`2W;^;sA?!*X)czL z6`#Vw(xXr?>F1&t@Ue8Qho zJ%SF5rHM?J*V<*W!Hj9?!5y5?Y)A*5$jfJvkJ7c%<>o3)noNJL;LS#% z=MX^Z$&Z>fhtrp!4k6QLv|6-4U++~AvrNgfV7cc0U9`fvmtQ%j*{scY=-ScNOZ|N? zLyaN}^~1{EfqNwy!Yzt&*2~RJaz*F#v9Ed~zN_c_VS6$!B{(rXp$5d{giC2bmdEU1 zfmq_ohQMyU1b`IE6l~3!0eqO-omMK6_6NBjx;Cr#di30)0Tc8#mHv%mECGul51ktMsDG0f3_`V&P8Sap^Nd2?{O zrFL3olM0~0Ra8wHmnvk}e5W}P36^at^Y-7z!6}(;mFsHWIWCi-qapd)Pt-g`oVEPi z-f4YPvk2-)vPG_xtopV{%BO@Gp9V-lrf01#hH&nj&F1_AzKYAFc)}pVX9+~1=Q=cX zZwE!>L?_AQ?TpMFw?3sNs7s~zdPD~S(qqn0po?H%yxL2M+RPbUh>Or_3*O*Z_|iR< z=PPQH1c`~Yz;hj>!S1$K*Z)Za$zrlW`rc5=T6Dv?r+woU?QkGu4`pYuk+;?YON$Y5 z8~nRA6N-F^lI*nwv?8q57V0Iufwm{9KKNG69JG^j!of>XI`Y;k-j7))nZ^z+C&r}^ zAo&v6pR+RC5V5K>>LjrP$fM=M^yft+gXI46`DQ0F=_0K)ekOij1!7syXT zzPV~RsE~aRQ=Owsb;}|g&c)a@`eID$H@lA7s9fd0ba7VQLoL5TFq$-tT)1|*ta~O1 zsDwEf6%mfz`4?6iuFV_Y_oz2B-8+_L?g9^e>QO?7MUV-lk{$-{muKL=AfJws!LQ>6 z!LWPUt)lQIuTntsUx!1L_Zz;;HZ8jh<}=3>Oe4*y2!bMJl)M^{1 zU0`!nw$*vKWb*Dnb{f{jC^WP%84>yzIn{VH*?mVpP48}u%B5^xW4nZH``>JjcV0*I z*Yl(KzB1YbL|Kuz{s%y&Fn2vzuX?8nQ>jn>s?6j5Caf?j)g+=g?I6#|(SB8;ok_$J zLdwZ5M0eOkdvuM2cNBX507$=<#GFWs z<71bgRMHl?tiFrmOXeaa0R!)&<;XN(N$;K~rnMvT^OJrf?`6w7q-Na5v=AvibhfPe zNs5Keg^yoG?ZXh+9jrfO^u{#%j0fMBKF3E}5Wb|gu?K0Ej)Ukt(I4S|1HBfa@S-?k zrM0)u_6DubXNAJhG2NP~bR)?_!#klIX+I*EUcO8fRDxGLX5_cm9mmLRU~bvkB*B89 zQRt;Ljy2i>A}*PsL4Q&q5icBH9G#ind@&goTSvMbHmmnU;~ZPivJ(_~jzdXvE>ZKIQe0Nl zAuvTdj>0Vdu^~i^EGu)#WSZ4zxI=hauGTf@#eR{mC3=4ap!q*1Ou@P)Hu}@M8!Q}Z zh-8{PReRdxznSv*kg4$wQFp4DD$PPtYxIzx0QtL52%Rctu7S1b}oJiaDE8$&QoC3 zJia|z4q{8GswuMs8CCGOFu zxc&{UCm{XosSg)g8<5P5p7{5|Bn&p~JhF924#|8wUao>!ULBBSm;ZA|baeQ^5Z&zS z`meNe$K7ZJ11+u;v^P>U;@!W09X)k6hLCy>5yNE91uScblK}3At~3#v*@N@HNoSk@ z{k)nx&Ase%WsZlSR*Wo1TtBU|G1k3H?E2C?(GI7crMZ?u2?YRXCIQ})fp<($q7PFS7>q(>s~fh@+VAD-jZ#K#iF0@f zN%zIP^=DgX=+O0AW$Y=vq%Wmrm*%a$+iYnOg>?U|^I`3RRd8p&Z}`5Y&2@k=d2n(p zF|+48k)MCs)}{OJvCh!((OzB0PdAJog3*`@21@++_Fhx><#s-${{ zbTt_UCihTw?8vTDm*V)c)L1pkR9Jt#A2*MNR%@CrAdU1{_yh<3oDQxn*cENGB7k@C z>y@ii*sRZsKb*x?DPAUF?@gCW&?m3^B&w0dH40qqIUM2{HCJUO)ofTkd7~D;c5X%%lGG}-D|<#4(W+GZX=GqDn(K6l;!$6@|#~hi%PxY zf1x##Z_8!5Y*QY}Dak5MX2euPB5?qHvVc=M*gl%P&B5*$#Da;SHR3h-x_bXZm%li+ z@LN{<5I_Inu!c`s@H#E$k+$*0M;cmtV&!QSF-PaTQoX4foh-X4{~8b*J3b3mtnlNN zyZf2RP-_>fGy$POxC^Bw`-?v`WYX+R{@F}2468zhV&7oO^=_+422oIb$}hHsR&M#` zoU3i?KZc{PITdHFpHfsN4{8ZAP{&7SjycN4dyyTW4h}h_U)Mod5ITvLc?2VED)#u< z^1CI9?7ly}?8xll^1(7#96iiea$p7qZj|OJjO#ymPm2A!3;A%zc=oW}otsb}o306F z#&ZLzwj@-i01_Lk$wueC`Q$5a;X1Yka-YT5c9LZ`(hN?CCMeYHG6Bm+WedZ;gp{Un zmF{M#c-+c&@_vfb_aBRoPs#ET5@~^&js1(Rkniz=@Uuq0fy<|CD9U^c^3?n`62@ieo!rB6RCl1`yc6>a@g;*YtjeV9X+bkg zdRSOV7eg?<6?%1ytERgp!WLp$?AehT$SOGMP&b6RkOS zq<{(*JY{Y6y)GfdSm#guD*gK%%|o}Ngp4hs`5LPYF-qzM1(l|sMLN7R5S^wkjml=q`PO& z%J~5atOw@O?_@y>ewLA}*4eh>8&>71h1RD~_=hNFkO{f6gE2-Ezlfdus3P?k@ad|% ztENmLqjwZKE=DX$iye;+K&E#qHck=_T45y<=NP)*x83-@xgY+xQW3`@%UXl<0}BO& zrULP>u6XgPg>C88vwg-Kn_hlr$3H}s(0(Wo{ypkMVk#c;_CEnj_;`wCSB|zVaG|P( zF_*NJq&HrHZoM^gv{RXXg7S?$83MvzN^Q)kDtO+(k8kJC&^V-G^+_(|Mv=2cxp+Z# zm8f7+Fu1c|CTEo4Ut<@S0?aOaTFgcJe)41@*4d@Abz(4b?~aTbK-O!qH0()G9>>e! z>11wz_Qljb8cP<<@Llw#ywpc5N~`gm3rd8lOsmzdAbDc_)kS@LaElU=&5!PicjKw7 zZsRR0?7L~r^Ako2lO}yE3(gtQ)3djZ3!D7Ub zz3V;F)#vy$HyG(JDpT^>vOkJXyO?yEN4rhZEV>`TMe%+pvCt6$OC=1=)MT`YU=hqO zdY4B-=UD3aP9z+w5gFjTm-gA=f0y74Y&#~-Qk&{RsI6KEU*$X7B93I;xy*4MyU}0ia`?xMar)onzRkQGESTN=^nAzb(fcjs>J|FOPI=!va(|qj)qt{widjutjzl)lyC8`;qSD`apB2x$G1bD$Hg=&W(u4C4phu` z)p_rC#~>laqc8b zxzj&RoSz+a#5gj?L84P-g&07vv<6I8$}+=|Zh2M`a+L$jO9j($UGWUVUfR-_ty2Hm zYF1kBN_!^Bptw^zb#;CvzX#RNoBW0JEV641#-fxXSj0_geg}ImKj*r9l32)N8eLTs z@xJY(gNN*oh5V)ZS;9J^6m}lqRmm5Tf|iHDLYR}Rz@qa$r2Xu0z06f0j#^eYJ+qhb zgpjv8NsDRzs3wf#ou%H8R!+~KWw29&Ft2WJ#sN#M_>0^w8)MbbI_deTA|m27XuXPA zm(kC^;Z|5;T`nFE|3798B}LOgp~vwS)YOYK&z<3G%F7r`R3248Y&-qY<_D+AQF=Sk zNf;@CF(Se|cPA&w{0GtY>$=UJ!1Y#yYaEwLZ}d*@&+>8tt>r_pA~`D#i1<0N5WMJ6 z3%YU{3d1PWG9v5KfNc7nU6ZSG^v{Bed)9;UojQY5j zx?bhSww+v(t(LT$iW0M$(R3j+_r0*m&({>*zLoFcGUVbS@}d3r$>@s3`jhatuKmn! zMnfupKf;a}ue}8F&{Jt_e96RnOo5@#(!Vo1V_BYYqBm6-*A_zZJ*|FXeK@N9q)X># zB{vf#vzLucR;qac8VnES5(I4%*=X))lN&tI-fABZd-wBtt~}q~CMKwj7W(SB*hrJI zZO$`-W9rv6d*=WBxd5c=C~C_qS&Da!_t8XEs-he8f;I;Dn1Ksg^Rfeo*B>l<(Q79A zCdXooSzIATB_ZTrd!6I(Wbh0fWJtCFN+*b{=z5HC^tJjq@_3!D`?UXMQ>gc zc@M_}z=*6ZE_qb=MLD!4x~frEsP=QdRMt)e{ol7Q$tUZO<9KnEd2#f8?r*QOd?J;9 zNhe`7$Qs_EM<0zAIeOz!Ela_CzHvT>aK>)DAZfMZ*YW1;UCqjqUp!MU{N*z;9$@6} zG4@^k&}t!49(DJehmumGx@J!>aSh5&Q1kA+6BUp$Crw)PQWifn1(sg-jJGK;5fMht zr4t$@Jwvz3RT?W~W7%lI*r$DeSMzYPy22Z)z*9zBG9JC#Wpk>VR;3 z7kywOJlN3vH!M|P$A+`Z?#03%??Q+d)2qsx`cEI*1jO^6k_}D7fqxAhb6A0v3!l3m zK1@%KWt(y)3&eZSd*GH<@z(5UHfM5Lz*p*tU$qzTV#5sX?)cbiiRG@TS@4&M3g^6T zd_~7WWl{80tOD@0fa;1$o3~GNC*I6X`HD#TwIogEQNudgytD}ML@f4VH-Xx}xp(RW zru_`xULzIH|H%oaE@Ms@JqHO2E|3T3@GFj}9hOwx`Be4t<~yFqV=|j&Brau%>fKwb zlA_v7{lgxjsbI-q*MMyp531xTWu*imBDLhY0Zwda%mmRXzk zQpR#OZ@H65Qi{9@>=AV6oAT0_?6QB|k#*)8*SW54Z1eS`4cBh_v@Ed>u-WTR#5;2# zuT4>dStS&DkeiADN8|?zyjbx^vfl&!U$>(HQ?v$;bVCjz@dBenO4QR!c;q&t5G9eKEym@FeX>5s63-9TAQV9oV_b`k&e+>go^^>HsT>wi~#<7$&$1r|zYyWk#)%D&Pfku@L_GU+T5K+JlH_tDl_S5O>%u~-u3 z>53m=>pH;XwUqhEXA7!>DU_WHSyN#=yyxT>ZK3~!zqTwSg^cQzS2}gq{uMwwSoxQ2 z%?B5So__%1txe>m?J)sDZdQ?Q3$2r?zs9yY*^IRNlzD!au{J2$zg}8*(UPROGR{i7 zKkXTJ5J$!W$UE?8CWjg3;ePHpf^6fV_sE0>t^=w{&udvaf3nb}-M^>zDz3xQFVPPm zC07*I;=FrJ-0EvEm|X#mN@k)YjUj@s>E?D9`P$3nv_lIuUYr_MtRrqzHi9@a%ClV` z{vsdhi6x(pij>`Ky`hZ>wJNvk9b{ zK%oa2t$uBY(yXG(cfbD|O>{`eop%H{hfj{|Mc=B%9a|A<$TSxb8S>YbGD0mLWjzlb z`940C|5ns-)CUd8$u&!9=cd*h_fPrj|9JMeasTghrpg@b5vu8dzN}7HEMpQGY&1;- zT_P&6>9gj&!%@!@wV^jFJ9YHki4xLu=?dUOaP~H|2}`XXudICg_VN437A=AF@=pFu z%1>488ANC6XBFrSEUAG{LVDAYPk+Lu_KW?jM751(&*A%gyO-%e=e+N4MF*Asl51rC zJ{il6DYSpr*LU~YiVM-KCgWra+5ZUI5s43zsKj~yo9<(r`T`eVJ zwN-HH1;5DEvn**htxnbUi_XX>8#Xs|Iup^*6t;zR{pixeR2s_xPF}ZJmHJv zJGVx{2*L#6x$004&cb%DM5MWUUE53c{gsa2G1MNZ-Y&80c3PF_aZKH{9SUpH2rgIm zj0FuoKXvVe@o!Utv}QQr!*wrHvn3MUc!l{Z{+4v>PWQ!`}${Q~tL)>cid>dU3c$%w06-F$9-<7=iT5lkx&0HC=k$H?!$q^DU_IoONv ztBp~zY4nRsN>9^>{+`Uv>-3je>Cc%#(&h?@S!Cm-!j#Grgr7|o<iDC@?Y6DLa) zdX534orTB}@?|^ECSAWpDZZ zcK6HCFK7t;zK6c|m$#4GTh+cA-kt(E?4IaxnB%pP<>Y1af3{i`Q(_&%U=n-VL* zDU3$#a_YZ1ik-HZKT3Opm=xl`1A|iyQR+=q2$Fv33}pg=wB<-VU_fn-{Z+ow63@%m zH#3)t-l>r<)A4+4baU4q2V10GW+9^NU4&rZ+}?LqIJ}Ng9bYL%ggc?pkIR1pZ!&mq z6gOOH1>Pv(PAYTC<0OW`#o(zXQM56c6cyP3KW;hh%y5OWvPw#x{<~{KauTn$i|=j;n5Up$etG%z}hsk12uDQz^vq`4t)E?#`W(tJo7sO+mL&btUN+Fhj-kkB zzV%{Fb1iRG&;P&@_D*{Uo~Af&4DyP5i>HiTb!|C_8{b;$_T=?4q8aQ>r#yy24>I%T z-XC=cvQ!*RlE~)oz3a%!z|K{60!&PWH8jm2?t$VTzhPd!p^e#f6xndaA4 zq*H9v)5XE}4=g(SOQdsf?wpS4;q`*(b_z@OOjd|t$=1vwXEKGFdWh!DUL?^c|J^tD z0ma?MA8sC@x%Ek4X`2WD{MVNVTo!L*U?ZtK83H{Gs$b2Nr8&k30sL$S67tM1&4GUk zo%v*5;Fsz;CV!&@%?~FNHixZ8hz|+Mo5f24Ur?6N6lxmsDNqsVu~g$~{SQ5b)<_|o z`}iXjs$pa#$jXpYhQN6R$gzi$a3bH=^TFm05dCubWNwr+>`nZnD;d)viT{w63ps%- zaDa+_iZUP)6OdfYi->)QhkB=TQP(#qiNBe_8@RH@TT-lV{AI`71hrJQ6h!0`@*`H2 z^Ni$=wNtDEJ_i^o%KL%7@d1YqOSI;4=J6IM4{|T+Ozur)&*@tVzE_S^UuZlMg7FZ3 zyNosjWfy~sEQEsPN7A!*x6g&$p_X}Ln+|0FOc)xL4R{*T#9KTO=B0;E(>|5VOz)Fx zneGYSA87im(M1#=z^e78VDDN>0C1tJ1E?3^Q!i9z|&W>mPd6PaLIskZfn_T8Gl^IQ{FQ zpI4e`sYijL^UQgp-RFrHOyB4d0X7CK7gsLj~SJ4QbE72VH5%IgeS4k_`<*lS3xisL|ot&PwEAVauZzL;KXu|D8n%Q{oTVD$aAa6|9C{Ud zCYtf4QY=JkB+2(JKi+RHi#)o5<>Tow@EYpiAMr&z-oBt<*R!oKN^!Nl4gG9r^6!9X zT9Vd~BStZDZpm&|ttb(S%RA_{BHiS+PbN+wVfll$5rv)~08;jIB&F9SoTUoY{0V6L zwz(9PO=$&${KY9I`&E_gIyIN1d6Ar+mp1e9qw<-h!9W}{{+~xmcA?F;MuX)cfArpV zhx^~$NFBbu>wB2Y4XjU1)xw;`VsKEWA>iJ%CZ!8gx*9cR*7c)?!0zPSUE0kdV6sXA z0XvUK{k)M3zr@^y0)28NA*(3#`OtJ6}Wm=cjp zgY{Lb#j_GQX&O*ISuO)1waPNp9qnIWiKOOQ`=@g>wzIcfTRC4hG(ql*@3?yJ^L6ms zJ9gnooZ^v8e1w6x%c-8a0-ZJTH2RIhx}THkH34V_{p7!74WP%NlMY|)+MFCufUPB8 zo4ifDsL%{Z87s(m)&`g zu-goaq>*DTJ!XaJ4%JFW=83XH5`1BSjZYrQ&_FsT0D#+J$P)4_6<|P>&`xWdxV0Um zg14&;B-2zllD4jr*Sz*NWFSLgD>Aq7maOtMbF8YuJ|2Va*hjfpx3;{ZPUCx>aom{@ zt}@bjuOWgW3z$cvVDRDlqZ(JFuCm747~)7KBOTvBz?DLEGC|id#lWDNrG8wGr3P{E z>pw4yJyBqjUVmq=Qc+_|*Ck=IfRk*q+36-{op37a+x<*$`6bC2e_rf-j#CV)U_%d^ zL)G_LUQAfPp^#hkfGnDW_xRIkb+6Yr=*w zWv%>Jg-Upx6N41tPUAzkQO*e#rh0PwXbT3? zNuWy({y&x1UFK>T&&zDq^OCF7W5dQ4bYT3k@X@(q+f=gR&gh=bcnkpv6I0K>MD98T ztu@n+XSbcf4UUW!ky^$h#nPYFKnBPSyMlnuSR2uJe2xe=!KWe2c`)Y(zH4aJe%7|+ zim9i7aF{;%YHc;Iv=lxlDwB**;)XfH?c}e$edex6Id^T(I9t1}Gxxb=aMfL~%Vh$! zAdM`M#XXDAOzUw^d7=CE>yJY|8HkR+<87m+t^Sw32X=aLkJss}ad5lhl4UGMnR#4) zx8_x!v|f7{WmbQ{lVNheFHb+m6Pxa!jNxmwRP~axsfmpnjG(Smd?qHG|Mi6%na zozxXSt=&hd&&{UuBIeNcO4?23ccxI1^wsNzMuDvOS>6zQOc_W5BcTTIThTZiX@}9Q z6>U3p`@U?Jv10`GLaI11XXBN`)ZtZ3_Z3Web zOi4hKAAOeBGJ<@Z1+sU$s1s?3!OdPf08Rx8+pRW_gycMqDNKe;CAjcXYcmkAph)1 z2m*_xY!-W?*;|Xvj6vt2n#7)Vph|%N*41`97gqit7foCCgpitT1`8JOU0u4Z zG9+)Y`vJ&lOBb<8;?&+t72h0ZB zh*o^F!j$eWCs=tbKK}VBJn@d)Qx}khj)M`Zc|0z?fF)Zd6mnyJ_W7YE+G$fBAg^T! z&w=c)i48|TwfX^U?-K8rPP2G>(6|Ok+53po*>8bSiN>pX3E!eNR_v^&isg*X+s}K1EUexD!%gEe(zzK9S^hjH z%YIOoXg<4nMdMb~?Ap}gnGJrj)BmRh@ICLV_(W?x7o0x4Vt3ctijgK2qP!$}r>giV z{HiQYQ6(><}(&4tu<-tTzuku5SICvZA~NWku^$8BM-$|>{JGXAY=~xr-wJT_nSXE_|ohlhM!-q%F`LM>?xp$~gZv z`@YEKD{elsYGY%$wrEX{;UfEZn$R$Hj;3dt{ z{WLT0J}(^j?s7$cW`zgRC&=Qz`7}y;=?TWnZ$g$GL{x|W)QZm{2Z~2WNr1}|9*W_e zUZ!ieR5bv=TZnt?+sb=9yFVRw^>!soGihOMes3ZNslast2??!bWh@lKYp`R%8AA(( zbl1)PmY;SexO_JFFJAu0F227Um5luWQW-0A9kV^8p9a0Q-(JQ=B-nCGP3G2Q|E#IW zDe-++vb!%0rMt8AJQbM#?l7wAs^Uu@_k%%{-fqe*W%AOip_InPNkHi-pMy3zJ7aUI zEnOykE)y3Ig($m3WKbaoLTLm)sT#BoH0a^aPTu|pA~dinMK8d%;MR-+>h`EvF?}7v zYdrDb#bpKE1JKc!Q0O@bB_ZrYnM7KF$~{rf4H$lFO#gC=G}etOdnCoLpC%C$lSZ=> z7ke`r>@zEu<*&J8EwxWIAbnK@LI>1$fzRu-Z(gr2uGgG@?&^*Srgbb!{ipoH2Tign z442oIaWtb^IXA&b_JDMCLxn(*b#Hi%Mvo}pl66$>+)hS*mCa;ALB!*i`iq4Lo7=`f z9G52n!{tt=<8!CL9VW3TZ$g`=I*O*gAG-vSbP!OA#emUxkpVpT!Jc@ zrpdTkR-|; zagE!`i4QnRK+YYH>I?dx?FF*RRr|I)lh`b*!ynlUc=zH7X2CpNz>WOd8?Da3PTjNZ zu`~eb91bHCV1u3}fCo|rBrY)wY8Kf(OIlhNHDNc-m@t8wrG93guW0yGe(|0$r7br{ z`6GQ*c}EuV#g5_xky@%CM;&g1Y?Vkmc4Cp=vJx^^iA{c{pqVLb3&O=`f%*N^frcoUR@Wa*}GYUOWcB%(j$Ks5#%h->gn?OH5b7H_4tG zpxDC#=VuF2gcBL+W>MD&Sd6tA;m!aN-(>s-(ygo0M4Eo44P0I{n#3`&WJI^GCUDly z@2%+-#ptt$PDzCAJO6ft9jrGj_HqPo-i5Rr(*`2c^6qyagz{*qYpRr(1LfG#yB@gY zri>ozO*@;Q(F4pAh^jC;p+(8%m*0VXA+H*07}kxY$$;dzgO<{afp|Q{xF;0P6V!=& z7;=XE6N?m=1u2ERa&$am4$J%cWZUAPa+cYiay>8!U^y40_tCLwZ?1>=-QYf`~O zb^jzv#TIvptgiXFuu>Bi#4|iDntnO^(pBkNp46I`PRZUOGk8b=&|~T4Y33675%7nP zvVkT#vj1u-b4~B3^*N|WK8!}#H5J|xWkq<`Iu#$=ncMNwVYMJ8r`r*h7MH{G^d&|l zWbTW5sIJ4Vo2*J_!-@|^rfwq3 zc~LoH>nQXfQ^m*bk>(@QVCq8D1zb?So=GRC{M0HU3}>_|Ph^9~LQ{IV?NBZIls`Eo zJ*tuZ)l>v-!Jeec@}xaX>uZMaoBeX18j}a=yurIvQK<^~DSsV94V4z(nsA%LsD!&9hDa z_}5OhF}gW-P3k|LHhv<@>Fgs%RBt>aT2#d>cTK zmmd*pFb8F87zukt%GGb6_;t6t$^P$snT!_;E!UdA6Z#x5`YYIzkfN#_%`08WIfzU3 zwEkz)(E_fGm?WS$T-&aWsf?NW{S%VL@^EewU)tsU%uZHM>V;|Z4?RP}9VG4jg+4QX zv)45)1Gj{qct`#cmU6#LTD^I+_37>Yo1sNHN#jVCTTINyEju9HU#dftT1bH?wlT00=4Z^vKHf_A~#v@sJ0@vNFdt&0xL(mJ+bl8P8eB! z4q{~pRd%gTM`Ap~*5!xjD5`Ve8d z;Z}4INqh+h3zY+&%xaigSoGsNwxj#|nfl7Nt)4=q(OH;49tuWAmQ`+W9?Jq7bX_^O z6$DIeu}4SS)iMm^7^{`Z`62Ov;B_>sD}2cv_ka+WG~3mnv_Ml;@fW$0Y6pT67$p}A zCnt?^_wZIsSL2`}E)?T*=w~ffBXo#I<7G9LN$toa-mmaxIIHI{3~iv*Ai90zxp892 zcQ$qe|D(Z!>X3Vy{9t9b#sIQVWsZEe%1Ci;qD4q@NBjW`Qjs?1`u)?297V8){n)fi zH$D?eYg$m>w_Jbts60t=dh>#*q%pE-%C8*O<_dy<#%9>Qi}Y64y9&1 zwNy>*S-|eX%69(Rw0I-sMC`v)IgVjDj#eDXKa7p1felxsV6NgFJ|MCOKwC@DqYTQcGSIZF@*q>KlN<@Gx`gwbJ3Tu~b~W zR15r>!!e~Z!3%=8+5u})&s;aBtZPe$x&j~Z)y)X0Y5pQFTOk%xLwSTj(Wl2i=!bK) zbFU!hL4&yMR02>bDU6hf=Skk(y7Z*%L+($ zE=z-SN_TgNNOyOGbcb|zNtb{$f`F8ufFct6EzkS?3+Fdy&YYS1zUD6W**xz@DnRrh>&b#qMzQw{>n&gZ~D1jGH~ z<7ri3AaZYXshJB}9W}84Xc5FQ(iRd6Z`DD~BE30CnSCKN=aebru3FDH`hpRPozx9P{~VXfc|JxR`$B$)q`6er|7&^IMGjdt!>50N z*vz^`YMRj8%bWmWfXf7fU4f!dlFssL6h44U?I#c+-l` zZM;PEcltp4j@A`;OqEgu$<)i#O8%0{f}`nP1y5Q;KPEamJ|8Tw?qo_t=k_8Ed6vRy zkMWy{S_3fIg!ThH>9sVoB?j%JB(Cyd2C0Sl(oQ&KOoIBV1O-d2eNeI0`@e5qm}MAf z_1&81JVnnVa#0(@6TRI21^1J8gLAb2^4X+4V`^f^C;LOA^LL=}`0UOL1Y+A{Cs5bq z9&vFtQ|Z8H3y{G!QYX%=rbo+(4l0RDHs+M&&z=}xG4(c_P&~m=D3pAr+dtP^wB4XC zIYtF|_Y7T~jZ=z|JIm1_$|o;9h&(c&cwx5&mja-c-}6>X2-y=RQxeYsW{cP#Zu|9>$6Hg)@#BT2VH0B)b7!~4*$K@7CJ{uYHHZ7Ca zhB?DXKOQg_7mB_hjFjYz|CGXEC`F{2I{ndn#YySMdOZ)S5DzZK^6{IW>04cvwlX-g ztpB+Ve+B{WxBh2f`HxXX&n+7A+2R}auuQZOZ1Oya&G*5KRR6BN{uflrbreKCn(Rd>|Q2o{62szM6%5kj3V% zca9-%kp{e~`zRqS`boE&YLML)6eIOkq2Xi*l53C2NC9eL_P1*c)3L)L?g4Yac14pC z-L}Ar?rgB^Dsp1>FiA5h>rKp#j-p>MEBFipMHG|bp(9~(mYGy-Lkij(y6)VEo%_j3 zCw6%h804a(xI)g8%W#;D6z`2m^-wbddmRs3d1xNXVcFZf`gM%L4)ao}(mM;|QX!Gs zxMAic9)-1xYyh$UR6<+BIODz??mZlPGH{RWwtV&^xWZ|9|r1 z(UI5AxfnN-^8vYu+|hdE6XDX_x4RG4ZVBl-vp`}z)R5wImMDcaXJ%jx1RzaZ zISwdux4TF{qTnkZx$rz{6(BUwwe%^ zISLCh2WZTWcze96DLgMWCvVB=blS`hy#>EF4NFRk{G_GW`z(jTvS+vEn1TE}qQ)nx zOKyStNPB3JDdH2s6_f$}rIFY}XLl|aVv#saFAPHal62*n!plWpnKFCvMRLvJEY~}c zc=?s;l1L)lkQDS%0ip#;-U`Jm$ko~Spc^bQHYc36IE*JlJxUdZeBe5)pK{Ly3ZMw} zX*VkxprO$p*(kFF)Fi|zah|~SO`F2=npAL!=h&tfIug^)y|a_=NRnxq!O2BVEh^>Z zGE#GWrI$@5@Bg%xEZ@!i$a!m28($iwV}&jP1-`~YCqpCcEgXxd7cZHnu1%nEP);Pq z9uq!qwpy65l+B15!ui-T2xk^umRw3pP!K&6;3v!debl7k!CAdvM?+gd6_4G*pz6SG zk)+{t)UZ)-TRt!+Zx9d~Qcct&ffgOpBxIjR3k}k$*`{;d+gCl=_*m!vu$7JEPQ@1k zCZDBbhYm0@@@#@YV9p8*w0G{1R@o_iEP9g<#- zG~AJ}yNiVpvV-DLYlD^<&8*4E!8ESF@24j!!bQL`#B#PKT5Y)TYRJ7OV>(fa*)dWa zsmsPiW4I0;3wY5n;&0k$7o*n->GQ9_3$SE;! zZEC5{kdj76uBmXtx7#FoSJfya7y^OKj(bfkeYrb3i$&WHXUnHMPtpg&;3sejU?RF5&fs? zSS@&(jWO;Uvx_Hd2_#2dLBhJn+Sxu#x6Dmn?<<)pQNgLd)gL;FlELtD1!_!27f%Ou zKQxCU77*;#-(pj$9}%g}r;@d+D&388kCWQ&lT&rA;fG45bFO(X>79hC3-CAQT| zD)Q?l1qelG0s`9=WrMhS-3VkAaR`>XtG|))g;FNJ}ee_4isb~wJ z84vyivlE-0!k#gr&kd%CXNhw{W#5VU2VZ@hWGK!yix?#d6$ckx8nq=^@NLt6GXq{1O%;f!sjVtRFANq|ck_6rT{a?-jdvEW{XPh|y}IwWK^(s6Rzm8{ zE`wwnf?=hSQbD-N$x{5}TH&>WI=qUq`#)*%r;l`xH;vMK=Wh=S9V6mi3Rsda{eZ%+ zJ&u%%8~0!XdqWZAq_7c7Fiw6XcG#S@lXA?8ZQ<%c6N&%CQ|>{c0WIgAa*x!_$0zRw zuaP5D86kP*)#?;O;p|m@wHwm|X-xhQS5z6w-R^P{K|rDknf4FF*-55fjdG9-e#rQJ zwc;igLSx03H>XTbk^ok5c_-tP5U05{ zdl9Fci}mzeMxE|Ezh(}GI|DfIAR{ga#>uu<1(eSwaP8OwE7Jb;j~p`lB%|5n4f^#)RBeKG;lJoXD$2P26H}41KgnUv5+Y?J zoBJUeIntaileAiCVRc;~JzC3B`0KzSK)LmdSky6Hwq1dTXrE2?W%_-F@71mcugl_3 zzb`xI7w0o4Rj~(-NjgI61k+hTU=|HvT(}tRzN|Eseb9&>-j^69D~;l=7m48>nvm#7 zr_U1L(K9xFiGW#kJif&kem2zLJy?FMZZCjwRfLf728-2O8vBY6CRCnpu6&xz?8f$X z#9A|kc};$QXT5rl?Npjv8arQD{eA>whstQjNbkFVbD=TD z(WbXrS<4JA2dL*3y=Ycqvogz_(a4O!{Dc=%*Lebf>}L6!y1wmf!fWxQGlg$Q(Ltq@ z!nw)K@=~;!8rMRS_K)0eKD^)Db#l)2G1>K9%xUr*#%(p9RM2DW3J)&4O?@S7RWxcC zPZzWB(A%Gi1ZF3r#LT>%3?6?sKram^k}f{r(10~y2`L3&d7=G@$F|z@1SooT<7rKc zD|b|jRcYFQ;>$J)G=>#_KhVWPm>g5zJw?wMvhE>EL|!3#tTaw!hfzJ^jPyml5H}ft z%8Sy#?A@qeO}E+Pw+>@d72KMC1Dg%g<}M`?FOL+Jopl$yBm@U;L8YhI#)ya0yQp|J z$E4UC?4YB}q$RvdgGxmV9XNS=#-fmPv6&27c#5N9!j}pYoCV6pgudPabizs(axc&Qk>u5S(z3xp6X(7(z~JR3wGUlp)_+5 z?z>?Ct$S{+ju)A>_18C|3o<`B+lXsoovY)NNd@#qi+iX5`Aln04&IkxzPt=xQF@^~ z-sGF^2JpEdJ%1Z;bsDb=1qt{1M+V3LubLmEk%9&%sk^2p!`+WdGm~S7Za*pyNX^7g z9k0M0yt}Qs{N?l`{~w5t**^L&?TTZCW31#fnhMzlYK4qt!@`ziSj5u#_`lNyH;8h( zYA}WS9Lf;isc=r`_{cyLB$zV(VP zdW)<~lF{l#6-AnIKq{hKC~Gy-GhG0l@%t5J!mSFE;|Xb()qytNqJ;gtVbftCxt`2w z8*~-Ih27?seO0B4jv)}R-hJ{EJr^iMYmraU17#?Eg1hM-U?*WD-2v*)f3>TXFZntr zZyaDGi}jUslgYjjpCAGsHETTvOt@@h9bbv;eef5tJBgZ^yWgnvdE@BBD^uKXjzV{U zue`sFovI2&71L_m^ZueK7^f)25H|%9QD=3q69yYlGrp%@V0Z#c!)#GfMb7fVY>#taS8fjfpo?y_{zeQm33eJ)Rs zJiyUXP92NKJ(R$$i6Je_Q%_KG-AmbWb)jA> zw7KPLG~vXXqj0@q2>BIVo@}8ow8+XUMAoowzMW4ydss0+H!efe8|9k5Nam59y*`2e zHF3?|mbEoli+ZKyQ}toFWxbJr;U&vU-s!md{Bb=(Tm6id!lbp7LG(%W?}lHV86PaK zP#HfuZ7vP#8^#xtR7;`g{FR=khVTWLj6JWND4;Y@)pWiSb)TQ|M~LkT%fIEgB&T53z68GVG;Owwx1F!K;KmGn1v?+8f7u)?nC6ub(#=6)GrDTKVAF7sdC6wNYMJw{74e>(38Tw0|KI-O<70QWf30JZB&J-WYy@L9hSM`z zS1CLxOGhh2F$=CYkSPH z3-dLWZ)jjUmpvI!jp4i+G;7)ezL^1zdST0_YAt=ZUV>S;9VreH=`K$CY}pm!S3mLZb(k>X zDbC4Ibq5gt&Bl&UfMzd4&q`esA+NZQ3HUl9a1!DhOJ#{ate3)1=2!bmq<~P?B_`3s z@}JzApsI3~w^)D6n%dRe;*2b_0?+SbiIlWoaxIF##~kaP+b*kmY}mcoGCH-eJx4Bl zjBsL#ZwX~gI4hiVm+FrPxyc-&Vo_0I&?$Fo;yh~0MGl3;gQ)3Mt?k-I8M{;=551nh zYZ5eWn*e*8 zxiC3;;~4{1OV4UwuR4$6sFGPC{Q=GnSDQxOs@73Nw+|1q@i7e}u`I*aCdn|>U`icI zQaOEf90DjKM zWFklUJ#sSZzoZ=m6r*`67^RNNpQ>i|JgGpQ_BSaiLmzxu^O|yUaKZc7$Y22%8tf>I2a$@XW_hh8hd z9nYQ4qr8WTKgI|h&*w-O5$6)GNyDAqC+gXwA`ZNmi z*b%(i7J4KwH1hKJp!P~;09Bv8l2hrz=n5|=1M`~hJu6)S#;H9o>E1az2r^axF0--wf@L;3lfImjUGrag$oM@UE{=ZT1T5DPd z(BhmHp%#mOHW06GE}T9KBP{J01&1)Ou|rV5QdlcuV4o1|`;5Ux4Ln{!(7@@F*(5O) zc?XX*cS^5{-9}FGzUvT^j;i^3Zm=t-RViPby63&C)c9J$^koL9h#6A&t>l^g-8>%B zvucX;ZV)BYJkb`w)Z|FoLj11{*|4TN`8mDDPLTxt>xUuNe^f;QohQ}WF2sSiJ8@fg zfe+${t?rwL<@=fLnn;H;H{Mi?JZ-f#Ve~w1wZSM@wcYFnD{Cv1{NVySDC}~(X4q}8e4Ah*zJ-N@s(-O>(65=DYt~q#LA=(UP zi^~@L)nPy8sJw;zgiV9R`+^xL^UVE6?@x$h z7hcRAOP2U~G%N8xX`iRgZyuLE_b&2E(QAD4<~JO7};>Cbw z&goOD0*RIUx-U9aTX+=B!d9Y-rS|q0uT0cXPT`njlsHpk`E(dnzpF}NIsd@K^wYs1 zM?7Zv$g0^5jlQ-KSul#uHl>o^)62^ReA{U9y`7VosP*n7zHg@CaXcIzw6TS)wsQJ% zCVMiI`}Z&Z)_&ONuJW;aV@Is2fh}A|r;v2axsDQ-p`@Pze#bwoB(oZjV_M5U&Iy0L z$B%;t1oYda*&#dZQNd|TB4^hOoC;RYx!INJNufS`ena4vCelxrz~}y+1KvNlFak7; znkH)&6MA@*Q-4^LH7j{!vs(SJ514G5*en#{8VrS^#xq|vo4ug!q#u^=_6g)Tp>vv* zU3@k8F3B_pgO#HY7FHP%^9r2>OhOL)^FAw;A#>y^BWzWlMLFAWZT@6<5?ibuhON%H zs9cHy`FX*L>$w~){E2jiY9fD>zM(`isIn-u*4!AJx@xw#q{*Os#Rs)~xr?j$zk(6K z^bFY}^1{W2HX>iUeNFZkm(t?y-}$Jb%Wz0>3bD1KYn~Id7?w-*PL*^xw^r}WZg)l5 zIXR+eUUOJtRAVtlod07)lV+o?;mp^wHbuwJBb@zgzmLAMtv8dk-gVXyIX5&{_nlJR zrL-M0>>dLJy(k^aGxPo6w!V^oHnq=kA|2bZ{YD83USh9tA_skno+}if ze&7?-7LC2?X)X^+7JIq4elT9BVA!vDc=6(GSGpHD>-z;B4*~Zo{EDUh+rel-YW0=y zn-m~FjbKhSKkNd5+@V;|>X;H02iIbQ*vYbF4Qwd`CTqq~y zuQItjN1XluH|Q5rNr-T+LX^7)B+EBZFN8u%1MBRinR1VN+5Iflb2F11!%_wz;5QoZ z>~7C}9VE_1SB`Dvfc>@pp+0kD=kYK3lIKjkeSYG=xcA? zI?}v`SR?!*b+n*Er|F|B#rb39Tp_qHilXtMf@D@bweQKtLj~$f?YjPUPtkK5MAT`4 z9Pv0+<3paFe9vv(MfwM6yz6h|GQ}Bg3F~`HZ9bKoo;tqRghoFEDef_|?RR=NJG~XZ z#gppWErr9`B+c+j3vm`}!sImRzqcIfeJFg-Z#t6ao*c-XohL{K2!+XLwNW;Feut5y zW@gPT?Rr8uOsj@&`>oP+cHA-J6R&sF+X}|3@Kl*b56GESk2?pgz&^*AL|gK{%yb#& zoc>pt(ReD2m0y>Rdg>#}B)an@dpuLWQtSU>Xlep-_b;BtAI zl0ucZ{*$)MCs1I|$|@;24YK7$?MJnVw9W$SUCBxol5vg-xD+2-(*k@cOlC?515STu zY~Bi$A&m6w+$|GIeiiIHTz^{LL730>*LGQ}K5A=nURDa?Ip7;C)zgAGInlmUXi#)S z70%g$Sh{*z?}2bh-fR+P_S#jR^cIch@$8H)cTg@)-%|6n9DSb~;!*3u4-xL0?gD^c za(t6OiV$OrwI46d?8kIR`7=H*UuEYG+Env@8dEZwyzWLg-y|~e!5Tmz+F;iq) zg}5Br%FTZ@6V}q_TA0MRq(dlCvGi@~Knsd6E(Ky^CfIjwo7ZA$w78hS99$W)hDk^& zdkhbjl>%^O5t3(gArqg;uLG^Kvj`mD5ddh7Wppt4aFs$}Vr#k3zCf7t#Qi!1?@dDv`A z<*Evl2{Qam}sxM8e4z23{ro-GspjLyo{V~xJ8FfQ@Vv1_q@7A z);%amy!H{Llwa~+$c-*iE0Yy=huaIyE;xEn$9v#FAM~_H~bCj zVbl~+d^uTY>!eSwF>QcuY?L`23s(Lc2oewfu$|E+v3RVX;CjkMx6tTz+rJj9{@N1I?kD=umjy8Y`lMVvBama@_+x)ESDR9va=u)(IPRm4u>K%8dpI)ANSmRwn4WSWb|)byAVoL8S<^r^7;v zX@MHH)=6($#zht-_vhUHnP9z}SqgjY+wy5H!Q&C)70=Q{00_Ij-DLxX7s~UYGTaD$ zjnm#09yexNSVDI|bkgmA>5}SJT2zLBo=-b0W%- zwJUPxEw`2J{*CvJ0)aT4&WW#e4KY$9O{d&_Bk3^}#26Ndi`uNGF(y6ljHblM%^Gk> z^wEE>sX1ji?JcW!iAD*dqry_9@(R6EAN@8(r+AFbTOOt)%cE%_hgg5<&iuSwuL#rPeU=%DI z^S05yT2{|AN7sQsCE!*mH@^{W23le5TU^OT*^ui@;b0s8kJ(d(PNm*|;? z&NZK zc^-guRKyHmqc~VQSgt*UH`-Vtv@W6J+OgYi0b4U#yHqdiY<0R*vln`4`*d@@ zXUQ^Hps9O}vG&cG+&F7Z4P7wWrYy+tfd)RarXEs(N7vV6H6Y_%PZiaZ*2r!kN9WtQYL}Yj;a2@hi&GuHp}49(6E7ZEsc1yb zVDY9n=3=Y2qr#ysnK!6RF61D4`V@!GEC^Hia+#%zv=+S?6=|qS8Yv=F?pk_{0SCSaaaxk4_jM%yV^L+#P_1}7^$?|tpMuEr7O+gJY zNnUY3FR2EK+FPztKL{UtGMsId^(Vv~yhK2k4?ub#s8x{4`{p0qp7x$@&dIuzI`*#V z%VOt(yw>Sv5o+jN$kLeeKo5SMsF|$N{P*f9dXRjN^u(uY2YZ(PWbs5^x7NhD30ybk z{vkwf8=ZSzgyx?8CXdHVS=EqrS;%Ix6xrNk_hghwT?%h14lzK{fJ=jzb~@cGXjv*m zIJvCvbc#xe11Cx!NRP_+vcFh=V*dqb;5L%ZYd;*7|orBn@7lQ zEi9$)LCeVK{SBA}EA9mq+7vegjW|=E$9jBJBdiCTZ8zF2H4bAsmVM|N)MP5CoGNj{ zq8i|By#zkCh%Y4}6~HBJL61~34JN>GO2;i!z%72+dEisq2iVv``2>K)!lu4C3K5G^ zl^``H>PtqoPen; zsTVfscJ{2a9j(o~4OSOb@hzn4<7RVpqplz@I1}yr>75_{xlwOCSc-jIZI=qBC{(-w z!p|`;O47rBE%RJXO0JU5a31T;EtFl3%Nb-v zpM_HCT=V5E1XM?_2N*jdi_)6?|60lO_fuy8jTro2Yc`TVCc+BB^^&+~9h7vE24fhp z+H8lE-XFEO=l4VkrH*~=Uonu?6F`|vf}wzB8l68pP9iS0rp5zXUm=M@AsggzT=f?tgO{QBo;8l~QzrVup2b&w7HY(zYy@RF@ot&D|sywznS zdoC%DG4K_K-N&zc0s9&0y6`|DkBSquVhs*IpTB|bKbUvG2&4YU--HD}KR$oBN;K${ z-WCN7elegR4?MYe++MHpYjr|e>+%^wbgsE+!Jw*GVx^|vZ0N6b1dbO=L(D$C<5Ng0 zpem`$)Wj^jqfh)oo^1IPJxG^yHW8B0;5;e9`Lyt{WddlVCB)b-qm-#lxq_%2TQbfV zI>tR;>FmU6$#nO5zx)U=`Df8FF?>YizD zKWtZLI{7EJguw%YrxS{+d;zd%g~>vKt^rOQjfJ9y5j#SC0ezZ<4{bROUo`h}4)`gB zETLdyBfTr7qkN-Kj^Lm;(APq3QYFJF_9#HJnq7ztCWi;4X4Sd2rfcxuDUODKk!?1nIA8?u$v z1&WxAE&LdLIMZLEMxU3K%m}H0g;cBXkAr^`|4r5ZlTpQH?!2D^;yy4H!l&t8K z0!to-E*j5m>)OU0wx{U%i2?{l@?06+ihfsKB3~{m`bLk9Kra~{wqK3fa<>~iQFiE+ zL%A6fhZpWX&$~=K$h&bb&QCj|Oln(4BCsRXD}uA2G7(bC8Cox2M}BTxQ{z}1c;#u$ zz!1HiJZh6HuG)Bz$edjs0#{|x$gZhyfI%yuR@N4O4l`d{J4Od4si89zrAddKfcG0B zbsGbfxJa{vY3Z}FuvMXiEfgBD6j^xWN@(sG(Hd)<0d5$i$3aoFp92yPBwjfm(j|7UUGCZ7P>g38I0o}ve7*VOy|r0R(NQ}UF1_%g6W@Y&HUvA}-@gU_>5?e`f!ezTA1f8UyW@ULpU z!s@k`q!7Whx|E~?VFx-kKipd>-C0jYIVd9^OT5d?X<&6wGLO+bU|vei@-Fk0d$!1l}76s$Ppi7H3wMCbHNyDce z5;nQG)FOpHRnmZG{F;|sJKI>^wYDRzsm0)ZZy}ZKaya%hU@#cN@xu^yZ-j!GMg-0$ z{Ok_#TRg86(=Mcr=)Zqj6)MuM=>ZceaYbIcDk+twwBfe{ArD-xJ4nggYI@jQ;OE~D z-x1;G1%wVs-Zg!T|NQ-+4?pf}BJ~}dN@Gd@5v#{(f*q3`04pJw+k1o5SC*P)A3~U& z!cV~>pqfxsjpS-s-oJv9Yi-x>!6RkAuUeT5uj@u~FmxHIQ*Ei!nXEC&Ojhs-somQx zqVCj3ll&e&GE@O}&O+Zcvnqe}F-E(j(cWBff_h0HJLYE&1%cl$+j&lz(w(A96=aTq zQIL@cW&q{@8L==Sss%Hix9uJ$Csr!Tgw>L}J!vwp1}7tdfAB5}Z?rxp1JmcV)&1I& za?eSq4cv<0zoFt`5a8fV@C>D!!Y^8Pu?PYu$q^C;hz)fZWVWmuCOjA}RMTW%f-Tfo zbRX_q<^#39f;e|>8PpKt96!L_~-sg8}6j&_7dx;7d}qspO*~EVzV8xWZ z{)fe_zMTB875yuZKW4JL?HKHcWw-N!n6sHExLTpHFiOm$rVK*6@)`?*a1pYjBJV2B z*eyWwVbF!r@;bjIu@{hwWFlBJxi&{TKi#UwFK-k>M^9g!D~JCt{H<5qw~*}Pe~aWk zr40w4{^0bz7>81gd;OkmzIV0--#=%)H5q$>3+T_6=)b++X@2~IC@Da+UDg|&Ie}2X z!o1P6q(eWe_;PAey_6|F&nL~^N4pEU9;dj%Nm&`^NjRxszmro-@)n*IX`|!u-UPSq zg)kgLGlamTs+}RuRSU=L2ncuxYWmo`!L&8X=6v@l%_+g{mXR- zH7*VXL&a=k|DDbdNC(;6X&j>iF$+rZgboxIFK9SyMsTx@d2j|dM#OwQ6Tos@%Ib2v zEFLb5i|M1RiXfZ|tuA)_R9ZEe_IbjI=C#Vry8k93Lm)5QeSWd-eP;flf_Pw;@xxps zHvfDy7f;hm<0!^_e?(_G7ePy02woBp97Gkw%(+`Be6F~!rZ=wf*optTdlL~&K*Z}$ zjzxN^pw%doY@Y1<_7#(z-2rH<>9=TmZ2Na zhw%yBl3Qw|66C+!v$}vBNqgYp=0CZlH^ULW*bmMH@BBqc^@>izsx4NP_a?-?0mhJM z%>Lf$5)m4Bii(XVePJbb>iaR`O+w(hVRTeA6hHm6>@JY*6H}Sl&y#vxgQ}+Bc%p;4 zsPuHHKgYFge9T1hM?>oDTPLa7a7)3F+vUD8rl+fNq zd_$cgWSkzh&h3ksTJ>+ZeC8ebv*S7CDe*^tpWzpXt!2c;!*rFuRa{D{p`9rsANal! z$6jj2(Y!+cSgS0BUx6~nz?76+SvH)WhMD}&U^}a@2B$rNMTQ3^vB9rOd$u7AmaKQM z4akV1>e>IQW`I+CTS(`BWdiBZVokX-rwR1qdKpW>EA!Zr5QxEf9S!1QLxcN z^>1f&N}l;O4xx3lT}o8Iw*;4W?l(50-!Q^auyKtSSE^F@vDjj`8b&Ch!RcTtczQKX zpkACTRnryhZ2l+*(%Q%qUP_TGC!{M&VwJQC=`OPL;{2*hqc!ozK4E5nVxv}0hr>E3 zt+{uD@4H=^#dO)({bV*ek64HaUsHNaVk6bvx9mps!iRDTsc$ZNdAA%s8YlfGE+*$A zBJaN0kroUTF(k*?nUWe9vsp4m8*+Hb&$+NP(o4RR)3B`i*3?S4>UZR&T?_U7=icf0 zt2vjg*d3qEAg*w07}WkTv}<1$XE{km%}HyL>SfAkyXdb%#o1TO&Kn?@-r{}y=KY3& z&O4-r5h)@M0@70;rNeGGKQobXnD_&}hFKq@*-nB3X=1HQR9c2vpA=# zeYKyH|Kz9|t4DIfbFLhXsMZ={U(@ihNn=I2!P7X86XSSE8Xr;({qr;{HU$#A8IrSwLRY0U5-B&#rjx)UGtkIP;!EmmL3Y-IqKsD4Owg$oxYl_ z+MNFDztRHD;M$wo@-;pAa=5*$<($Wfmh@P5hiQ~B;Y2(U>0B-?DW|8s#{4QymBnPh zB*MS@_O6+`25cLIQmsacO5EPY-N-;n9n^G|jF~uQ5YH&QrBC`oc_n{1loi6LFE^wp zy3QxtYY7B1Y`Ad4V9%l)X>ipnP4kmpQ102gebxp=8g6Rwlcz@$2%)Z)FI;(TGXH<{ z*iInFLUXwIgaXJa-TXX_Hh869JR%VNh`Svm zfpVs*QlBB7QOS@Q5D5iXQewwRqi89t7vt8>7-o16GpQd;kvKPYWMN<%l_-C-Gc@=# z%g(mEJ?Qz9UCo7*J-XWkhMSN8VI7nLy!}0)m{Cl$Dd@8x=;XQ3Q~f2a=!LD|_PJr7 zW4CI)h4xlVy;YUeq<}#X>@bqkSg*uT&weQ^vPnYP7O~Yc-eKgFz&l)u2?0%@K;-t} z5v9RRUl?HmVjeBy)6w6OrQNjEN`^jQ)ZNFJ+Jj4}L@ULAo)*~>Z{4KY|EKCeipYP^ zKYcul!T)(y>ADR1yrcP)m;^8p*Uc&^-7Ol&i{<%lfWjuq83Eb%dOfk$TYLIZv@k4xYi7!h3iBn zuR}Qg#ez+vbv=k2#KKbYqnZW2Mopn&D@M%96Vqu$VrMDv8;(aZY`B&gcY5$|gi$kF zvaD!=w76U=Worc;m{nn0^t!9FH6YgVu>ZtHTnth6z34u2hY4Jv2wVlddk+1zXEwMj z^00OKh}h}v^ec->k{Y88x#J}5`T99SzHt7M91L?VJJY^$&#?G;ApcUqlnv>9?1{0_ zA52pIk){QS{&NAHb3a~KfFXG=RzC5iI>sWWcDAL${L1xX9PS2RpQ7gm1xT-r?Dx2# zkv9FeHtT~^+GXkadHGkQ@rxF#u8LWn<4+37Jef5)MUkgW;sodIyRD0jsVM&z+Z2s! zOV(|6E_0@#R0y;l=7+?)6~(erTBG`!lpLk7NRd`GuBVl2L_5lmax&<5_C2H07bwyB znb6Ed!z{i)Y=queMed* zip$&IYd-IKRc6gGoM*5>PlLlv=!q{R{{jm(g2srwpQfkmixs_ThwGcGhesrjiOqe0 z_;>QS{iD-H^*SCLO=unS22?CZap~!R*(Fc>llOq%M=RA=1celrl93)0V|4jvN|co_ zeuUC$nAy+6LExn&TM|3(R~4YVLa*gF$EmcTZb~g^N=Ij?+1IzqYJ%FjS)~J%uIWFs zGb88A`^38_4TM7CBH{-2P)n52aKx`7bzR!k3Dz(J0=BKVOS4B7WmE7dF*J4|*z$l0 z10^B!xVWBJCUPL_&7PS`PxXhX3XJQ08@tF~1judnkR zJo7d};aD?65xq*qSceT(#hhDyAL`*LcOV{=BJGt7-maUNhilx+$DsEZ{?c|V?90^Eu8!mfHm*)r*2L*<~FPhVs zdP^-2vqEWh63Hep22eYKQNK0FOq~ei`~y;7Z6{}ESf8z_>;x<$%Ys1=#Pq8*S1=~K zgRS1Gs3kjMxxL%xPuXs7)A%A2j;+SNmn1lIE0+o2s=wx`@1Yy?e9_c4&XY|arnzjF zX+W_Er1CsY@4MqQybz#djX-z(g9$q6?3zbW{Ex_qY+Ho&K1B~qpoH@Q>HLueX<%WK zqr|>oOGm|F3B|QP0u52Nn7O>+r_-O&l?~UPosyte?bvh;Xe&bVFWahF>$?jS zDX?Q>w0hdk1ov%t8QhN_vLCbCac@q^T(0`B$89IwFA?Vl`%~p9V~f(sWY{fl;70h^ ziwljxS@0P4^bqDQc>5QtO^1c{OBYjvcJnTDrz}}_T_yje;S*+1a7b}?S=|%VAL;~ELv0kl9?Z0l}EfS-wihS~2_jq1$AwR2?VCnEA9V|VL zg~;(-ig&1CXbO_OBO~U;0_?WWm4mUrl@5~yeqMdIbJEoru3|5rq%cJ82tzA}axyj( zvS)j(+Nbri%QUjQ1jkF-z(OtS*rrvg72VT1&O*XI|o3#9 zUg!z0KQL)GeP_MhV70cnB@SqwEQkx>R_%0o=s5o(@en^BO;NB-Y<=pkQ^B<%&^;_c z?QhF%`{+?{|9HBN-1+7ZUm9=A-w>vWDV3FQo<<Z)p)JsexA3q5qzSIMGiW)|8)z$2N8`XBc&~_C(nzJKS!>16fxI{}D? z{6qu-ikO?u%?h+a?rWId;9Y}X<0OINRg}boW8QZYc}(}P(*61FtjRdB)^a!SORF{l zh%u}p3g5)ybGn*{aV`m0JQS9#mM9O3C+%@MMNaw|`B@1KgSprxzt;-BL-cCyti}zM zP7y#lzKvU)#(<)l+x2Vx&{^c_%ytW|k-I#8bc?SDQOnT0S`y(JImPyxFE$0gDsiGdL3> z?B>i6`w>P_Jj`N?XS8IyI}8dutpmsr&(n_`P=tp>1G*>zsgbmW_+y=XduLKwd<>Nd z@vow`zNEy?;Tg=oqvAV9Wz*LS-hKYuxBaoh+m125CF!tZ3QOHp6FUbQWKHfP`6>*M zQ&7!#1+y}aEGKEIhK$cRHE;^qbDp%XJ(?6iyP0T$3L1f&m#l@n0>2|GCoQKX0IS z+He%t&@9!i!_;_QZuPz&4)r|{yW%;_`PxS({7#y-nK9+@gsAsjs|7h#Tm` z=H^tSe{BkHaLH@+L%|qabAWo z6gR`uKeCqUpZ~l#W`n-Ljp^xi`JEW|?%S_z0~&w7oYW1fCZ_9{la~Ug%{F6!odkyE z1#h5V;)ObjAbGNS+EsYbN$tYq<~CWpmE)O+4wH&2Zs+54rn(UYK6AyEd}v{j1!|^f z7GMVxHpu|31Iaj^iO#lG>ir{ghN4dg4~&qr`4JkQZ{)ACL8ZDS?EQkGaISo-M$ zjkF*!jPdnh*gPj!Oa2Ut2Tmst$AmGu+(TF&wdKF@c>D2u_)$t2G&>p~l5X)3Bt z8f)Mv{#l*K1c`Glr-H2V0HKW~fBXPyBG~?zA8QgmQJRs3}%Vk z#|zq^Lll2b+Jge#SAC<2+{(4H$CLc`>Ve3gRz5HZoy+FOBGG2d0rZ7A zlwrdz70K-5?aN>HGVZ#DeBYYJJIC32&2^=Eg*)>y9@CV@EL|JrnMnKP@Ybb%bc6(j zf5uao`yJS;gW~fIB{7e2zQF9JCZQ=3DcIt2CkGvMq1rqYt71;}&G4}CuDfJ1w#jv> z>HGN9YE-Ok>&nu%J6%hoq+XhZ(D&G^cN#FJtaJ#3)ggPH)8G%exyZhrKH8@ymYGkS zxAXku$*$WxF>SlZfj?Xe8Ce5An0} zZa(kUq~Y$L?z+rTzh+LTN^sn}$3F5uLakLJBH>7FXOvIMp1qs(dt6qzV1J&h%{q51 zP^UhE&G~pb_t>82j(#sqYzx&@ulS?h0A?huFvnmRkQiuH-oFksArzF*L1>nEo@4^m zDAVpoNH~(Kei)*_cT?Lq%M!TQ!hNqEh&5o1`n$uO9bqOU#E39K>8Qvnn#O{}dwBly z7Qf}aeoXS(d|CWB*!|1N+hfy%;OEqjy1n`JOvL&F0|rB^!C|HQI=nYO5_Np|Yc7 zEE~$~Laa8Hy&AYGDPzE9dZloKxk)(0;(;@2y5<4gw~Lvd8EG8ooie*Jq0l0~A}KK# zV0EML=*3t|+^}X-ex;&CijJxYn8y+rX!<^2;HOf^9CDPV=!D`MOC5tmr7HJK{c3H8 zxu_LFnx5)(oNi-8YBR@b)ffUG-e~{bT(3p%if1#50*I+CVftGOLW-enPeW2R=VCTe z11!MSgw<~zg?Hr_9;>O{kT{~eJwf=7&xBsGauGQ{3+~pp-m1a_YGRvXD6E3UF+pu` zLDs=AE*`ah&<#TwTp;RjJAK1rsyrfD+foWF&LDDe3{*Ncj^^fOKHkWTd3!U3wH2m+ zkT^sY^W)Un-0^nI&)t&3G;oJGEDS(dHpXCS`Jmpu`&dC1P9jw-vtoqi@>>NiB{tDz zI9^^FBsKv`@GbcMV6Kxnwpo=XmB7GQ6ET+c%yOAVw`x*eE-&q40a~ zCI8-?qLP#CHUD=nY&Zmj6fxF(E;_M2E56|6A1NAti9skz^-a8Am$FMp|KS&_`ySW^ zq)jBhYP$i&Th8TiO1k>L^7q{DM~>um@CuC@k{nRHCG?a*Bds@XP`sThjl`-9k4YuVz;$Xq`?C`#nrmH1vs`6p`#Esw}0p}jtvGO*-M`&)zLqt&%_SoQ| zblvUQ!~(;s_+5JeXfqte`WlK@V=*3^r^*aVFX0L(7Jj*WkSv920h{GMvsc-VS!qCxa~+r2?lhw>1p!%O!g2FU$yK4gy0f z$Qz#l!$*=HeO7?8ao!2sxGE`jXrZi(ICL>>o(e<9!+Y?ftngGxs+I2}kytwA;n)ba ztJ+SW`jPh0`P6E=w|{j4Fril@2szOTK@5S33(Jwp!j)yEQ`v#3pPG`2kdvi6a)8y; z!;_P7h}e%xBb8khfAzh3AleNI_;;AKpP#o5;&4|Ge5Qzn@S80+rx<|tm%>W2G}NZh zFoS~w(I1%)?FGjI8iv`ya((}HH-Z@Ef^7NFc*~PD1lcs=c?eV70+Z=6_t5LhpB(KWWGnUAb0e@%XuI~H!e;K&<_kDiz25*61>n=_L+*t~?Ia4H5mBn^&Q6hCOfq}8~JF* zT4>l-T$e#u*HHi8c75)UL)$f&B)#E%-1zBtVp$@&-K?{zC)Vo4?M-s&_NyA9c(()9 zy6Wdfo_7x7gX%&A)Y#LFF!=d=v1jA>{AFu6JwV?DN)^ZRuN)wm4(Caei@?|d2q^Id z+7%jj#1@Ay<|zTGKRW2T&C6Vi{MZRG`VgrtQiLkbpq49tnx@3Fjgdm7dak#tUh=W! z&n%+lK>vh@klHZgRg&Y<+b4Q$_Y%RE0#|0r;x*dile|w^zF#+L#-14pQnn>@jKe++ z6Tk_B*P;U+oDAi;7h6T>`NdjuH39STZwN4hV?j#5amm z-G|b+CQqhhdeq>`=>Sw|c*8BEY-*zU#bsUN01i5!vi686`)cNj0XORs4EC}V=IP*g z4M7?f6CE2)1~OTb9Vra-7(fY$+jk_zASjOE_?8Lpj#AxjfvvSHRc4C{C>T>{6;5hW zm>gc53h0`64_Syi`EG6D+=PFH$*COq2R#`3+N)VAc(ca2!1+#G4)@R_Z>v?_=EMA< z?etB*|1hE}h}ak66GY{@LsESO88^=U_0xOyeem7lS>}URW2GM9>t{IllAO4dtCiJ3 z(1?pq1Eo_h(XS9HZugr6g;k-1iw7{Ty|$~PckmI*A`v80-~-}OQ~v?nHu1U$c+eyWi~fyLJP4siNm0)~p^L*G=>)@# z#5X!RtUkTj-e~C4D_AMfm7hgw= z1^hZ8S~G|vCj{6>f~ch3`T^t+e~&l|{p_tWrbPOWT^HAHmIs!P){5+Bk#GE5#+#FO zQ{8Ln-u4y{T0OIf-m)kXV)A&`&^$x3nA*QNi@_s_0w@U)50@XNDO)u7>|I#Dhb%RO zn)MZ*kPG35q+ADnk*>Ij06knRW@Y}sWaMdxCmrQFd0=aB0Jn1ugauNiA3dY2?9{WK z+r|nu1qm=cf>eS*)j|>C^txhyMVR2d^-mALZ9FWiL?c+T)HM40UtM8fQC5R0i}h2K ze!y&-Dv$BFWlN=&%V1JNBhK(pm!c^e8X^6YLR|<1mTyzQ6dG`$cVwmw&Qls#yJ4_uU-yjF+A=mzeK>~T|U8Kw_J*>Lv; z%cYOH)n+BxYW&6G**1kTbmqy(mHi-N_3EIg$_wyDb%Z~qM4%G8h3RihM4OSXR#2Ka zpw*f9*d?bEExoSwe3PRF@nMx83Lg|x9RX@3fBg}hQpjh7zvVihol?h_7c{VHmbDTTRsVEBOh zFdCZ~l}?!5^!M}g(T>zMtzo$6T76?IhEg)RP4?kp(QXAF&y~ThDtZOfpeNfCkZR)V!Aa(0RYH zetmhb9*8}ctt@8s81zaYVE&OS(70)1H{g&TaPOsL8eR_DAhBY~nv{;Jq`KNCha+aaFEE-(fC|q?u zLp~F(XbQ->Zk>D(5|__)NTMG>k8ei%Zo>U?B8P)TeP;%PoB>p#_hu5~_&)qGRvh zTF>vv7rX(yqbJSpsXyo0zFu2<7y3RWJg{$WErP*I!e_5x7EV*TK4Fu*y>gC#y^FBKm~Bclo+SaDFiN>oWSk z>cQ;Jct;pvm@?k4{72KUVBhXv+>fvtWow!;<8h5oh8%BO(~b850|+Il+nTxXQNgeh zrchTSrNoHe%kFqoj#DO{yE44(j>{9}6+qE{W-+1VA8ooOVo{S~7rb!iuq>u;EW^z- zmgTEf0;33kA8K&16~?o*2%=}miBbax<$v+LNLr`Uh^Y&qq5sWG7rMKdY&kI(H4X@w zE){d#g_j$&{7}0h6s21^(@z5E``$R5==dL!X)tm&V>zsnobhb=HUF~)gm8jN z1R@{_EMhq2|AF+(h)%Kz9pBKckcO(tj%oWybXzkdGNb`X+J?u6JYGes*F}r9+l&ZX z-5A^XLxjKRC#yoM{#7{ujfRV=8T=pN=>f@=sJXw zcqltviZsk6G_jX_48Xw(-_fV^WGnF~XV^aA6ADl%on=f@M4Qkdwd z>Q2d%`p97l$aRTud7tr~{%)_bw2c4v%_;@yLsqwta%(UKK1t+JBJ~%@yXQYQ;Q4`f zPLLc_7K9EH`8w!}X3V=!kX&o#*zR|VZce0Vn?ue2oESpTwS*UCP01>wWCQHDztN#f zTvE1ZVZQPT@9im5<4F^*{sKuSoVqEa9K#h<%-tpoaTS=)q&+n4gbcro=*M*d%M{Y z%M!~{*?o{fXJZB;0YEX;h^Zqp8+;Iwiva@ytux}$U@1Bpe!rf6^rRMREU9o#^UG)d zpU0JBEvR9Jm)odp6IEujkt-L;dQG9Q^w?GVqpYPg@ zO7kCe?MdjaTcO`pzUCP7WgW(gU7X3ok&DsFLM?lV{E4Bf)0PCcyq$Dbr0aXul!jX4 zJ@sPRbcH9B-oQ$0xb$i2L7g= zBwA7e2iZx{B|n(Cp$z@g-Wnrm$U07)bZp6F^)jxvWDO#b=ang<``@7r7>NiOXLT4w zW`bZuX!YB#{gi@1x{wsV3Y^J_@u-f>MdiRK7(T9#G1{M2H_imS*aRy|D$4wGi5@Ka)8E8K!CJUUN34{ob~s86 zi;4<_>z6{q;ND|(kJ2_I%?@=_iQaNBqiI1smj^zL8um)b%w*!MiWoldK6~ro%T?Bm=-@dA`)kO(p2bp8-(blr z<(g4ciik)A2eU@B^dJ7b@-lV|=X!u}_vQd2vb1pWR0WJ`E!uA8)l#VHp+5xv+-Df0l=jVNFi2J zob3C%k6{>_!{QsGMINuwnL=foC;o#W@VEOzON_iKGV?gTIwbKzDO=X{f?R~D2nX?M zslGhqtmJXRJBj1GvWy)H)(RR*W?NH6-lF2)4aEd7E5nI61YNzn(;x)+UC@Z8q5#&8 zf~+5JX9g&_OX{JkjuL|}$x|GQKDxx;XeSz`+(5z*K51t6UOmTw7%AHS?d3@-+5AJJ zSbZSMKknh+jQA-f9in!zJXRMKYi!X~SFE|VLUEgR(htbFr^SCI>Ph=*zwty2{>F(g z4I$cYAgLdUw{SG$qsJ5zC1G${{$u-fGEz=SkXI4BHSrYT+~N@UA$uEvT&Gx8Y@33a zOWUH7<+Nd6Dfz3@y~K{YTpYeaj#pQv z8)b|5FPC19j`%|Rr#D3$yFU97L`(|!I(_CPQ{~)Dfq%-2NHp+Oujn%B>=a-Mq6o+d zZLxN6^@b#WwjFi{AG-QuEsHLrvLpMb;7H;b7G9A1bbN+cC`V9}W@#z;pqDN8Dk8_&@n3 z$I%mze0I6!3NWZ3Y3muxp3yyHatAG6vNi4fV&!L`0$NCzR0ZB8v<_8a(3#Zw1hD$% z5aKbPzku7zze9F>+CKl1n1LdJ8OkgAbmEQn#R`@R8~@l*JZy@T?zveu(nd+g)EB~5 z$Xx4`$<7rC##rZ08b4<)kPs4&WIYT!j-JYy-l(~5~ z!h8p0e1C#{D`9CLrkrf5R6zx<`=c_SL`09~CRXm3Nk)M8 zZ^<+p;ff#OHv;PI)QTOS&mL9-sD9_JH}S=M@7|w^ef@8j{~QSTvj9;YPMN`yzrVEq z-mX=DOYw>wC<`~8G{W>z9LjWD89v$gxQ5SFN)r^BgcL7%-Z2pBj~?X(8vtBh>O zA?o^mU?nfKPH^NU$3|nVr_sZVT-R+Ct1ogmpO<1N&d>ZqZx-vbn%JXMhlPook%ehl zL(H&r_*ri$GDVp3>5!tuqjTi;i^_BvE@lIDMabKi)#RbC&hQ7nMy;53##>eNJ!HY) z*9^7i6Cgc292a?iESfAZOCE;_F2Clp`26z#LJP>U_Pu&80s#sB?=}^{)UHo_p&29M z@q1{L#Y4B1W=H>^R_XpgbB+1}+Gner+VfBTj(Xl4vdhTvrsJ+86?0rW{~pPFgmmic$<0<&!NB!lowxe`VUGjZy zi|6qiB!})b?I(>mC+zDABIiZRh^QeC>M^dcq-@g2BK&3{yOlMU+U|V%6Hxs4*FyWq z0>yQoI)6*QSxir?K9ujGEMVuF5|i{{wJ4NYEq%u%qF@jsS6F< z%tobOB@it59s9!m1zt)AO(hZWmjj*% z<6%8#H3csP9b3LkAF4jh>b^l3soFS?gWcBBVU2#`ritT=dr$PoZ7<87PDRa-AIlC~ zAUiOD#a9S}&`W?)7E6MWWlsTyZNDhe6D6C@OIIuw^Zwi7h74|9HWLevyn1&@Dv?5AL_uHN)sRXhJas;u+xy=_AR*%Uv4r^&%Tp{#CzapwVcnrMr8;a zi*C7nJl|j68qWyVCvhy+Nr-~WNW+r_hIXWz$$Zt;tKx~s$* z)L!pOLu`g_Mc1K*YgV8Ejo?u(_;r86Pz~jJ$n+mz2C`67pI_e~0XdO#>iPOL&QdhB zzfxaQSXcP@eVr_jBp1;iQ7gkptnq&Et9f>YxBrQAv$5n1UR(-z@LEuCG_wgdM515~ z5y~0bK}4a)MM1CBUqn3N!4e^X{{XrR8&<8A3tV7|^@v{}5#@|mC0Uh*D~jaK5+heg zraLp!pX}DumdpV$BX@NE@2v#*0~t}MCP!InS-T;w4#aD`3NT_ZW5xJF zh~I^r#J>8l7`5Xjm}Mp=6Zl+XP$?~Z=4AvQgEuzX)Ab$VI73o(Z_CjsX^@+vAepji z+Mo8itQg9e@!-5MCWj=F5)&ql1N3j|7hb{%F3Y<|l$(tPdxlc${NR6B!NHB#$W7Of z*rD`?F^ltA<${@-#7*$@#tSqChl1jQpvZlyG*pyW_FxcA69GjrLXMXm*UqI+HK}5%P9b;{$o?(8BhX?1oDP)|WOcgZUg6s~cQ>zmnhT6; zl9E!tVDV9|3Z08GrCq=g$Mys5*8AB5acH=cg{*~KMxpcBAU9X@7O}xrvdE=V6sF_| z=(#*rulRwtso~65%?%(Cs7XKNzv{V&SF-=-ECS=|us~3Fc#Oqhe2da{8*#))%n$eU zjnH;d;l$SSV)Jb+-M%;ykig5rDns%>fZF>aZvfLWr#25SRS)aGxo)=D z!Xdw^fo1ot0E(Bkt9$zSLDHg~KT2H6LA!Yra>`2=M*HgR%ZajB3L5&RB`7i~wyGs) z8WtXOlaq|SO!s}gJlJ@N@Pi%^bg0M9=4s8XGtJ@v_HylNSJzpMGQ4A!_Tu$P9jQHp zGSna~zOo^{Uq_^Keqo2qjJ5@Y@6`iI*HpN9_kay1s9}d3+WzT7==Bfz<(u~M-+AWG z%Ks5i#Ogf-Q*}Lu&AusaXgRfPxG$HQZQL`T_&>)T5)p@y=toAu|EWeT z#xoBSh$6+`xZO+<0)9%_pB%}f_@Zi$AGS+40StGllX!7U{KL{t{rl&$14dLwY3hLjtv3_iO+(NquSRi*U^?xb# z;e$1@90b`F9C98ytU68}eFw8#K^$Un9sA4A8m!xmY9^9ozL*{{KB~Z>mA{Isn&&Sy zkzQZ)Wdc#z^X0_$@)4^ki{vfIw1*nS#*3KX@7z`Z5mYf6O`i+7W1wwhVhRPLB0HY? zBmq?oaEJ{EH2lVYQTioB(a(a21qIn}5XqN;1tp>4QphUO!X}V~ z#LK*!pl1wnS8Q_p*6_}29YgB!FPlxO3uj~ z%d)SUWlS|t_lwIO;!O|UAUrzpRB<%`@tPgs_kgoPm5_o*?=CiLvkYNJQeNa|a}h~h zB*{(WCK_AiX01Es+JYNvb~|NRYnqh=JRiAd?K;Z+ zlZSsAlST>Rqa1VmdRxij3e3p{wfFyUKSym%jAexR65AFk4p0K!Dacry&UZ3@p$ALTshZXWs_Z`7%)@gx{*xq>jP%aZ*IleZZ_qL{MPj) z50?4T*7{7_Xp|omI+;jhq&7Aa*}oJ=R`~~F<+Tqv9v%nWUIO;+Zl8EIjupIgZ;b2H!J$z*>enqiT3$@SOt=>z3b&!XAbRiiYOUg*x-=z5FH4i#1bO2 zAC7BZJ304_$Sz114^IDvt1mEcY7`}mAd+@o?CtC?NRjaoVx#Z!pwolrg`8ua1tyjU z9>A|(7Qu($`}NnCAKvzk4bAcBg22CYy0&m)>M)h6Y>Ax3gkHeY&x=83%CHi}LCF%` z7Tg}e#8hd&NEX<7nIb!EHlI%Qj_49?nU$sK1EJ!tiuiWDv*q%vm|q5qz_(sI!g zP{g%1+o|Ji1KO@GhKS%(H#fL9ExLOTD-cqW~MZ~1Co>D31WM@q3KF0 zgQALA)hMBQ`|Je>?`?Mrv8hlDgH(?kc?N{{n6aY97hPeF{_?Qup7c4%+DfpB-;CYz zU{0{)`XPC7ZSPIVszlah`}!k-0N(S|a0#7j!WTi`Q^ZmQ{EIVpe@*ZOxHRDPlAHK3^@)lb0|%)_9dZ@mIXy3|#L~|61D6TZ8+ZfR$zTQe!NB zXR2Xt0a$;d^VPd&Txy)oGhRw8Wt-5-EEeaC*gbgyh32!}9Pha$gWARQf#p-RR^mx2 z;_#F%8K%c|ZRjz5Ti!NQ>{ML9S`rf=MAIVUP!k`sJWn?)pELcJ^ShX1;VIJ?2>@R z3eG3eqfCL?m`)9@uq)fEAQ&Xn7jug@2}D8%C8<11t!vc^2*m5)7`ig-XhR`{f0T|p z2r{PZH`C1-fe*C0M{F{U_GKFWXzT1cj9u@Ud~8mI4;pESL=2W-RvU?v|G?Q8N8%p? z!vH4=TN@t1i8yevNdI@K?&gy)3vNxERDwM84suQo2!^w8?sHi7EU8*IBQ-M*6#`9q z{)cq`X3Ef^rT?bdhfxgyC@{HnG%|olCCkO@fA8Sr}RkGP}l#Si7#^XZV1Ed#dErqy zuP;1eCa+NyDhnj0bGYyfWC=b!`yFOatw<#bf>Ki0qIIoR&t7=*_oQFh09ExAO=4s$s_@1MVo?mt7Ml4md(;Z)!`3F3$NbF zDz;?SO7~;MSjK2Jy&7(UZOC+MYhGr~3n)s(MW?_m462Gy-XIY`RUX=VBXH`UOkDSN z;$>Rk5X%{9MXf|CMGiw#uuYd{14n&~0H61xzJJe#tu5Qa8|=JBX|u-m#= zAM13kaY-}`3WiZ-CLowaK!~vu%09N1`nBkJsJd$Fe3QCplF?aH6{}EZf5m~?jgaql zoK%(=b z*cD+RyI^kGmf*m+^B=R%mY(9N>uf=J;PGoD-AKrXQn@^WhBNknpnwymVVmwN*LP-d zI{EkDODc?$jMRe|LsZc^n2k>K=EeZ zSJSl-$a?>95a&-q<#+B;KQQNAUT!+YF*{HnsZiO{VUdzbwZ32+!Z@ieVmUx73T>hb z+&KV>S|aY2aJCF=!1Y8Qzd@wB5ypCSlYZjDyH zV0{Mae7U-fab>B*5y?%=I4D(1?Mjy|lVD~hQs<6Gn-@)Few%J0l!`YvnA?pdYH+h8 z+z4||^+uxvkG_39dMR@K?A6vWoBu0|yg%CE$&JgX0l^2HvbUbRt%=T#@WoD`jR$<= zr~C!oX=u#edYE0uXo5m#;{8FsXrv!;wiV_+cj)#eE&17)^CsVwK&?0j?X!_59zsiY z)|+$j;woYc&v@Il><*0l@g2TsBy6vBxR$6R%sRF1<{Y+;;HZiiR2Dn=B2!KjN?R_?n+0WP?i4!u z?RJk4l{;#s0-9+NkCS< zeiRxDbVuJAG8!$&^ok5EP*^H?N31eO7~_*>ODq|?Rn-zwJY;}r1lxtkfDbwZgL#LC zOJP1pI8zqh@#BSC0{z({YGnzN{U8-jrsQl@q9Q5e?n@6COsdXUTy+Z;cUlEpQ++F* zXLmO%eYrI%957HP#sslwz)O_>N$c)|8a?m=zht)!L8c(fRgONxz>5VRsnIGgQsx@v zy@eoiT8;2K@39c#!}uD4ZY#gz(}=KYaAXrX{^0U@aVh-j0nE!4<`{B9Gs$}D?v2}(Oi9f6ry(?elI8fGfI?+&DMi1Fuqe&$; zPCxa>A%X*esyrJlb&H;){no`qrMItn0xTh~{M{S!zTFgV{`>g($ok z^|C`PxAcpQEC{!M(1iu>DaSTgC9CWn+KO(g!-a{wOjk15$0BE+y;W9BfP2a#^c`Z0 zGXSEZ=n`r(#eSMtK~~kJyuoM8?mWoSIS2l<4}v~&3UaX@X)%?~MnBIDXO;CMLX$kJ ze6dC0=~jCjrnj{QopI{n@JKokTC@r<9wF)WBua6zmuxY4hra53Qh~`oxj=+eI&|lSG5XJ170h z408TUMzwp`(t{ZI`EuO@IsY%!l{U@M;d0^Rth1PW)Y(|ffnB~5y`~Lr&^#YV9G&5q zaX5!b#yrqI5W3laRX=eD3-eT(F6rvqlJ5jn7Rbh+@+N1wQBnKS=>k0kCrpcf7oz!C zB>%HX)>2DSL+_Uy9kCzymhT!_@>2D%HmQc2qTb>*sG1)2DNnKB(z)gG@x6K=n6}6( z*43rz+_NhdkxcTzJG7IhE%-MK5`GBLI;)3h(eK~0%{2Te+Z!f{h`z$ z)-8>mR*RFn>B*@5^sCh}3~`K9v4KQ&!Iq{PNJp3r`SHRC7Ol26Nqay|~Cyp*zK?+wFb(x40OvUFZ1;w`FbfJa1TDg~l8#=Y@CY*lD5fhO-QiJ1z|ABU4DG8il4@aP!4NS`kM540 z5*~gb`I`m}H#dQeS&Ay28pN!jsBDveP`zyxT>=aq8lm`Zx)>F)X#x#fe|f}A2>?0j zJC!Xx`}(S~wEhOllFXZ`^vY|@$0tsYNQ9kS6N^jQgX%F&TqRMHVMcd`&j^KHZ8O6X z)>{-?Zm?(_IL%~y39)oSU=5bXH^iD{;YwNats1d3x!H#^*XG`<=N<~vH3-6cbPdKK zX7dk6%Rj!?Gdmq$plex{E{=^?Sxo)5zD5kNKyjOm<4YG$xkHN6~wcCDdr(v zQyYJVg`E&5UL{JBHpb|mF*Evm6Dx&M3aDt0#;e%mK1rlUmfvjViDefM@TM-io%`fA zQsMn1S&=f_H058mPw-mfC#yKA&GWM<>>=RvWoxZG($OHHIrtQXyvxRlidz8%*|ZH# z%#8Y{p>s%j4=andnm&^B^=jgT-DsL|Oq&nNjApQ)r+L{gal!ZM*$)JKJ%hB6qZmTt zdkdB86$;gcW5o0(%an`4(!;_nkZ}str_EA+-wnnJO-oytL0= zHL~k^Z|Aag8Gf}LAW(s#FpnUPSmIy_p;)1cZHEOM;)XbAjOpVb@~&87%GI^l3pkSP zY`s2vVxXNTa>u&||6$_R5+naH^S3oPRAf-#lQvooTgAgK^%y-K?jRHd=7C6>j997< zc96inLW^c(S+Z~QpEIM2>+P`en`rTHk-T9Pu{#?FUxUhrZ2M7-Gd_MWo?xhT| zITpi%0*(`z_R3ixu-YuSFhtFQ0=Jud23`(Fe~$(R+GPK!!MfDcrND)5)JV=Qy+dx1 z-Aa-Q*VkfVX_?25W^X3ylrN#nU#CCV7elb*NycO}qjytN@QKd!b$M#bR6_fVD-|}j zd3oIS$`akGv0C@Q@Llsp=}5l&SMKXcN7)*9=`GZ|?V+;NlBop>iUA2}Sc-{@PtgNb zQ1my}jfoA)EP>Mub>@J{lm0|`Z%VRyaRKHwvL%Z{+5cBh%r?ZhdmW6!l3{qhr%XIh8vWQ6ZgrT68O342FNTM6ODKE?9Pl!rQ z$yjD^)7|UhMrTDCCn8qsKM@p$F$DB(kqAS$VInNNE=T{Pl)>d}HqyWfnOK-WH}b=+ z5#C!B5iU_>jO?9Og41>@f05W6>jGOn4yrCl9Q%LZ+6sho4Z(xhp0~|uW^)~Sw;eQv$ISA6V=t2ktG213V$r$l8c$QljYqW_$<^G?Z&&Ttkx3-I5Z}5@UsXG&m;~et24qPP4)4e%cF-UaO{9hzf-M^dMCO9M-xh|(8SK`m3XLqs$<(Y79GHNQ zC0RB`a(HIrn4&f*qS(b2@U+f1f75c!KZF6>U%z9V-fdJN+M^v4BbS;*4#fc6qv!+% zexuTPJ=j>Ee<=}=!%x{sxE|ivd9>UFm%g_hL{wZ7`#z_c3Aen9YuJ82W#;&sgqNy5 zA)y3!O4x4C9gop${akTXSgSErc;>lj>GlSn>`ZQTcBC0vBs6EGvtc7*FmS0C^+MU! zR!Ij3)20NMR;%s>=F_>Z*qV%s0D?uVh?sDiO?|ZL!zh#BOPJjAjeLZvI9vIZ)Bmyv zG`wPTCSE#v_)V}`@HY!oVh>;b)1x_HF&KL}^6iWUbcxiPEHl_9SM#^19>PCrDl85vsMqRg;J(htq(fbF(XC9_%%fO>feuuws$;7pQyV5>;m2B>l+HfP+Xd-fu4cTO}EUVfoB9mn7 z85ucW=PGSoeayMv{wI^zb^I^flQ)Sx5N1FC$Hz8?BvoZSxPpCtnzt|^xotcrx6{3@ z=*RP){Cv~z_MDeyFgPD19j*8kgQG0c&m>H}EkLAGX3$YZq(r<{&vB6O~WL zpGRkRh#y~*(8takTN7d@fiN+2ANTp2=2e#inlU5Ehr z19OT#h@Dz(H)X2h%<3aFyPoa(ETJ;?;By@6*>6D zZ>RM99Rv3N8C`Tb_e0%xsp1g+@hUu+@#6ft2L3|)sQ z$`ntGW9j9@Q6w`i`M02TtHf~I$5u>ogAzuygJ{mvC=yL`AWtO{lx$nw+*Ib5n3*_L zoK8Vj{FN2K&P;=qquH}8oyS6P#P_}JUZJqiBH!5~a;PNla~efL`(Iy#_&i1a6kGTj zGEMGOVyE7~?G}F+*4=j<9IxUj$ z=z(q3lA`PNI|a#G{?uoqE=iYu#bw_>)+VN4(l&%o9VO5-{5F<=zC_E z7U9?BTndwxHk?0d90>fYRv>M4<2G38zVlzGxfE*C)$8=2V#&Hf{tCJvPW0;q;jmF- zfZqbPz!zI@0pGk9^nX84i6G>oBo#~ z{TO+nqpeyKy(HJC}P*TN3Po$ zQ9EhC*79_VJp|PkY`7Fbdj*DlClpkLQ5BM5aq2fAN3;4fi+0ZCh*kOJ27?-`IQ2YH z6=Ce)*qHk7Z=8v$Dp4XgLxg1_6RoJEK8~!PIDjMcL~Sh^NWk!IB;OqkwMeJ9_&eEr z?1=eLVbvs!tDcdi6Cbi+^55Yx`a@tMg_asgm{TMXwNcU|!~#A8FQq6Eh82pxzCO&X z%n|fSI7H$%oeADYbh=zv{4jU z=)!Emc!CFk6}>J4T0tf!3Ww;|h@OA0lTxAS{^T;>OC`fgsFH?b%d0D|u$F$!2?ijkeQ&I#(8iwxfZloKLuA#d@q)S0Ssky`Z-M_HUI%_|Btta{$ z&sf9%MWw^-x|`x_^)%_Gk*F=DGwn(I@i|Scvm=bkj4cLAFw>3;-6iP{>1ABg{ke`W zVXI(y$NW2;)OInYhNtZMD5d8hY`2?OaVpkL+@{8XKem+vvwPG3&fDtSYS+T?t^=YTt9-{szcEL;l`?Qy69g%a4bmwTFJC)q6@E|UAjRVZD9SA3 zOK~~~mB#)V{asbL)Rc`on>v(0{Mvg?gMi1-*H^w2CaF7Y!kEbiYt(4a3KeBQe6fr|t{pi|U|~f7{=NIRD;j8BAnRIxKyIwIHa{ z^CV;}!^zr%F2Wp5IDksX2b?^tC`X4h8(mgm<%oFk9_I+HenH_>ZF#WOahTC@6Q9bq z+$bwdG2C|fN9o#q$ILg7ETLm>Y6Uc>_FqSeUT$=rj9z0jJ8FD(gCKpHL4Z&}-ULq4 zPo=v2o`P66wIA_Sl{7A`f-+nnRG@9)8KmUtOmA-EJ`H&4!H)w#VuBCC_+Ep7$wpl) zFviG^05FRwDsOg3FTN1gxPKs)8j7b*0fKC5dzo^z;y9RN+jJfQJhqgD%Ik)ZO1NEPU3Aezm3T#TjWu2mbwiCRh8CvTWOB06e{FK& z(T)>m^RqPw+f{f^(gb=ZIKpCettz5p2WImJeg=)#1+<-#7**UV-SZi!{sqj3dY|MW z*B?}DJrN>Ng10Zs<{o#pGC1zmN0ev*MLLC)d+s(Ld=ioBEPH`<;1qoy{1UkbQ%pG5s+4^h);5X*kC zqC{spJSRN2LZ7xeJ{quE2Z1Q59AhFSzTuj19X!nR~qm z9zkKGXAOgzJeO6^lSkNEgPMp!hNSy+zD&+J4-xV^XW}UaB`(6@T~p}K)-|6l`M`Z2 zGab-zGF`SrI31JJT_txwvbXAYBohp05H_#4L`)rX9N((2BH1^IxueX{C|7(n?WK+; zCi#GNj)n?w$PAN8_=aJ;`MX4H+@PA=A|^GYjcFd< zo30xaWP@YRB+@Stf=#)3TC;>;PlkaHHlzN4T`>sJzL};}Uf9ba`gJnTs{CH481hqm zpa#t)U(amihhJT!!e(q|hJKCYR3C|4*40bLg=tv_ZvMm78D#vUi?u6FoUNi9mD4N` zc^Do%UDUW&IIlA>heQRVp8p|2{!Uua>&j@_YWRCTTH#M5jq4fETkuAHKwk3rBx_#b z&?}lVbDQD@?}+jGf5N^XTrsQH;o2!n5f|)jC-ixTV4-gG&xF{smfBJ#Cs5gLU~f=F ze=qBx%IPKjL0_F^n-qG1`&EfXAyNTHE`&Z<3l0aCCBHAWvb3XgH8nGyt_+LN4$C)O z>Z%K$=S)820(wOirdHC#ad{V_@R1-5BVo400r0mIgyTu0%VO;YNeWsHRU2=KYKCn{ zBHo4-yWn%9J3J@ncv8Tmu1Mc;HNlxY%-S&Eo4$~2&X)t>e^|@@!$c)Ps#mdrImuy&Vmdx{^%;HIaN>*= z=T#KKWgvD*4|uJfLjaCs!fPNLx_JF-f^b8chohHFh^mcZH(MzQBH6|BO2lzFinbrF zx<_W^JW16*yOd)oeEB*dwUiznl`3zTiBa08t@N%rt)D*J zElmh%eHg7pJT#3@J&`Z?Y_7q0b-C3Y=>!YSNJ?@NoZddZ5&*K%6 z_NrprxYuTsq#w&Hs%c?nqnATEq1AGCpx~Onz*osbmh5j{`WbCILbZ*8>YFHS-XKXW zsr2i64IT;0q*{W@ed<^|2dxA_?BA3X>8k-VtnjZt`)qHV4Dg{h<#`}gPw2nLg6a$# zEq)L{?RQOvHKKXr2An`@89|tZ<5`lm*l#XXdnK&z|Jc5LjA$$_aiR0RH2C${^skja zg3;uG)E8+0MplQdu>nAEKdgEnO7BEov(UJeA`?q|BXqPi+F2^=>yk6P$h)h4$vHXZ zt>ylC-ZIFUdY4`&KINKDd1S-LFj-}2R-7MQJ0O1)Lu*7yV_f;Scfuh4#%EAvslZaEr%&k57J)MD74CtL@0`#TD?jFI$)oVtlQn{i?6y%pr=@<`!&^Dp zzC7D_*Sj%J2;(N`c&IDG=VK`n#EC(S;jL}@}51!pa)toaRqHx@;H>U-trLa zjA@t?U^`2cC`3{N2^O^T=jRnBRAYeM27;3|Z6nBwpc7|sdh>)yz2lZe9nv^sreuwqLDKKd74$x@2Wu zias~C$~8TC9>>ulIjRq=w+AM)zA*RNqd@%yPASf+k^wwyoaS!2L4U?kmEakwy{V#E zB>i}vEFlC7G8jD6l)OBE;Y2jF>$#yv+I@ZvSe(O}Oce2_o*gXWhrf-u1nFnq0&;$S zVpaD_7kEqmHTobJKOc5*K5)M>xt}954~V3-0(5CQHotadzSN`Pr6MVZz;W*{2k9%d zFdfs}V8^>#)hNSDhunky=!7fk#xHH-MR zkR2oDeowy!hlH7~U9^N^5IQF`!I5)uA@okfMQ%olAE+u!Z@fejW#;vnD!El}aeOjD zHM)V8(8*Jn2qsrxExQ&_=-QiT0^PyM>`7NR#>gYpcPI zfez0os|$}p;b463E)bl4RV(#fL8@_2IrzySpxTIG7Hkf;y zGXYL%e2@Qo+r9Za`05_vNdBt-FWR&M*}3}8Z_bpPDyd|2Jkfn>Vk6u?8J@ayfo?so z!=@;4#lb^Z+|DsHDYgtMHn^C{eRfpK}Wb=if^e^&hs_ zUyc=2YltgCv#J}>BxOk;Y;FTP99h)Bj2l`zGwdP9O~IplWz;E`vL{-OK28-X6HKdX zY`=QMV5_TT4g_SR)$deActH$7eWH2azD`d+ccrfgL?Mpo-m>CENlTL^J2IIf>4fun zBbu{h{+2Lx^P&QuXHgW)w;RO?e%YvZdh=t;RyU2=RsVp05^F9Qo|Y;rYTW_HN>%ZP zy(28z;y-U}7n}d)O7z^X>=CZT!KeZKKF%E|@Gg&chDuVsqPX7-!i|2px z2$=Us5(NyMe}KoJea)h4TewQ-=4EJs8H zIo!GbZ3?DWUgQo=-I~)V^Lpx@7cf*pdJ7n2Ak)Dy%xWWxUI-R}uq|MkCG#!xSkNP4 zRLIm)h3Ocen$vEAXzksG8jn?*PeY_gnmSWIGEFvTSQ#W2j>-Au@)(=Ku~2ZiI)v<= z4IX?S<6)ZrYe?>>gf2%l-qP+<1*ACw@X_5U)mNc09r^zG^Q9Wda3wFxK$>`9FzD4%X9sRWpQLsnEC+?E2( z%jW7C^!w!$0Y6-cFXWvLIRlTSzSz}GEu}9c)R!2Mg3L8(S}{hTmp13EDQ+h6&8)X} zt!y-DPFT-TGCrK*NMgfe+oN1%#sOUcrMpHvH|tN^kgm)x$#ektGSpA~cpXfPTs=rh zI7pr4JVrbu9%ByiXKjBvW;Y5$-^et$c_w4f%ELUeAa!j0Qe3ixicJ%hw4kBsAM<$d z+z{C2Z{mUs*uS0}CYqW+=edE5H8x7mAQjUb8j_F7rNS*qQ-9$&&<-PQ5kX>wXuS4b z&SS)v&18A-t)q=c`9*##xO=_t`@mw625T3JJOJ`0Kp59IIAsEba0lJcV-HViuc#&B z@lLpibYQWwi}fT9l5r}Pg$Hfy6;F8O6V5($oO3I{TcMP&STc{nqS=mkqj z2jJWiykfEt_H0-R4avAWp+@S((FiSWq*e(+VgD?*?lW{}FL$bPbB7{eDlk;86_lTD zlTI5fgJ{nvv`kzIr4_eYjnAF=f!jGGNqLqBadjd#oV2dM!$hFDLPna!N-DvlFM7+|^UhW$ z&!Y>eEDnh_?$0aGp#*^Ho=JV)zf=XiYY4WVSPWjZY(`@Q>K|ErRq;sky^$0SekU{f|G8`44eb zNgp~NEygnY7o|F%hs&p>%b(pVj&`D@+12mVwtUptQ#HhhIT5O#P9fRp%JlZhl66jJ z4PFQ{3f`%;Of1hVI(%w*Kk!|Qk3jW0tOJ1Y`B+b-uqX+`L=9si6EP%#PTOoXf!aTq z5>9LQ)O#BIvMyVCkToR%(gMfZZ$2t9!IJ;VQAZ2lu!-nKn@jBxOBhrt!O7Lh#da4g zQbi|JOnV^1)=sGtHAuQuppSUD$z9u64sSZPVj*fwSCEc12|DdG&mQr*w50KQ2>KFv zS*W}}YbSXK$dEQg0@)IW8MAfv!7hXKi`qED(v6|P?xQ!lfoT^-EdLmm9S*r~0!aNDW%=sWk-Y6(=h+8toj zd>c9BjclEG_>#u(c=y=HG2e+Eb!dx|0^X9{U=C zjffSOtw^IpU!h!qBrDGipTmrI)}2^d(X*^Zrd}<2PFHL}W;0r*nr)bfHulM4bEqOy zkHVgD43wdq{Q{VCK*FSLC8DLHV#;Ero*KR}_i=_M=8GJ@IX^2xmlzI(WDMpv zbixi9k?%%TlRo{coC}}#UB5zb`ARMF=-bU3_~rda=Ul_lSQI66Iyt`o!31FDO!&Fz zL#on9COk-=r*rk+tf|Bvf1>?Bd^$#SihoohTn2kp-^KO}q|(mJSdm5<1CZKo zg$RVhfD7_RNX>2hv1eijA<64rs6kSYg#-PWq$$rbR#21rzKY+IZeH|rZc4y~>AhY~ zD<9vnE@mrD7H@lJNb+dd7q$}9Kvoyp5U%v3rth_)+MbXy=>b6yNZlF00-ObSEVqDj zcv=(v0AmL2>tuu?k^JPEmItd&w71?~585D8mI(5VTHe?5-O?av)Vs*N=DP>Y30DqvI{0I=uZD>@G$ z&U5dD(FFaqn%R$tz^p=szZ`cBHkp6!B$M8J=~bdOyAq38a$|KK2_A#w z<3;aR)am&RJwjKY|JpJxCLFi6pT@u@>P@hi{iq zB{9G$4~Gv&D8mm+O3;SS;!=fwAS5YMPn(&2VSl`_HAXjJt~q=Rs8)v zE>mYqje!X&L;y<}<5$Ze=~%^bxzZq1FdWkVm|CfIm=H>kncH*t6l2|eTylF1-I%y> z_h{uIL%o=?KnwuJWlcYCv-g-XU7`DnhsA3;20w3W>N>pk1ze??I3yrLz>)nDtEa7d z+ZR(%M5+}lc~&8P^AN2EE%IdK)eg6=P`k^|C=(y>z>X#l4NLwEhn|5;m?ubq(GG3D z59|{tyJ##`#KGc`OW+DU*x+oU<~(o(V2J}B-0@EdsIi7@Z;H4`5knTR?X~1%B@1NM z7PHa~i$yH%T-7{HHGJi~Yv`{Qjcm_9Cv-L&1fK2;i`>3e&ne(dZYRtp$OZ167-pP6 zQucn@LA{uC6VVN_s+Q<0Wml%X%Og!gDo(jm*6VNdH+l8KEal7oUEgDGO{9@E%vGCV z4G~+tIIg^K{OtkFMMlxvWP&OICA%_+`#$&9b4SjJ91hJsZo~&2hhW+H^zD{J!$OJRd%8^!fU5>=;-(AhFb1YOptT(SY3+ z0N-Nk07>_AQLTiq@ii67oa$`4R(sWpVer51k#(J{!iAfElvY zin(OsmLPcuwt4MJDge5r6X!VGZ^dtE+qPAUz5hf zok}n-^A(pBmp0<3P#%`5k`UeK9EikhCo_&W%LjKFf!Tvit9``l?LofU_>sc(r0kB5 zkSSN2f-He=O4gFBj@#h}*>7{>RjEk`Jv1wncdg(Asb;%0-Msv?q*3C1TSR|VN)E-; zuN*(H{xSV+(E$qtoj3#B^er>?Q z8)usfhVHkwcWVCZNA5VoW(YTC zpL@@$BaCVsk`2C>DWsbm@HzfmmMuJrA#bih!>-moz*e*%NglGEJLA5%H}s&tTsx|# zLo;lRk^Q9IG+d`|FLx^lVK#8=&y21nh%i_>4Y(82fcrXNqtr`-dU5t|Wu`oECOln6 z26|8)_uDSFoPO+L_S#cB*#r>~*olc+AT zlctxZb+-u;>Y=CVhOowkNx8-o7Yy7N$heTEX*$y8qRWP1-#dqHl_97|HVRlpQK@VB z9gQ6j)>t*rjQyiwlIVKN5b%54+PC@1pWSs-3l&`bzg%1%VJXaOI+`?V?A$#%GayBQ|0EU);o%)?Y>yf#_IW-;Z&{@JGwjKM$g!nf1#pEp_NDf;AYEf zckpy`|I=wbZDD;2!?Sb5dNy_wH??l_b3fc-@{jCwAIdLH%K2{tKZ@-@TQ#p*>XK1g zRH6~tbHSjY`7BEW>_I{j9`*iAgGq_X^3cJ*KPWks9yl%ex;op|R0#!tbN4e?#Ok24 zQDBl3rC?F#tU7{ivW1dNCgcy5Fc2O5MGoJ)0BTY)C#S1oiB=axzaffMLL@Zdm<6u z;7`(6Ev3A2?gwU2x;|L#{>^2S3&@n$cCfV_^6Rw$!=$8B?5}j=YGB1{X0=z!(Y#BU zA=ZTFQvI(g*SExJ?;MT(s-p+;JfaJZcejc(`>6eHtr?OJWq0l5!M zVXL&mYlK}fTA=*_ z8KB9D-~$$-Muz?PZFh(2$)BM!y3tRiA4yq^8>v799JE+5IJ&;rd_QKGBsAZYF?%8`%rN}ZA@ZvQ zYTZ zoXTIr)cWl^)n)&d#yWU*E#kjArLnzjTII7~P5ky!@tlGK9a zOmn+Q^8h_|nf~AI{lD1{f(rEn!Uefhn35%aDX_JDAMz(>3VpJt|ycWL^+uy0rZOX3D>xHf5Vn+mfi%Nj~jO6*sl zX>J`4)-CeiihtQVosOsd8QA{v=g(lS|K$~@Gy2u=jgRNTsei-%wBzPucXzr0nSHWM z;vb#`Y9vw`vSV_7kQpMJIph~SS?pJB^%^WMCer)_*5ttk?KpetB{d$uKEk zxpiU69~Ga5Bu>?&AWy{bt)4@ zBp3A(R)J$i+=ut37qie&=)?1eB^Mc=Z)%gCoh*$jl$LtKEl6%QV`)MLD^Dr8cY`L z)A+_rLd}yLfQ?Lv#jTr-vMetOx|o3yGdoOugM*#o$!_SD!}aVrPL=(k9tl%3r>~A9 z-zI&42>fzwRFh2%ty?BO=%!~k^(@s& z8ZC~Umn&D5NfRekx+^U0E~?$4>v{maKAs}VxJ-gW>^${-JwkNX{7L5XsNeKLu?=~t zp^RX0I`;#NA~zw7V{ovLg^=bJ&Es45-*Y1f2MnX?(9KBERlhRi8WAfT@XHgwrl+u0 z4GiPNk24yP)3hvHY}w34LHRIm&>`kLed)$671=k(TfWd?Xh;~EHq6@d1(po=0$snn zfKF89)FuHHgHoAg&~e?+gn&q>31#W(Ex7E24Ex_WFzW+S`xaBYiz4F@6P0$eug(|t zaOaVaN&~q{Q@l<}+|NdRHcNsFk1_&!-igMN=wi5Otn!rfV*xXYTEKcbtiXaTg}&eW z=_Mg;y+q$mN)9gqE%L_KIVqywT%AIHR6@@$C$r+LV-r=-(5c2+S#5sEINCQD<4_?a zH=K5+yd!!JnIH6_AX#5AJGMq{f32S5AUuM#00`ZOXrioFU5N$5v;{qJQ&Fo;Vol}P zgrBMO`E&J3KGLO{V1>L#maCncqsrmYG6Q76bMZvvJ++XHzwxIxNR%a0j)*@H zbQzq#t+0^xoZ+&q$m%>zbyxY=Z)ymHkmFMTlaQ1aCp8C>HH0QhlWXbAtKGcKU%X@) z8R>X_+^1_AI-QQ*kh#P=vvlywsh;%e(!yI=-Sqzbm>E16?U-36;78hc{io3QYtN+} z1DhibB84Wzif%H(r9fTEQYtb1a3S^LpiG_q8=n+^7+h=by0CCxpTl0ZBCaBVH4=A3 zk=wFVH52HV5dTy0h=h~8^$PoYSEDl8vI>n+JXA0PdhYMY>~fH>7Sf)q*Dcne5NVprl?0!tyu;c*a=ia&rc!c0WS4?VN@RD zv55nk?0(gBA#ITaK?10Q^m=^J)iWf2-jc`lqF{i%<_Y3z){0U3?r=3(A4cBPRX0wp z&*!L^vNkHn!Ix6j6L*ZrV(ai^ur%NxVGhW#l>3YV!cg<=F~_j1<#OS&1nw(!u*)@u z^4rmUslY9JOSQ7^x7t=Gpzl3d4#_6wsc;u#&8^XRXoHSZ3-RRuiK^I0nL*hspT9Nw znOLAC)1k;nLYDeVjO0PjK7)ni74Oit2cp1dVgdp_w%wKEMMGMmD4?I$cxi8`MjVpI zI0K@bys^7R&WVXV5Y74K>)k>mZs2ZqHCsA!$SmP?9TQ^7F%~&m`6b*Oq<%uqsLaqz zvr~5&R>3wL@R6vW=kpp(g+R6gL_qEVd*Dr?Bu5xqI0B;1B){~a$xTnochRQ1@-Wh# zcvoM=dGXKL)feZ6+c@|W(x>JA-AU&fUsBQWGUNkH7P@&fRNy?~+_g5@|!klv3uIWHNvWQPTi)h^>+$sWG~o(I?$bq&WwPM^?Zru_L4uo^cU(^ zHzF>M|5`+uF04Tz{6vWk0Z?}PMRTX8&d!5Z zSqTEe>4t9O)pF?_mHsUito315X*?)#AV<*)!rS* zdN${y6D}gpxt?>AHMNz}$2TO?DkxH@&@9*&4~~mn z3dynC>-97pJRSY_MH&CbD(d1v=QkAk(d_uKZ{zT>oAc6QS&=S^%3Gd|5WYYvu_LC| zcn^ip)3~0zt5Xs}w9 z78|v%j{@czEP6k-s7}{UA*^;w$CGy9hf)o1l_+sPo_vd^%0+C(@!Bf%AfBZ`uj}x6AjhtMH zm17BT@mcnYYYYIZ$q8j-R2Eb0-i$`&3wd_yVt@^{U#6p!92Qa&qGFnezeYNXPCi)0 z;$ZPh`3MH|l@GdFR?#oGf7J%pAXr!_`t}I*{CFq%o(;ZvxzBE8C^rRFpAI0OX}`!q zgHCLTMvtiKOq?9$fN)~I8&J+que%_fVDkLDlanHHVI<2Yg_n_KoE22AQfN;bl<5mB z^Ad32^>S^Lzy_~n;vz+{gzu*j^?PTCMs=40+vNg;G##osXXasae3J`S`iyQ%rUz@e znIgrsE*>S=!I{5CJiEVp%{_AXOWp*#^6CB2-{7vBZK(Hs$kl7I74C*&YV_snJ=?fb zzm@5?JuvKF&3;DuQb#g#x?1CWG zCqID6bmU@q0xR$<&O_%k&ePTK=Gc@_*4lvOTrC^zUT}Fdc28}EGtSlh8uSUn$mgOD zrf7Zi1>H?#Q`OJAb4XaKlxK8UOMn<82C}+5n!D%Q@*h$GyN$@g;6#?Sm1VZD9Yc1W zI)ScCy^sIHJvd@;k>^zI{g1`h0by~^!CR8_+T?UH;4Leiiceph-yqiN9SdV22?KQ- zVw`&Cq{Jt?_a2N<^v83|d>pQyi=HvNn$F(~dCUES#-Y6&a~B}(TwQK-e{E?j&0Yhd zrt)aRSFX9@)Jf)Aw`!{8V%GUeVm+3ScHO3+!XGQ*l$Y$tAl~Iv#Bts0#1SjYfIW&` zleXWKgd?QmBBD`w?zYo0ONoBb3$dJ7VX6SmT}$&KQPAEfw=nQm*u48*W+VC#U*q%G z{59OO&q^eBQscRE!^d4{Y#e}01<%E#U^s)plj7(aL0_+D^DEy)OQ*MQ$+Twvsz8?v~$+s6W|O>evIN{#)OpGSV$t`R8hl=^6>3z+@WA2*;%4DNoojN z;WhI_48an>a4>)|7HLtI)V6rs=Goz?J`R}XAuN(& zM^Pg=y`k6US>7f@a(-C?OP3T4DSVA>oSJD@rLgj?xP{GJb^8a(ubsFBrf=z@Fi8LU z(UbkJdfxOvQ($kdQ}*K5L0PF$8#y*Jb*P2fWoZsKr6=u_7Rq*)+ECjONy#9hT*6UJ z$o)GeosW0dRXQU?0+^=2{O@)Y@Y9%B3jWY`=>5}9#r3KKbaQJGri=zBDtpnj7V07) zOIhY|Ag+*-1ZY2mO6X9oSR!NOxCnyg(0O<*4EOb_Mw(x|In8VT)&+E&l zTIa*G^@_F3^BZ|+9(7cU^sYY_t3eNNl_Z;lJeV)UEHKG&kk#nq7MIyvb(#lfX;D_M z$7b8(*-ISQx6KsZ)gAD5kL(i-`eGvF|T`4fj%)y0DJt3zUb-a>BK~5BY z_tV!;q$5Q&F6gkA)@Em2X&i1ncsID8P}00o3ec1EzU*GPQcRK*qv?gq&5I1cj?rQ- zMGRM}EV8^DYS^R9usNHp9Z5h)TK~S#o;`d= z&O~n1q|toYiQJ{bM5f}V)-))2lve|ZC6{n+HtU|Z*EY#*Z`~{G((kuk3*Zr>{y*;F z|IaA%2P2o8Zzy)A5fvm?CFzW3n~C-;N0U1 z_UehG)zIqgY~ai3<;(UIIPkWvWg?V@%RRRpG>sF+(ge3d^UN%DWe$3*{U^h~LPv=r zJ#Cc2mXoZjvazU&>!g^f$cbgnGKsk6FJ!uJ%9rG8)W&A|tx={xp}TyZG7%iRoWz_Y zG{pFVP#%dGA}`^>Ns6MF&)py#$4>QA2fLC7JD*5gh65yi)Csj>f?iB_WVn>Z@g+i} zB#tCx*j#r@SaJN8S~;Y{2odx%iye7*6obe7K1XOe5mFbd87@EV`CcQ;O8w|FT5e6g zGlf}Jf(qexcpZ7Dn)ocj!}}BKl(I54xS|O^x)gk(x1sf6GGuC3BTstwT0J*GZ}?G? zV7-U=IuoW5!Me4hE9GQy3}l49f38L;l!^!$Ldo#|zAJmm!a+^*+$)~v{c`y-0rt1D zPXx^d7vjDuOskNRD0u!-in+bPNAHX zWl=_ZEA=is++JItMWLR4^1w?sc6!8RA*$_YfIY7NkGJPnM1JfAkN!5>Pwc>`#=|$J z5%(;N(eG1r#4hXXA4M{pZ>DEdg>tE_L1W6VPk==+UGT%uZ%zP z#4I}6^uP6tp6@iv8CgcZJ$SEnuLKv<`sLxSAh7#(#cignaVVKWMiOZ%FpC>Ng$UK1g|H!a8{%D4)NZ8w;LZ`sR&PQ|t#lP_s= z!@RZv$@Qjuj~vpiICbdcET^g)F7#_v2t;)HPgt(s^kk5#GM9CiaNnCB{`(kuR#DgO z7Ov3r;=j6}&!{D;%my~rT6d;(leVtr_DdEn-McO!kK^=DOoaC} zQe46U)UIB(yQ*C1oI^BQ5UsTk$nk$7mm9ue7S z1B{^%>#f$YDW&M-l~tcM&(Ue808R*_0r6Z@E!j7u{|pZxkA55hd@Ez##M_uG*L!pq z{!PI%4)=6{TJp4Kvg${T*I8Ye> zpO*r&z#|tO>8)G`2KFE!)MD(yuwXn1!|I|<2i0I2#x zH};d)#`r0}>h0m@Io^%2WLux68T#X_$9gkR=V>G+xR-}csy_-Vv|j>mm2VbaumN?< z6{<7T?W42xxLKWPQtMJISwzEK6g&y~v0a!K79mzjcb!vT)={NPD;GQ-bYt$@Fgdr+ zB@i@mxRS_}cxgFJZ?SBZ=|e?cN8?@3U5D$gZ{%`tDU`awXrSubRDgBgJbm<;R^9pB z#FXGojgxxhx)-PkO%0PkDM`=-T|n^=Azo3GLI2ypJfv!7$AmW{xuy^5=}Pe@4u(8E zT*8>fB&^d~nplUvon&v4bn}5rIF{kx~2mgFfhzY4eFDA1i9u?-$t`+uz;Q7)@Q{)-b=JZa` z*IUY276H|hmLr43b0_^mN7;eo@7;C}VpI+Ey!W$StLGAcqkjV%xK9tTbH1{}4o=?A zDv#l)%!e8ADW5oGapOn8E5-1d1&&sXP}StV0G0Wio#eN1m2Gh?4~m0IA_CZAGH&Lk zxsi`Ucz*J>M%QG=O&NnB-)202m{ATLu>v3|S1p;&zwIZs^(j8RNsZU-pdmn8wX94oe}2 z`!EOWEM4Hp$_(!SAk`CU2x_J2Y}&ZW5CU2UJp0%w5{GD4vcyzI8=NcHTZ&iPSXl3J zn$GWkvRX>xg~zI(+9O*Jr2Ft&-x{iT?Ug%~z8)ORwy=@$Kk6_V$!{1ZsBYVD=e=)I zM`%Psy#B9=gXQ-$F&^SwNy7o+L#GMm`YQcmxH5tLv72NxX(GF7j<2Q61(AZkAd)(Fsttd>L0aIZKZOCMvBhM zE2KT!y5|D}beB=r$F=Jr-kuvRMJ5RnWaI#I{0 zg(~yiqUlHUXRj6-z_zkM>c|;|!;+b;02tDKr2zvmuU`9Au}stJQt<>aY$7paB5psv zFhV3pID`u(S=P#Vsx}nPTAW?S5HPnV{Dg^}K|Wt-<-$j#obP2th!VMojiQgD+o%%> z2Zbu@JYUSfAg`APUr30HQXxE+uw{6OgNlB)({H@p%;Z_GI!OVXKyM%#=)Q{Dk^*aD~C{G=6N)fzL+GYFBmje9`O(gF(I>Nd{uNR~QTQ2N2<@90y_*8*Vx+GraPI42UX=wEZ@{n_A_quw}+|GW$tN z*ps|lO^ED170H6F_?OgD@vT)X)wFoV#ueKqj2^Xm6CA9cRp6 zYN~E!-%8Z7Yxl#OYAi`JiEIA!307}m>7nX z;U&2N90i#O=A_!&>}*#YjjBB4s3@{Ym~3!Hu?$`liL-@xEnHQUruNG44a8I#S||n zG*j@`yT~}(>$);1q}$ffb~8!Rv{K19a?fav;aHm?)$k(@RwIW>D!td-g+Mn5>P-*0 z>@J@BYFOHNx2>BD>~!`1gp|4>QT0I^N8dxC7p|`NcP1vi^L$Z~3FcAyb2c`^`d*dn z8g|-Zc|ra5g`4z36ljIMsQeV^bajp~jqCeZg9;GZ(}s&^Oj8xqer9^$nN=FHlmImt zuajiL;WU|9?~#8K5`i8L0{mwxeg}B-%=`*6S*Tz!t1y`G?!@a1azB$W-}0}Fk*-cd zh|d7EU@WanoTBV7y|q-QtQ_G~3jQ<|;@Ul6XD)d?+r4lx1( z9zqdTG142w+)Wn38r*T?iGlTwpb!oBkZ}172Fmdqu7*VNLbMsKeIho^Xc;T^l_*IL4_l|{XeosK_x|s^8BWKknmYbv7&Cd%bQ2ebA~sW^isIM`8x-h65^LXX zotMhje~n4VjuC%oH*jq_#n|)-h^)i<;*R(6H@5ZB&uD*nX&P{_Pp)^Us8eMn8qVfW z(Pg0U3i~`ft*O%*w0x#&aAr~@3sq9lV+3ZE8nh&B7;>f&<`wXMBf}T_t4my|0=krx z?eI6(wiRdO0hP<=S`{B1j`4=KkODI# z7L?Gl(cNcxSw4r6e)B_kz3uJ*z~2b48Ie;H_qbEbhlhSgD$5F1h zV{6N0{)mW{nCp~H;4XtHC`--P@?Bd7EF5f#ST;d;_TFiE{p(E6X7#6l+`7`>fl3@i zdw8{h;N(2nBx@>q7R3&VyeUpplRZ@Y%`kv|7W!|gVi`n-PM$nlO1dPll`hrV#d8s~ z^w$=ZMV;$GdLmXeWPRqV3zkvyoJXkw84d@CN#>-n_y1SI_?ik%AT}nwxcL_)c64If7 zfUw{2efJmaI@kR@=M#5GxqWl}*|%2q82r)0;<>q05~11)duoKJDSLk(4Od$mkTZ6j zZVw(Z>f!1M+XGPpd%a{CVv^{xGNpx?%3KYZ>RWSjN)YN|b#Q30&W@=BA`w5=tD0gdY~Ynj366US2!6)nPq6VU){xm%IedpT_<9`B8i8+BkSX94-DL zzG!;F_Er6}$~*pZc#ffsi8UAjA=qi!q*G0t&L&8u^b;PL;BbWBP( zvAg{WFKyg`OnO;%KFZow0TRZ5zw&Z z2hU$)nj}LQTB&Rm`Kz(x&FpdU|BB2Iz@IO%r{%MV=ebue^J%V?zwsCz=5l^?fz5C+ z3wziv8G-ew_R1pOHT$KVaRKrB|MGPMgJx9fpg^e9Gc`8(c!)|7OfIA1qIZ2V%W1@J@&h}AV8F%V{FF?v_b2-Dc%^WcD3r zh#8fRvkI>UdQ`UmaVcIG{Iz?@dj!Ix^x&^uEj?GWctql#X}B#;wo0A-f`j3gTDfCe zlTH2tey#t;T2KE3_+O}N+2la#rCMEd1|Y?mXS1j4oxaXi^)1m^lk?@2U<43GKhjV7 zU15&>aXd&mJ4Sy$k#$yLlX{{)iH-LS$ zK(aLiT><#3c_1w{6JoHgij&)1)JtPk*`vgq&~!;^p8=M;c_#1NLu%w(VbE&~t_W6ef7_Tnppp;R=kvYjXMv;5!*BJ1jK4IU*l?>jAKt za4V{_K-83yv(;sZG?NyZwivDqf^9+OxB5m*#(sDu(5!$((#_k*HFz-$kd6(;oInc1 z9b6Jxs`I*(JGzA|b@2ow{DZ7vb zW-@2`x~@2I^rzvLGh)x48Ln?eFU)X)sMOEE2J0Mo<&ldLCeyl z57uYoN6Itlf1Rc>55BJEj@e?1$lf>NnK2Ebys|I5`$!^_Zl`;TWM3 zAi@9zkjx$dWJ+i&YvASJeuaQ&ZC|LvQmFJ-f$*SAm64P((jo|iX+)&{>FiBuLWaJW zM<$T<(Lm2SVFW{tM8X<59QBJDV#F@bCsev}^6aP__n{4J62wv!`li-lRLtPO*SX8v zf4i!p46G7)Btt+f0Yt<&h%vLP2w(}v3AT9>x*2QoV3&UPM~&`@8I2&5%<^N=HnyhEx5T78 zCb{znP2M;C$S}R*{dZ|2fKdH|r%2r=mP2MwgW4X%){5#8 zvD5C!@7)|XtBu;9wu|nK%n)zk`%j(rznhzRpa-xm4Q2&45PPaOU2jO93t8xfSytdAzW+gs5;W}B(*3K- z#Ul3`g)>cJAxdT$L`^$7GlCUTZ1meq|L8hprp%u_O?1(3lM>6kSPN4z*P!N@IE-R? zDUxsNno*Bt5bX_I`SWj=FAjXMS&e-%m75Vp9zJw;ZN*{Xh3Z-_&NGdilkF40@`_&@|ZKYgfi^l=7A$~aE; zv?+pAC21h*N|osVC+0=;Iu1_dOEqNdT6k)^z&h1?4v5XS8!&IaXlAwtGk#ku&%uIR z^f-!v+0W(ONY$P2UVKVJRKs31C??TY9~bgLu-wx}vpaCDd(Ea?;pj7=>*>in+1J_p z{pf(UTLr>55BS|h_u1-cqK5XY#Vm4#krq)_k^P7W4hWTmS|ou3QpC)+Bs?Q{jiskV$ih+60g(D!HvS9&Mz|4bq_o$N+guZJSKZI(2ts$hn@ z$K$VE{k+)N|MvJT$6Jx!o=%QU7o96dN>YmMS28fTn7@W&&s%9kk0OeK(0;9zxgyJg ziZZ$+EG`6+OZoe_Pz!93XB1-o*kw(q;mVL>Z9MOG;US47FO|Bb2Vqtyt>j8^fxZKZ zF!_}&{?fHs2m6Ux&+ zM&rrzY93wk7xbKj;6Ks-W9(B`UcnE+E{$851!d|WLN(X5v)kcGilkK7CdyU!P|0}u z`rSC6M_`mXh9`SkU`?Cje6(Qp8<=VTS=(KCc-#f-w6iL>BDF1zj7>hLB_$S+fNq1D z3CwsiinSxdZkrBVe?7Bmn93j|%+=Y;1m!xnvOfwZ@7gGPUQmEk*7I>Qs^L}jEL-mr z?R`A79um><^O~WX5+d@ekpp0pC`HDDc;-FFCFkOe4^m_e{EY1|^jV~MFf`ZYn>@sW z`%GcCL2!#`dYQ0+*aRVZ3ylc!-!}3QeAa4flH6KonH<(hC0C3~eQP~sYgS$I`ON3{pt|mxK6%lIw}&__ zu!F;bm%Haa1nB?vB^z7vqWneYO0{>CwWqfKShEn!P-sx}93CBoneui1PVebkZ&!_K zT@qj9kcSLnnR<%jjb|b#V)O~?oN@Qu3E{fM9nA(Iq%5o)VJOMM~Nv8;6F2GHX`|8)b^O-%V`weAhh z4<5kcIqD3j*y?3NJy^*QqSw0k1Up57iT%^=%qpdRC9UaOIUs#Thn^kKQH zICkD5MpBKPO}H(lj`Rkcad3>G(NV_$rPnQ>YEV;V*3KovlgUg*rds1DDZn>KQq)_%fCd17Zgkt8%r1*Qx)+TGU7W_lV13U8 zw-;ZX7JJk9V(7_KrL-$30J4L?^2wa`yd}nj&|6O|r0;8_Ib_(t)YmdykqEz27Sm-P z(=3<|(dfNx`S9~lOUaDq*lA|oJ(YGStV0YNQ-73wiZTz)=W#m0B$xoX&EV>1xElN` z7!d$Ba94*W=eSqpFC0dv6G|$CZ+WdE>S@ef<~s#{wr6gf7)6as@`A6nr>7@A!Eud% zII4_bPZmd*t=;-P4aiPehBU%?0(yHv*?Ii#0OI0=$&zX1g`x1H*r`I`F61sz;n*FQ zG;&asuxWf0MWF)2xHjC@qTB>K{ubz-98G_7)V2|S(a`%#E#mKoETf`5d_wm{3~jCq z1u7!RE_^W*znn0~$1cubPY&9x^+lPqy9h!Vnq~wEWo>#y)gft}6(gU)dce-5$a{PW zK+GW3G6DKqm(B#vfIp}8?wVQc7DmX*A8<{*i>+KZgqs90Q`co8TL8h_Cm9X@Zyg30 zK6-h%u#ie$hHLedWbO8Yl=JAbM`Au;$fJMqU%E_8-IZt}Pqz5+kt|=_rsS0W%E?)$ z*g^8IwDr2WFaE+{{^=)Y%g@hSJvGTzDJcn3K3Kz<2wKI7%&Gk9jE@i|>A%gZ@oa9z zq&7N;Uo6+gZHPe?hUR01N+{PViOfXXzo3c!4m}^rm@&l``RbtyW(#rrEDg&NK1YSR z3&N-s^!|phRGVkH02Bd6B7F_@5AEmMx!H2aC-n~3W@2TIS}^d|N38?c+2)jQETuw- zIs=NNdM#c>{{l9+8+FD0C~M#wD1?#M&6=e@ght^#)O`LMsT5|**j{)sAI8t0KR3oM zWx)Cf5^_x`bf|?f-`EnkB&^PE!ut9#%yU{SbQ z$YWQW=_RqRnVL>=SU2GFXFoX(ncNYa-l8|lJWSl(dPfA<+7HK`sN6ucY!pgHo z%STV9EdRaHOi{|s=T)I=!$Tn{pp?gvBC(zMdNofUT6{CrD zkqpX$)0T-zoZY1v<)rq=7}^S3E;k(Uv0PY}@(s^KcD|Cg&6Loz*XI5- z>f4L3{x<$y z-dKQLoOX96?>hsO^C{ikD&oSD*+w92K^b&VBGVB)8qb>CcWu8^zPc>68GGDT@69oP z&jHdY0(5L(OdbBRHB;6rxQa{`w6u|la&9VLR3a}|Y9deT_dV9f*m>StdU7}|UlIgm zQAK(lKBjX&dQ%(G3$jc(eE7|{8dTnK*ZtXrYJJT}5j0yL@k9>bk2ppqMVhzIhEnDZ zxxHUw{d4|Cf^}qt0d8C{MF(t-W){^Ts+2}MCQ6kT!Obzq4Shk+Q3zn{1N;ysCivko zU~v9)PDyNtH1s_KjyAX8168tNykX_x+0eDS+Yc>^BM<~LK3fb;si56GI>YU~a3_uW z^0f1I;}G`o7gyM`?IIss;d=MR#^d7o^eiT^JrxwAU(W%Q9f)K5G`CYuq9$uR51p`M zBi~LNn^MI1H3cf+f_mXphHaE~qi#f24^ZYOaTLf_#xr9|eqC{H?|R7I{O0zoh4*2k znoa0?)?y`#^n6!`-otI~A-)GY0h1X)F#T+{;0#Psf9!r!*%w#y%SD4qs3Ll_qi=A_ z&ZbuyUo3x&urnJ%h48a{(_#X5d7+km(PxcngVXp zo46Cd6vIAhh%#`r)+3S{+^o8p_q*W!;`TzN658PrL?<5C^R)K#wA6cl;&K8zuJ$!D zPNI{n4;TgTNqN8Opc-W^wU&cJwf&jZq~J zTkOmU>ph=^#d_zTA2<%){V+Avnolb?xWw4k-coXJJlWnDOFlb!WvFyH@D3Lb%)*C| zS*{cX!oZ&Wss3{qbAh`dzC971ljg%xcz&@7&FL5kMUkpZ+G!$hVfWyts5Cy8?!Q~7ENs^25E5k3~7lUwsf&2@Z>X;O+c!r~A z<(@HVfhpx+9OJv?((+C&uW;MSr{W)0^T%0LI$t>p%M)#J<~%?0h-ki6(Vm)J7@Az6 zg(czB#9ks|mNqI!x7&gUY;OY`V9y&T58ub46An1bZX*KT9#eVrKg!h1n#J%4Q~198*Mp3hZmoxjO%J z;5#6J&gJH1$#k2z9N_n^4*VUg9uNz)SRv(qRg?~VK@U9DVIJcn^Fmk3hcy@6h7)JS89;LOiE&VkP&*Vpt0kG)u3FgkW_Pt?xgCPUI8#7; z>7Y9z8aM-jeT^57)Qu7FU)GSb{$*DIGXo5jgq^j@OzWQCng zAD#^N!ArxhdTL{lZN+FxNGYfr2*o*;BdC~cO(C|bIgDXb4wo_U;vpJPoSjw*@pZ9EJJ9-2n z=eDp1s>S#bt}f6IR(W`+HbmhVx+|=)S$$pDqpI}AWuXz~1QePN0Na)AdauQ@>uf3t zCZvHuD!=H(*CVVX;>u-Y0w_3>5~i3P9)10+q!17gc-{|*Wvc%IBCt=$a7L&rwwPB4 zN@jVKi%kD!+R)CwQQ$CV+nLHs*s|KG=%JOh)Xp2{L7y%`eZ|D8ps9*gZNDm_q$)Cz zZsvpgi=cDj>3WPL>)4-Vj>iAo&GJ_hP&=9W=u0qO>Mtkbk$Q4x=T60V9}O>EaAdwm z4-Gr+Lf&qp_txtiiNy=&=T|ta$$U@4?`-Iq9jTZOU?Hj>3h1LWs%p(HW_mvPr^)pr zXf86&Ar2zw^u(-af^jux*`wB2)P>XMWp$Ze4(=udKOy^t3F6?|%h?GhU>%gP)o^w& zOMGBu&Ctsv)pWcpv>$p?ib6YU`$07JaW-Ie;)AN|=_cLm@n;oB^2fpqatr(D~&IIn9bu zKVl_bX9QmbI6q)Tb(aVw3*xFy7hqErFZ^-K~k?=Q?gZ`=m<^>N)i!8SX6jhs@;BXTRskyE1$*=W=+7yLQo zkj#mAJ*+~UKqT2oY57QD`oDFLYN*O5WN2y?OwM=>W8G#y7>u7dzAl-z=TN>=(B97! z6*yj6@|JDEy)x^5=TzF(1{P+gCgGrR<3XZiYmTS>gNjPcBDQ+337La%d2z5CRDhe? z79a9{)8GB_WU=H(Etiz~&OJEbVp$!%SS-V%&Ra^u*^cP8Q=Kku!{0D$7DxIzYkGo| zT*FVeSV1|C!D30OLPPO~c+qWKu86zYfB!ZjaQ29a0emgwS}Il91aDEUhV@~+-_8oE zf*zkze1EzC$ESvaQ~Ms*102)x$eavRR(96+A`8xyJ@VgO@N2TQ@rZTpv$G}Xy`d#Z z=pjL!nLV5Ei}y~fjM8JLWcH53Y5dmz10o_-eVwNHw%ESx=(kmdK>MxNL-GEqDj&|Y zl`rYiDsQPP@n@Axz*KaXD7G9{^!EO3!Tn{v8U=q=t7+WKd}uofT*Vte6hv(JkgP~|%Jql>TV@3{@k74EwO>*hEvse|v*5W&JBKT5jX5Q;w5~~L%U3Gl?it@$MLdI!?Bf2w6N#^5UkGDoS z!q#N>pJcped@^ufF=5O%`m0SAq#KW2)4g2uaKh-P?H97T6a{=T5RTXW_ei{LD90-2 z#|bYoRK@_o`-8|n-tzX7!}Io5SCk_hG@<*5lC5|c6BRjl`ugF~Qko*HhFPB`Y?-VH z=lGPu{N~c5Nz+om4F!e0shFu<;p6YrKGsmJ|19#c@iy6c|FP}W@m$(d>8F~FaXG5` zPU5)ANKkn9=4qr&x6%ru!eRIJ&i7SDKc#*rk@sS1rKRWA4NeZ&Tt-i2I1e!2KAz3I zCnslKhwSSiG%x$eZxS?K5mCn^H-_IRCVIYV)^>Q5vnArB?xN0C2n>`l6;jcq%Y{^? zd-5@1tJ5hBlt@|{_G5_s3}KW`+QHbE5(|kO>*PXw{3!N(6U*G=xC`STZ=9}vNida;1Qs$M%{5~x zLdOA~Bx3@L`jjNZPC~m(!JOkem9f8C|DQrZHbU@vK~ki~jke6P|7;78cvLK9WBiSj zaJ`f?6kIM%#UfktEgRoY&KfDPN1vhV?Dmll?&D%TDbS}#ZcYpYG82*pG*WblwFO7B zMqu<|<4hy^hk%OjNuwg%MXvXaCwXN$_e(HtKbEN*kXI~f;7NR!%t_%l$#iT_BaOxD zr_JHlF2^;ok0k(7zwX2?&-@;u2KNzx$6g8F|XHId!CQ+ADmn6_1KDu@^n!4mkM;`pd;l zU98PCI9z&jO^w|TFalv4VaO;0eTxKAwTT`kA&Ih2;MYkLCq26K#=q=qRUyzI z6v>En!4{9qf})Zru#b`@v!j$o1ojJh&O(5Y*cUG}DcZu9Lud+?`?{@1NwHMGn7(JN z*S$C9zjcTE86(ziUnptfvhqK^Xk`a0A4ksb**TL_G_S*Vf5;L?8p~LT7>}D;HY$Ix z^?o{=?#xzgNCc;0^bQW&^qLQd zq)Ss1!dqQ35jIXVhF?N+AYu$fIyDQe(4S0&nVMN%Mo;M)iQT%fik}q_`xO%qn3nE( zEX#z6@8U465`0n;vuhGRC(NxwX@5=jsTpVF{`?*DL3pf!-Zej$vJWSgx?je*kqZEpu9vP`C$Zs!tvB&5R_<>Th zjAAtwpdB7Z9ot<0)=47$P0Y6!^uP&NJ4Nu7v?mfXv?(w;XD6T@n${2>NGacw^{uW$ zE;Ex?!s_@Qwfy%~LdqSJQ1Qoc(LH|y%+~9|;nuOM{Ql|%_CT*ydY)y90CceXd?V{a z?ei@BTwI;u^z5)kSwKmvY{;-oSS4FQA-~*B%W|dJwC_i$9tQTS$|a>(9Xc`xXU>Qi zuTW&)dhkPRZrY`NZ3Up^P*M0?R?J{}&{n<_NcOsml2?&v;0uofzYA8TUci3pty{vG zXZOs$ZtA_BVuO)i$&{CsavS{~8X*h)1ATBcYK}t?N(`x#C*j8`2V*Bu=;g05R#V-Q8}}RvpHv z9^*hAV^AQoqKzXHeLXDA|b@A|1%-dE3Ke zC|n{TFJ~Y(Ngo$Zb99ydP2Lb3?AZSPXUD7mer+}$3UAJS>&!MfOKn?R#YL$Bb$tOA z!x`q;I4DNgs;-(MRd0(`#DPO)lpv@^TAldVsEa=iM$8wGE|){=bWbbC4vyG*Z}&TI zXPUhCqMH!*FbT=Up=AV4RZ{tYUWp;o$iUvuZHHt%oTskuuSx|qF+g?49~A|e+4I~*F&AU9G0|ON#io2_iZIm?4xA&u$Sn#*Y`!Oy(&HE& z^dcbo5;>AyiV#)#&yNV6RD5RgkE|}h+zgjGoGlZ)c1Lz{(Yvv()&^+b*OblD_@iiw zBh@sIt?*R^QBZwkC26=f+|k>F8En@ZJHO5O_02x{wN}$fbom4}ZEtV@eK0a8d_bQ9 zPNReW&YsSDJ7Y}vo6DmI&8miJOQb$ot4GGf#A-HAD%2&FtsiNMRaX-6V9;^}c?+|A zA-A`koiKH6T;i zq;q8sff`ud+<+#rqKYTevMmOf#)dkFVAQ`UWjR3f7Z+ne9Ys#DYC(9~s_hd8kca<7 zS?_3h#IdCO!^>v}R~W@K!VAW!I65-;E}sl~CfkxExy?ht+JQByQBb}$sjm|9Ra`*Bq9AQ~xL?%M7TFd=P zbYW~z36a72q3>Sfdwe1!OOFp#y8)O2Wvlqe{LWKrwi1RkA(HBf6s-gNCWx_#`JSs( zF>1TiKz?I&aU2H%eiAcyxo3FL@On^csXL4KKJ>M{LpuJ^JGy5Lt z)=yjDu(NU>!ed zeO2;5D3ROXU_%NUPz1o_j*n5kMCQXMr@v&^)Npt+uja!6zX!h6CU&HPLTMexiVd;} zp(K;vO_o}uPzcIJ(xum=*UvPp9z@-SEx{*+1BJU|qA6^9Fhj=hj@$@K22pFKP#+uO zuYskCuYbHspw`0n_2Fi*x4efNdkVUggI~X@vT!~&H8otmTcoeV?ZxR%|7^T}7JCq6 zzH3H%h1=(CVbr_5%#G_55rXn5!}+$ne+VFzL;1N0vZ~d6y4k6=X_wz2KTSxhS13*v#e-+#=5R2g-YVI`DX1kR3xaS!RT2*RvNWc$uTji! zm7@|24qng$r|+E^y{xeoXM!-rmBbkTE%26?y>RBe&u#uoxYn~-{xnW z9nw5M<|C@oOHVSR__H-ckPlxT2RT08b<|p%wkRwJ#mEma*nQ#BEKdh~h&#Ms{5{CTKodnsDq)ZR{@CLLk3wo&D~C!ULgJ1a-G%L{ zq(rATSxT@7cH_{vv0m--4qOA)a_TTAqE)0x@%At2mtib?h-crQ)mg6$yr&7;`-|Y$ zWS`n$;Y6l9YPM9tx0oF-5L>2a)mRooY{4Q|z>`z~VC3|8MWyTsrA@CjLG>^9p+E4j8E2x-y1cI8S`7>74~A;XvC3b4oC?Z>tv zSZ?oZSC5bKTYGR+#A8fp@+6qDuIvzupn}H)iVeq)6 zMTv2huWe%;tJ1SoK#<7<FEz{8zbiY(sx6J$ue4|37g%bf&tB*7<2{ zik@!a;;xf6aS_wD$Xkkk#x@^E`}AOaz1trgiyphPc}^M<>0%j1(?}H5cD`E> zegS2I-qfzR3>%0_sa(>bj}Ou(kbUYqJ(<>d#qdjurYxQgI#8^GTpZdTIctfSD7gR6 z6XYfY$nW~HjSW+0Y=&3OXCL2hWW(m|x>v)6r5UgwiA#$IO+WVAb_BnhT=7HJale0VDr3v*W&E^@s=M3IeVJwiVgNmEKMKQ#W4{@$-oJ9TiNkI zsN?XsF4xcxEEc-N{x5!BrqW`pu96#F_X91HmjI$fzd@U`Z3U)KF1y>R~IYoFiAlbm4a>bqhVg-=$Q zWrQvFy>)k|Ww7o?mIL-?8U$bw_&bDoN-1ALHnSo5<1v4+qgrm{g_LzapjZ zv&;sN9WE&vZZbNVF+{T_dDv1*0oww+-EBKLRsAi98$xOL3)of#!&~#&!PPp8M=$94 z69SkTf8jkU5fO616-FhMf^Hv<`8{M71F1zHkLv&He;ycJ-{uKUc-B~c-kx5INpxaD zGN!SN_aFt5EhBenq-sd8Q`Ob+6r0Ko1ktk*6Mt&^v*SLv2Wb*k84)4+Ho^AHwV|+L z#CGG>@|(K?KM*4(dDE{^*{`xukU#T`r4MAXuej+C8oe#;Ou>CD2r znI(F^zEvpH`_hl)ZaVtxe1D_Mk;9i8D_llH-xMI4wFQO^cDnaha|N0Y`Q=n z5p2a<@QPr}S9cT@le!f~=6V&}Z|yk!Cx<(r7Pc7vCg7p6kYw$xBJE|oW@RJ{9f!>$ zjhr1V^8{I4cWm04TkpP&R7&F*CvE^GrB#qjh&7CD?3Jo$T3R*hS@i90ro;{37E`-@ z76+=n(_sGe33qsNbh?B3wJ4( zUygstnyn=%eqo_m)Ep|Y3rCg+m3MP&B)hj{L;gaYsZ7yEz0lE7 zC{v*B*Vf4AD-QL?iJ*^B${;TsHCK&WAc?FOvDZqDwr_Z6|CPtRN-sEY<>z$6HcvYP z(@EAFLr7{tZc%z4Pe~qms@5(3(|zRHcXDiDgOh^c;Jvqq+r*!={ZyZEhk#OOAji{H z-~E%iwv>T1gk0#%fJvK@T?stUyB4IIwqbovY`*YU7$3~$_4v3- zwC$T2nbAOFY{MRWe^@c8*ex-%=9(7`yq0z5$Nih{37$v1J>R@0J4j^4fQyR%Efr&5 zl-1rW)Z8!a#w9OVII*;BOm|@^=M^q?c5`U@LGs0zZ8pGT;0l42v&|BnTEo0~BqRm1 zhXo0}u<;)CX>+qP$JxpbK{`Q#4;catVW}qO)zq}JAp$KLoM`xn&%Wz_l2(5u0SS}D zgO0Q?adW*!ZAZZe_9U$Dqf(AiI0Yf{SKq(4TeX_fY1D~T%jMalVeu$o_i_#v;9QH1!nd7Pgij3eTpSb_=sg8wc7*euPVL5tKXD7tLwCOy{{GUU>zDN%iZZ|NNXlOY>``W9-?x$4K%k5 zUR948qOrUdcN`nJ7m?pbg8Kv!Az_l2&T{}UT`N|^ad}wx46hLI{foAZl)fGBZ7sv{ zN(K36f5U=duqPPIWnbsN6-9CfKD1R~rQbLmLYPR_5KaDKs-)U70ZX=uut;~rzG`Jd}BJRL>@^JP$0i(KFi zubS;1v3(T^Orpf{rbrgn{y++G;v!K8eh~9rYHORc*VqM69>)?ot?HB6w3y2^{IF~i*p&{M_H)Q~{rIb*enP>bv~tVo&k(7zkXuSUawDX%e5 zZ@cGBjiLQcfz$ZSJF|C%kwIzPbNii{9RZ3VrQ8BbsZO zz6imV!#5Q`uXVoD!??(Pdv!wUbwy3_#)SXd7A}Vttoz~IqBm`9k(4ZmOaU6!<~|5$ zK@LkPvE+_K@?0yM`mKpWgF;G#V(DZTV?ICL*dkNe6o!6`seSqV2n)R2euk_c6e zGPG93(ib+?5;hszkS=zk3Z$0i6YxQ?iA;c!BH7c(XbcFve0K0`q2V1k;+*493a)zL zV^-1@s%oW&$q1Yfa+U8pz(tzcku*GvFH$GoMKIaFo2Ok-{_u5}8cQ}&D7RsWTW+-* zZK@Sx8;npbGVRSw+g@DQD+Ss4!{Wgi{~<2t8i8z4mZ36nT;)@n+hNnpWmZFl5^tzI z3fEHz!aDP3xobN5SzgVp$%>=GKmkDxc89%VQt*OZW({T1TxG=YSS06tLmWnq3?+_b zbS^4(yx?1=)}MX#H96k$^aMUeiSu_YlE1`|p@8tKRC4(Rw;4U@s};uo|D zg^-Ww<3Mg7JvxEJG3C371=j#HbCp5Q3c@$Kl5F_UI;nvhKu|$IgE~=zaz-vz5YdNR z5%bjop>nrO58sDeexJ_lBjx-zCxr%N*$N}?r75uq(NSpD)yu~DE(_2;==8j6kZi%~ z@O^!}Gar1U?Z%eT+MgX`h;1m3sy3E_GOCXA^FzRa*EiptyTalSbc8)dg?YPS@glcz z(vF2#Efk6Oe{VL!dV>BXfa->kDbGD?(c4q0< zMMua{>9nH>!GV}AEE#Hk7o6Kiskn<5O~lLnz4UL)dWZltQ2m#?!ANll_akDyQgsRe z(hZ_UTiSDTVEnv$@%9s6~etA@NI4T)vcF&v!12+c5U?#q+a^(}^l) zdZ!c>6wU#RNeP*3L=l3TH|m>VZ6xhJ%-Yb#!Gdm2cOnW1363LDvL^_#@2uo$ne~XD zs`z?^UeidflU2u*BQ4m23L{n7lGcC(lcwyr9i)eif^d(udf&bP1Jav9+-J&e-w5fQ5eo;d6MqQ35X*y$1Db;Yvlk&ShEkcie4A z%goNLYIcXl7vW9cdjUzi(P1U=o@@=SF(fQ=1L}yM`VA%kQD|+|p@UWH)^%~ZB_+)V ztHo^h5o~C4b`&DkN!1gGyUWzyh&p$Jzv`Phc>Yj#yWtIO88G6{- ztCMmKSd{06sUkr_!bqW^%IEPBs}EC9LwVuK2z!MEMYdnDLF<)7 z;K#I!<&FO|91J8ApmPCxCNnmDH&PwQ$!M5YF$3Hmh1Yn zswK6p4k>G*4W%5GWmK<^wWjc);;gxZ*@8DRhI7?%VIRxO`}=sY*;A8cQs!I^{e<#X zjs>CDJ?tcV9wq@|;6HE~&ghE$9H>fzu%~N5Mz~dKry+_)4_b=Rm1)#(ON*A9UgmJH zAnTn#@;_hX(PELR5x~pMhNVpOS4O5t$am80v9d>=6hOuQ)5nI5wm@lV& zDPpau@$>6fQ#G!8?Vh0-P=^v}EV9(8xb96W{5^+)RXydeoD3h8rxKFt6qur>K6bED zUdstzlDxiZPgO}I-SUl*hiXS37slKFd+kC1`n@ls*+Jkd_b2#p?eI~B`W2c!4N^$X z!cGffhb+T>9y@NS{0sAvf)Dp?KOa3m^}$;-uT+psm+%lB@PZ(jI&Q-HFbf+M(*d^tFMsqtS?wlhQ6i4kDA6}Lptbx zMpoN-;zQfxC;4SrHK#9sWjUYmUgZ4I4D?@%TguE~jWqJw->-BiyydKB*9jl;+ZY@V2cX?mIfor7z#Xb>I2p zRV2-SN2a5+0dq(9Xz4$%c+5w%q&fKz`C{#OcaMG*x@3RU~c>bDmw;#S6H9=*}0u>2~oUV~T3#XsS6#;@@B*?s-Z z%~>2>sooO{PtuJPvpr>r{lMTF2=UvY-$s!yPUkW~63ng4 za(;7r(DQA)cFA zD)7x1bwEBnu1Hmo@OnOv4uZ|q-beacrS#G4g#%9Mr8K$XFHlw68BFJ>i zw}AX*S57iWF%6`a<$&L6{ek`FZ#cW4e^KpI4Ifj)x<%~%FV*Pq5i5ITKbwzZZ>U06 z?qHA^jX>)>vH*;pkJov9Wh`9^Z(uNJD}McSnpQs=oi};4AwzzF)RYTYN&SY)URklv z9^aUYk(x?QOd+()zM<8YKDK!TyAG|qA5fYXT8)dw5-zD$OXo#aF&+D1Fv43TW=Hbz zU>0}R>R#+Pa5xyk`#HGo{r}xPz_UKMQqdEOq6n_6hTddG-mkpB-MLTw6bqg0iefFB7@^6kPMUKnIzD#l47 zdUd2Eak)ekXycLHvafxJ)$)Bq!W`;~X@y#y%(AJm-m0*gRrc8D%3)uh%7+mbt%H$^ zQIaKPiNlYuf*G;FX)!0lw1{C3}`j(0V*58%Dk??REH$nQLD^U3uhlUf8 zK>q3%8#5X`y#-#_09@y4{u0l1MgpHtyVvYyw}?k1ZgTj3X_`7n5&?3NHOy1i`LaDJ zisa6`=iHf^Cg-@yc!0<3bq#=`X$%{MP0ot8pW?RRMz+>QRQ4d5wz&l+RA5bZJ)*4j z?tiU>f~Ym+lafnUnA*#t^pv`Ud3j&n)0t;8rb*24uiLbB&dOyt|3nU@R&q_#rC#|4 zS^mrRlasq6mm&2nQ5*d-a4G-r$ z1-Evcl3zUb6$KXs!vfB!ty4-75EZK`t07jS?x-0dnSc4{HaPa*0UEkKC{=h}3{ymg z#f$xoA9`zAH(``{CjasY!4uE@jsB^mk*eVdcL}Fetr3QGKdyMWAL&BxZTE9crCDUU z3Y=XM{EaBewTy6-jg8kV?B=VBLy^s`kwpiF7z-glS*+K5-D6$l{LNs^q`2pe>FVr6 zXM1pji?;L?4k#-}wVhnufN#*JKC&hsgzCZts`)E#J}1 z_$3vxMzE+=<+7#5{PG);vQEUR%Pp&jaB<8j^L#$z|1=Ef8Jc}Z|6 zLv|i05epE69%Nt8a}@$4EraJHPGbI``bQm>%~z5^!p%Qjz-RDl9;HmVxhDO5?+%wRf^64jq*FQ%bygwY!TyU??wqYw22F?PrJ;o%-;eO#<&PNDXMw3>18IJVSQt9HJOuXPEt zO<0^0zAqHiFr(u{juH^;eT=R6pwx-=E6mc)B*xn7fMmpR=ccxFgPzBMyqG;SupfT* zoriV+-D6N0p7&fmw*au&>GPb1NzcNCcze#OPrJs0~t7t^m z*+5g%!pUS}N@=hk^4~6rH&m1F`L5=dPsZ;NX&Hs}yd(74rC7L8Wat;9?%%QXa;K|m8$BZil8Bs}=3<36FwhpQxd6%-8tAW@_^W|hQJPFM zIc%htpx44Rmj3woLle-+Q`xM`(hC3v{6XF`7Fv={r;xl^cM;xH3%e@v2*LcE13 zU_?Cl!^7HF?d3xVw5+~2NSPQj6^wOWk&qBIfe)cCe<(ITF9#NsF{aIQ=?^sCDMc1q zyeITp`A+&=JqYi{l%iln#ON>u>$AVdaY0t>SGghDpH4PJcoz-S?ptU25!$LxEPm24 zmeuoV982lDJ3B5mM_ck!SZruEPGR~M#UP2_XKiaQhnsNHTNh1oPErg79#~kLr zHOv;*L{sXH?;M0$+K$#6o~ib$Qb;$}XYH>S56fjFJ~Esx3LH&`k57%R?)8FjiO}#f zstMPe7_tP1*Mcp!tUR?0J-0I~beGV^i2&J-NWT8vxYZ=5yaDIXJL!!pq!e3{jX5bB zmqU}L|A?Fj+xG{{XE!Tk)Vw;x=-`E$H>QK_CW*Y`8Y~LUAC`s5sX&-1nt3`;8ku3# zYRY>kVP@7Z&>IZ~+ZD0E1h7=4C(EoOqRM~iR(wz?fOei*pxTF8l3nfG2;`vscIAzv z*QN%wEJGYA;i`&^GJ)3WcTkh*D zh?Ir{7X1e}J1H!RUaIg{=|@DepDd|_V(@XQ1_e<68N_-cKnwx@z{K7T`ohOZ2}0VF z1~8Gm^+F#l1TJUN(UhURDbo|^d%3I_T@yzHrxlZoSTxE|yT71& z^?)K73`zsnvIa*oaiyL)A<&sL37J?crPo~~Ji|*o10XwtjKv=~$rvNs7ci45Bb}@8 z!dd0zaPeF7#bB-cu-_hhCy6Q;m1%C)n})puH-JF6Q0~1nr`92*grP~p z=WBNoK*Y7}I|}jWxj;03!MH||!a`Nzywm;5s11VsD%N9Z6^~Rlw3K2eHe$2PmBx-jtAZ>eELly60|sLzqp1c^P%5K* zdfG$Sj~|!DHrLUF7bXUDi%Rz}Vt!2j_%&G0RkOLDHL#Q)v zP@raLuQbFmS&CR11@{FRvLrc%tM29%ii0X$%0Q*oz|NRla-0SQ@7C@b*92|bL^zuu zji`GuP8x|&CcL^@8436msw?mA{zcP-DN(WaK}*J$sZ8FpW>9r0uS!r6Z-z zp)~`7iIYGg%Rm&LJ}|Y6STK8%xVS16HflNbDXlE;YS=cQp}P*h;o(Zr1}PHBCUid^ z+))51Pz145bj&-?ulEbaxu2adb??j6x9Np~=8PA^HO(^%pF(%&N(TbSfFI>sV~5t) zk!$YA=VLBK{yjZjonIhWR_kMHWf_JAb^($QYe+?KT#i`)Z_q7^C7)8tsQSylkEHlx zBP9wIQ_cQP7i_)pMll~?AS36C#{>RyxJ~S=VZq$Ehh++Ne01D7&bTW&ZF%ofR7Te3GQ=e_o zMtCy}vIWqjMyidfD@bc%OUx3RH^jD92?a4NhkjvTvV1oxks!n#Io{q;TKXsbjkUBH zHZM-?4lQew%O#(Y_-R;e`_kp#3Sd-XD2r4w^>_xtmE zg_!aqV-cvNdoNYyGlk|j>QPo}qB&_xqj5`UK;|5d>s~S#@^a`?+0#fnJXN384H_g5 z@0QFJ?W{Q$KOR}lzZhh6LX1!5vYS!&Ts;U5 zW04R7D08;Jt#j){m=ho$@U-Sh>i3z23U3vMaRzs|T3PpT7|v6ycPXmJVikAG~P z$y6G?Uy*2A_UR>Yd#&`aw%p?5%!-I30O8=H0j%UfFf$T$0NPI#6csg_#zf~7N&}uy zeb7Goj-q;5IA;TX+RweLyH0QY`av-=#hW)FvfNy7^ALDtWqp~fpIt?B4P{ULV&d9+ ztIVx5?q3VVumJmE@KRPvMy4T$W8vn$NQZYl_&%F{(D=c+!{d|S)4zu<#AM>zo}&ZC zbFL~(v>H@N{e>!1SQ0)IGlNy1=Bl*ooG!xVV|q5}WG4fQe4#v$J7n9~0Uywie@Xb3 zJEbF|YO#ohUt>#)HWKAQ|IH9H_h3Y3a)R-4xGv3=7_d_bjO^VYek3oe-Sk{N2-(7w z^)rR07n}PJ;^3ejm$etd{Fr3?3WmWtN9!5!rX@0mgw{O^G3p&ObY0X& zDA+|mYEt)2wXzLiXV%vwEh;o(++7@bD#dV(Yk%Q-_UKRxhoNB5rF7kY9L6&Mm=)nv zjIg%gm_lv zLw7>~3NpWVahy7=o1WQ-ks*%!>8k2<{bac~+6$3Ga0JU^hzbmffbpi_X_p0LjQkZ# zBYPDg8Q*VWBmW4mL}bokNvco% zK@XIsLFLDkMj{KsAC#ZSsBn!)N(iX5cuo52hiPv~@|)U!TGpLtO?#asuT9|tS4IyK zGIE+aW=>oI(^&7R;6mK?ro#lHwJDcat^PiPNAax`j6jt@Kq3Ra-+$ZK>j2O;)3d8X zFJ@+)AHt6)Rzn{dAvfPI7B3;edl7*30ZewWel&ad&{pQHOly~Mv)`RmQ*Cm$Y&a3q@rlJzP9IWzMiqo?4 zyMr3jhBYuf8jpq6PTmD(omsZDwl%)Hx-@c}qq6wdP`qn$B?&a9$Mo0l6RFF# zwmceSO84SND3R6f^s@M3XkSXxuCQI|>7BvLAD=$l`J&(LzWwxYdNMYgVQg&$ zKw==F(IuV&zrbfL@=xfKQZANUvmtM9fNgbCInalU)7aZsYSYU?BqJ{8X6JNebI6p4 zh%Mr{O-$^E^f|=zul-_+Y<_ksB{JP8Fz779#YTH(_RDgRwmtv*xdOm!QlZbgd_h`7 z2zTuMI2a%Pt(+luB-lPAI51&_tN{hp!GTbzRX-XyLn2RUv2ut2p-z&K z2sv@JFcu_}Mz*Rt2vGQ`ax#J}-h6};24>)@h(Skr`(MpKo_{U`3r%tbafLh_ND7|6 z@B0GQFB4JQY46q3N_eB_GX5PYfhxqFnNFlXvLMj>9!-9FJz+>+2fMGimL0-Ge zjDRB=&)H2iN+9PeF?R~>+n(}F!L3)T58ihN6C)KZp@!PdH0oaI{Cl?`>1jL+R66rG zbudO6FKV^3neM7K764xXgYcuBPg1oYCaWHQwqBO9>I^?NG6qK2v1<=BN?8U+X#FgEX+aaQFk{S;z!rsyYDjnst$e8xAJ+; zfH);-Pv!RyN2{fdm9fPWQkYO_jmhnxzTs3IY35-~_>a*(a;SZE z@`{AYjX((y*q>f{zZaeIgf$Nn(36f8byzLLmH1p#jtR{lTVHe4kPsVzZ$^V>=dZ|u0M_WI&_Xbj(9uMCpKFD+CmBo22AC8aNuE1 zVAIl2VJ=(SZ-KC8Ff8870jM#0~(6JxT>O-QpWg3 z#Z5|V1CwNkd5E+Eodpm<$9BNEtVN-aVkr}E|8Gu1u7x0($My!=Rz^$r=+>o@uCDRclr*0!`}@5Y>2mWLbwZ z0Z;i0B>w&!?*U-RJ%k0sc)NxwFHgwu@)&}loq0HBNF1zG?7R9~Js=L{E@_G$ zb{3fels*0z1}RX#tTeR1CP1VPB5M*TF4cvGX>9WFkdn?+9|*9^+u3=~6`v?ncUC>{ zh)%EWvty{eEHXM#X}B#iNyZd->8O=kDiV!($Q5Pt!Ef|1l%xTsiW{|F(fbl;4U_VHmG!3XsE!Ik^x z6(_K02ot%lxUBDg(%-QegiqRl{zD}ZnDzke^GaHpnD)7A7G**fIyew&054hcJIGJb zq$B;QXIySuau2~QFR2dat2xY)BY5JrT`ack`quQxDDm(L4RS=bI?K(sPa13qCX?8WVj`R4a@&mUzISk z$#w%Gs@F=Fyx4>Lne`jRE?)a@`+3u3EJ?fzVTVsI79{=8-zS)NhoL>w~ z0%}t6+!uap9EaY1?bnMx*28UA9}(}LT|I9A;9bS7XMQ(0as+1>PUCR&T3yO~$0osj z$k3FG0?K=(GW9E(6gA;XUg&P>>+iS|nRb0jO0WGwUZ6$_7N0ffS5w!8QnR}>a%Utv zdbs@b4CI$B!E}?D7%I1u4Z44>p34Bd+RbN?9@8bn%@1J%_F2m%*&I)&^k*gc%++c< z{AuU@Zf%3`xPAC8BTe}WECEPNNa{7GsE^!BN^ll73iH|uAwpkXs!l{OV8l&ym~5X$ACE-74TY=-t^29p9$#dFs@?gbu)5e{wVp60HeBL5P9?Ro0;DOw*LSq(ERL|p23 zoK`3}BgEkH{Yrz2R)x zT)J6%e_`UUdAFl`O6$9CTCYof9iN1*G#-K0$#=S*9=krBX8k^SxE~FRWrYDu6YRSK zsD68)DJ=xjNF_+GFbfE?JQM~6^+%?~yLO_#;xN&nM13cEPO4=vR#p9m)KLKLGFTcc zDLd)6gHG`hg*cdS{bLm|&OA!{a?Fk6@@STUFV`FXC-LQ5rV+}B230G4&4w8jVKk#% zXloeye2|qkIt0cjI7R%SQ~xQ;3l9tN>_xqTY~Z9G+<_P)a5qtKF->ak7tT$ik!zuU zwOy$ORXYyd^E^O>I_Qcfshf_)>LAjSA4!bV(=#m&jSaf=Mm-Ib+yn{95<>;N?}r+- z163#iuqYx`{dW`uwnhIni~um?2Vxm8gh`hB>_W4_emPk=Hn9gD5mogvm8hD6jn=fM z|1~8;Fq*qAQ6ATy?jN5H4>I05DdNiw-*SP5GSYa1=4b=C0_cocT3d@o3@R611t#~& zq4t1UvUlo@q}A^YU`YjvQg2GgRo}czqKAcg0RaO{>e8xeGxX@5@12Kaw*q8!0+8dV zAxB7hio#~;Y?dv>*(Qfpl2|eFj z&_V7YjWXtLcBdK7)pG&>jVV7v9r;vQ2<-+=8G>iEee#y)mar*nGlfApU3AQmgduEK z(auHiwUrIumt*(c&+?;{Yv<5fo++rX>3-qfLD_}hSBa|of8GzJQ5ib071;!A46Hp{ zJS3)itV$j$iz;7TA}QtRrvk}Ar+3=5n;0W3G?chU4b$uf<+Me|%j|w_ZNWNptY&mU z5Gz6o={98Cy$uWuNg%@EYr$gdr;H0ij#S~;>NN2)meOO6U~#fX0VdZcX5m3YtDhpB zvTQ=aS{8h~d{e5rXF;K4M@mcS{Zx6+^85J4+h z1QMX-IQExy(ERSjXKLZCk0z>Yp(VTPDw$eeZEs6|3r*q;rLh2tmKWlZG~sJ>8dOHU z&=D4Gsl8AAVa%No%2KC{(*b%~@)FV&!{`X9Q&v;%C+5FIo z{!ZN(iA(%*^&AG^)7b_hpbjMl$~wf`bJqD1(C8GZYY)$I-!Ti!=(`prQC_5URe*)a zp~H~bk-+#F`5_cCLYSCUZvw<`;zf##uAWvTHu*w)cy1Sr+a^pV3T3KmWTIIny4uFO z+MTTzK9)Z|tqo`RRXO8_OCo#7Lm`s7c~;S$6{+|p48!kdIN$jvw!9uTQ@8?oum%9w z)3;`)%oP~-s%(>;Qc~brng-6+g{sY?b1JOpuG>zZBX(d)`hWJ^Og;#$O7*f*N)J#7 zRtT*Ck1JhlueBBL_=*nSja0(vA~eSaDO@(TmI}^jX+@Z-T}{oxG>Z+ zdZRzqGRwJeTkFd2vXT8t1pPUS=wW2$oPCo`0a4tWiHDgM%-5+Jif)toC&3fH z=`(9nl$&pgIsYKuhq)DOYh5dm2p49%09lI$eAmDqWJu{T4g00W^Bp6zssrhTC~ih^ zJdUxFQ%e)^-Z3>^O$9}C(dmNQtXG-#;p!7yKVIFL{<~Uy{d3%$IH6F_p!T;eG;v-k zUQ?RjJ9}bsN;q6z^y$8^PW+Qi%`sd+X<~uCgr$(@qPOg*5G&2tRMytKo*lzk>*>5$ z)$MlXHQnR-;Yhe6t#jd$9j3eo5V@vX2?Z@HO&`_zMvr)|$8J=Zd0E8Uf{SJdsAeNY zk;s||B_q(YCsJQ^Gj|x(urMICnnH!fBsN#KBLLN+kCq+j65vTGTKFFhJHI+K5x zY@*>u$jhHyhe75t&+v%-&qS_=kigEQS>44r?YwA*AI0u=Xg+Gx=ZWRj|GFNwgjW3i zjGsJ}M>xC07EfV+i__y`#8vpsNCXOCn8PE=q_5YnP|Wk?BdL>cAZuWYo-voOkVGEL zlsDNZ-XQA1+SMj1P;0iPve$L_wo6FzDE(SYFSE>k&`2595%+Si(pvYNL2QE@M`UCn z?9smZK$l7bcvG!4<0!-nH&$ik*bk!SjA0LX`@z|?pzA|}3w5JY0)Qwg3@u=p+HO+Q zv!VMiP0>4VjCNgz+3M(ogvTOaGPit?vyAPKFEhrOulO4maH;@z`Nia*UM@l6K=#?# zZ4&y>^R>GKApG)!k80mWf$*P|ir{a)`?)Z3+bRE++#^amaL$+H8|RiwdC;bnU&&vh zvRf9TC$x2uzOs4mxn_&TPY4-`>Gki&pOs}{Z^@kr)m->3bi|zI+4Ge0+$(JhoHt>%iuI&n?~;Ymb~&Xj*j!L>&94{xlC4jSS4Q|z z*a47wiQH==LQLrTacJ7XLG?O~%_Ji<;{!VU0X>TJ!qYskX;f@0cje4c zgj<{ttVyuEB6a3Qw4BV)Ny^EZlG?}Bz?l`Z4Ifen zJyMu_5Hb|XuIn@t*0DJZiRnBOy}9}1e|_pVEAqiQkxvjwh0rjpALItqWNg_!#iu|& zucG&P(RNgbM+4ZXqwh|8*T5k?$9sis{qNesQw(Y-?@qC=&19O?DpFZVz6T-E6B5LT+@FG(l&~D8uSI1hklO{2`Tp7|RvorBeZZS)E;< z;mM$pLrFw5T>t}jAbkjwdfXQ>m8B5f`(;E}6??_|kOxMkun?E)$Q7ET%cbKv^rw*} zzp1~aS6bI~$|EzgLs5j>sKr5EULoqL@Y=WWB`c0vE-SX22QY*yIR(INqxM`q2({1^ z^)t9;LB#Z2J-3%^(gnn1Qt?WfbTJS(4hzV_=4xT0)QkPPOyoGBiDY_{RiXXFO8j)< zsV(9YYb;3C(lSiF4o#O{4`MzNI6U~JXk5oOG!H06P}=X+tNFXtoae={s4|O4S=x_S zj&}uP+cd;Dn{-Y;UU7hb-*SnN|4E#Iwm+D1t(6=xYMZ;pH2M~Ey>j{scJvwjK3w(5 z$A%NG_|tYiDefYqwXzR_y{OD;h^o)xpK#6-nX>_666SCwC&Y5|C{CerL~N(w@<0q0X8UKIC*uj z4d2yw_kaK$uB;@DX77Q1hoPe~JYc1|{S{1sS7~s0W`fLujp(WmJOtKR9>ALpY|m{e z)mnSl){dQv9btdj(d^kat2yA(kdX=KMejQ~qu66OtB_7xYzx=F8KxfUHBc}4budYO zS~JA{03N`oIK24~H$W6LV`c#Fuj+~j)%+6^f8dy`s zag0<|oS%sUQ=PhkoqNJ_b;%lV+rHlq=>FO{>WS;~o80e_mo}YK86r4p-~I}dLJAom zAqodf(108iUpioCe;&nrAswrnLu-~e*f~Vl^6>unhF#sR!hsD@d4t3sCzDLk@Mx*>Zor1I|7&Y>w%<(0K z-YP>Y`ht3topLxX80@PLnIm*F(v>q+{0X5rzlJbH>6Me>98{xeK5N1hDLJzD3P}cF zvk{}9MVS(_eHnenEfRcjeX)J}>5p8$Yu;R2H>XQ^erZrYF?xi=nVaWI1^Q%Np<8JmPEWAOW&qK5jPx-g!n2cpxp@q?C6 zPO$)uZgx(0O)t`j(wZa{JM0Jm(R>i2^_LPHWvh~)dUD?BHreZ*Swh}A$=jha5Q#I1t6*jLWMPcTyjR(smj-(@Y#XWN=jyo+z-#P7G>q;CFUYw% zL-J;&053vNsWn;2(6GyFkhWgZ=m$ZKM!y|+m5)EHw1lf#$3hcZr~$}%ld`gUXo_DV za0A?Od5Sw47VLTg&N+FZ*3GD86t@Og$c;%1LFR-8+%#WPRF3k8HI>EwI$p5Pkc%t7 z3pX}=JACzJJ?dxKm2+@|%h+cL|u!QNc>pWtl1o+PA1fR!*QGv6MeQ@QF($!b2} zy8GPW4)amRzYHHo7FB3~6{{JSLl%z)D#X*oXfLKdk-Cm!d0hD|2fMnGS{uNbTUuA6 zoW+Kv;C;RZbyffQj#9C@wdUviZq+Gx~rp7aPedQ)$U#(_0Fn6-xq92B#4 zN;C4#+T#=VVdK}3-Eni!Lrl`jdsermFx{(UdpFwxxp|YQGK+6dUp?q@3=N$0~p&y?cAB|u92Xcn7C-DC}4O&X^a(Bl7{5npduVMuK0I+ zeqR3{7DD8MlRf0QpKGHNboQNIUyC7wx20zcpuchQtDoFKmZ+&;v$LrBtTpUnw4 zbK{x8=?WX#s0|gA-^DqUxOR+dNbVdPKEZ``kJs1#t!Bm=!4mXl-W#4TrE8FC$>N86 z<-lT;p9gf1RVJFJ>7ipJC!-IIbh}E2f~Ls6%W}R3R~H^IDfDfCjH>4MsINr7gh zrMpFuZVjir)rPGGvk`M^|BeUW89T=oMV;{l=_J(+H?(|DsrseR4mMRhw09FT4Z0-3g@(pmn`Z$7914Q2lF&Ptbmb#*$lx6o`+miA!$|8XPG^cf?fQDb-x?iQ5_v>^Mo z+aws$VL2MK6U|&ek6pE~3=E|1QtX-bA-?G z?GQ+g+_$x6I2y**E2pSvUJ7thuqUAJl{&QVml>FE>4~(Rj+zH z_&XXr&Xc0VzWH=GyM5t@GLw^Gz=867B-cN|S4Tfwc*)q`+#5VL=77?EK#t_TJ!7m$wErKNf3 z2lOf>?3*GjV|5#jHmpFsiR5f&z(Udw(O&hydh*4kJSm5!^nb!@W=9b6DVg_jYLWjo5c|mx&G-;SW^}WynO%sJb$fIk(2!dBkXx zdO9&uN#!weiKlV$`jg{?q?`p#HM=ZmE?h$_w(a1rF0$G7G3j-`zoLa@s|zkfC%+?l z$$EQ0W#kZDxQL^2dSQIc9K+(aCRobm$gg|XG(8)r27Tz)j(jk=d+ z*3#an%bvlxV#LH!A`CjTiW?%#W7$Eo#LowJ7y#;ggCJ8i1o0vKh!C;wDx@LP)DE8g zzk8YCpN(afaT?G+HU^P9H>6?g`*xcp=xNtRNHTB(-VFlIHp0`W*rhD`G-1GgIRjQR zjnY`|I;P?lQ=g~l$Dj9|WwA{$NvgT1Ul@t*672F#3itJ$`D`SEx%319ff)koKxqRa zN@m5ft9q5tO8<)}E}$Y-6O67~1GzGP6F8b-ILSUyHo++|HHX^>jsY?mBx6NRx;KN^nC3Qxn|o$|LxQ8C=g$M?3O4en3xkkI3)9` zvJ651*wWT`fkw>tIU7wA*?vz((ICe3z6bEIs*IG@E0!l9xfwok{1 zfQP(J55Y#Ncv^abxB9T&EiOVDkxGD)Bw*UFJs6rvGU-_rJf2}G!Z-|q$Tly0DC|_0 z%f7368A=YX*N^p(;<9On%_IcL>pWM_4gl|V0U_5MVMa@@L)Zx>3^Z|$#zAyKdgfFi z^kb`EvE!PIDEU~=HET|SelGa$>J@y2G@=L!{t3)y9R?JSFBU*NEW1xh#DZ5S-jO5Y zBUt=A|32j*LRt>X;;$0(HC=OMr0_vx&X6Vmq_Cq!mbiIrWuQxRHdk_rlY}rTf?g@~ zi|SoeqA#(&8tYU#>->OS31M;!p#`X%&bSnR+U(cni$(~Y-4Dt9&_PF3G%xE(y-@s^ zWY5)IgzmpCJ8Bk8lIL14N#G%PZacX5()>Z5BndgjXkh)JN#qSq)x7NFA2L_oy5DE% zf31R3`eyBIExNxHd5NEioMB_>cO}UcO)t|6al0zPJnp3zGzRrm-hXMeoWu=6kJ-Bj zdgcE)d`_j{y+q46)1pY9@2d{M!sqI_K{%cp{x{{n%teeFanRaPs-(PL4wK!xPf6<> z;lpLHA>)blOik|rsCJAVSBfJbEO<$`{Z1n9;pAvE!Wjxnl4?k#1H{s5(io6bd3B^$ zlnK!|UC|jj!7*Gbd8HM^{5($HEE`4oO6iOd1x*EQz!efVft1FaWkVSO%Fu?fz`CV< z?IC&=Tu7wxtetDV`+!HSyIhh(Z1|9T6j)QN0EHi)0}gqqwy=@%V0gasI?iXk>iTKd z$K`ak{k4T;5HgJoYe1nAiHc-+-%(&*?esw|&UX0D=RF#Iu~*4V!Kl;N8dhH*b%c&} z$mrRwL2~2oa`9E*;{)$sE+*P zoY#l(KcVH1%E1$~VSoV4(a=+1n_7Z8 zR;r^_5hk{xd5*2S7YxtUa|Hkqks~^7mjfcEIz+F;%El^9&DS6;Il*H=M=$N0j<5EC zBa_%GesbFJ-%F+-Ez|Fp=Hr_zi+fG$YeQe(`8qm7<*Qu+`DE>|NsMU*?RzXDF?CyV zu4YG?A+=!}J@vm6qF_P0ZXQnZ|HOL_B}n(*SGG2}ImU5c;1ea3hB;+3lYC*faRp_@ z>oI!H8LMJ^lfg4{abTYFDcCciAyYKPi69iuttMgfo|<8Zs%f^Z@gQp@KVG|ed;IL0 zdwQA$|Leth?3@UNxhX><^9bpIW@xaHv_6Mgd&mV(Gug7dAU1x$P=x0Y7hUP%Z)L`E zXZl#L1pWbX4QMoi)q!B40YIQWgy>~Fh^MJm2oaH!t-9Q}7bx_4-NTKu`iS~hv##+{ zb3}XH2y~R3GQ_NS%juK1by*!n(N0avE|rwqF%0@+UOMY5{&a%79zQD!4nxOMKGS0c0mslKc{d*o20}-&a+J z_uICP6dW9PI^rTw%U*eaLA{nBNC6NSFgJ@)K-rYPj*g?q(tR50)V|Npm;+q*xOsn< z93j0cH{66`AjJueLd{1SBom?ulu>G8l1|@IU-g64Jbk@z(f=9Ci=VSpnbU$BnJgtfI+9(hO!JPwTRM7Ip|T z;X_BYl#(f_vS2X$U-f{o7yk1j0v8~_wb)x#ndIi;&iueRnT36oIbrqrY&F=xTVA-( z+J(R*@d-OkEDl%A6a2;ew#UKKXnUj=lcik(vJJ6{8w%=K%l596^&h0baOFl)pj`eR z7&{{$HxIs|j$3IlEq!~M9J0kyP;hDVEhOQNZ6awav^mSEO+HVSojR`no^V>GEh!}; z&9cQq?`D^GX_BNl|Cl@9hB#Q9cWVrT&$>A$DU`EAJyqSM?2+NMLE`#9$Sa_}B zwE7N(LZ6L)6JXblN*{-ozUF@`|CXn|OL;@$tRtSm(e{I_(qsMkUn@Kj0|%_de9EPU zu-(z}t}tr_Qdj_hnyy7V%z|HoghVhYzd!%A9FNgyyCs3zc)!%BkRaE4)bK-1?gzHB znuv?~_{{1EE6E;*2#6S*85LVoALBCOye;>Nkr>jZ%D*qF~c>o9h)vQOfEz zuh(dY{}bt50@Tk+5Njbsq*oKCPysGi5f{1yQ~XW2{aKC8>5p%m?vs+gCA;GyOL0om zl&WC6{2P*=K1@?!2X9=(fdVi(fJGdd!%bsji5f*vB}PW0AU@$qu!KA!*5u@-hG7xhZcou{AP;)JsouzsjJu{oqVp*hw*~e^MH&*S^rOoObwo9jUabg; z+_mm)aT&-{jc%ttkbS!3BftE-<0Ik2bC7CcPiqx0NS(_Snqy=`hfS=#UL^EZQpV5l z>TG7|h-!I?*z70B7_+Wv7s{Gp7f4}FHxRSdo9Ls-@GE$yV9f~A2j(6Mdlzi_<6}zQ z@9c+$=WF*b03RG0h}eiIG177(uH6}}!iA;&As$X75cpm6Zby#7D;+bc)R>OM0%7T! z-8Tr%=Soj3U2~|9PFvOR6V^FB{n>%QW$l7=1+8OfSp(E*xbl!3=ICq=ik*i1)d$Q= z%EQ8BNU#7uP-nxHX*3pJ6ONdcHvGiNkHV{K^LFDQbqUe>%B~#UX=wCL&4}L6gGK_b zu?95aEqOQ>w9cQ9pkam=-csnn7ThGQw+j_&-=r9s{BWBzj{2U8FtB}kV%K>X808uw zlLdge4>E%46=6+=o&r{}M2=19fGn6kQgukQds+VE+CL44xMd8CH1*cLZU}G2_m{W{ z;s}`azfh(jjby}}=0He}czfW##wx@OXc#&QUa^OQf?-6wP~E zOTYDoYqzzx!`bJ)Ra9IVAJyneezx5A@0|M7f1~mN^N|+@I4Sn+aZ&Mh`Uj}r{rxyH36VC_-8*J!+X_YMYVutz37zD`T zsdS8@=2^+XYNBwfYk?_K3(;nBk$8O$_lI8#l_O7D*N>*!d{HTaD6abiPqLmKD}$<*m|49QJShIbDV zUvt=_(Rus}U+;LvJ!C7y{JoUOS#Ev*O;TcvlKJuEXgT78O>Ej)k9uS z*pCsyN+Y}%V~e}Aq|?wC$x*laKw7*)VtcB;HM#NSG~4I*#QKC*2krMA+2M?qWWwNg zPGDR*oUa8ldrzyQE0K;AFaSnN_|QCSDIsByWLqTf^qj?o=8*I~89{^sdf6!O`ySTF zg=+xDwLQO4T1ZJ{`)AM06yDq7U^d~H#lfuas?py)nRhVlO~M()GJyuCkR2f6hKF%#8h8YYTNQN=(wlM&^_m(Iw1{=gONb z#-ywMI#(cKy<8ZkFWj^0bc9jBVOfG(>%HkBSLt~WC30bSR1Uh#R(R5B_TlJ^c?r3f!~z6dkoRed zj#+7F_`apeKA57|NPiLB!sE*DyInFyd^t)0fRM{3%@`5|APIGr(y_A}!?CHqHSB|J ziyQ|6%oXV4z^eGXp-CZwqgO*;ZqBu&rUQAYqcoj4wX^LRWxvVD6X24AvA5z4o~!3C z0PoNL(R3ATQFUE=Xc!QNlvHBqPDveLfT6p)8|e_0Ziepe?ha{0xpMSTUH4gg@3rnoMw+R(A4nkYN+I|n5s>Foxg7>fpm+khY?9!N$*o5@I_`(kFTDuh zk9}7lcF)I)frhiDR|+2PRS%~}Q(5_5c1hB-EuT^GGo+UB+ABT<+Wcxz`IPm{6#Mt_ z*cLO7K1ejnHcTfdyJUnyM83z)k8^aiy`|>PX@CvK9ZkG!no7=q$i~;dvBTgtc|&~s zN+6pU>_*P4l7{wCP3tD#<(<8;m1&`8?jxiA$w50qNK!#KkX zKflRWw|zp-ejs7O4)Ve{g9iwlUIniL&fmr^6@X7Q+iWZ-X3RQaWstrUZy zleX$z9ITao>~bi{Zh8G6(7R~D3$j5nBUfI_0t=whvu_5GC6=tjQV+kYt%R`clfR{; z?x?9fR1!a-=RA-gvi->~-+`s+&(lqtVL~JuXqT;*`diW*PnNfQl8_w9p2YFSh~@d! zD40aU)|_z3XY5sVjJ#%NIC9tl2xG&oFFa8HpvTH9nAKpTskZ{%$QX$AUZ81Xq5M6R z2Uh4ZfqnH8Y;6AJV0~B!=R~G@T2>j2fO8pz4Y-O{HdgCV`ROuF<}@NuYf4?T>?8tw zCB?H$*0L2gBdI7v} zNi5FEqol^fw=`cDiy4mD#57N}vjV=yJg0Y05+O9P^4$Ev4~f)DW&G|Laa+w$}}a>9uhb&TzE9`^nqcR?MVOow-Aca}?5b99*Ktyy@3gh$FAYFv*h@ksVZ0uJz-sqON1?g%l`UMhc9IWQywRR@qn3SD%{4Bt zDv(R+q)rc8rUi@MMDAiDYhx7dZ?-~od526=QQzQeXZ_cn#S0_uLj%3R@jSqUg@a_ z$ZhPU*wchD=>8>=!wA2K@Ais}xn00Ym~LvTVH}HX}{* z^}U9@o^Nd4d~_x+g4zd)i9&7z)&jp0GBm+?$Eyn#cIAQT0h(NRelktqyAR?NI4~r? zAmZ^;RpcsrDRge{!mlO#=lqS2rVa4X*cd8CUE4B>aRp#e+bRh~(E^2b6AUKdk*L4Z zCjG)Ytxdre&JzAxx`*OLqTmV&cxyW%FQkXAl(V+cD^2BBj@O|8HAX`@81Y{QEHa*p zr8w$Hf=!CF{wYD2Wj~Gelxy>PTzu-S>pP);A)h{N(CaKrYDu%rsA>87y2n&DPK!>m zixa59)ZAn#(3ojEW7K|8!aAac>l|R6z|F^*@lNMsy9B6|j@D~@1*>3m>TK~t;}T7e__i5mL)qtS^q5>q$#JyM}B23>4)9#pw|{c@hra~(+V zs~*|3or5`P|9ptZB=6!XwF;H7*o;C)apPnj#bU?{F4}?a=Jft5egJNqK1_rg8!II! zlyY-)cv^wwP#KmG=9L_Wo6L57e{nJtj$j++IlUEzH225wW%4Lh)&TzM=31?1o6s5 zi)_(?VmtYkJFh6zUZVl#+58c=0nPke_E|bVw92TN|pMb{zw5PL?M!KBXfN&P!s4 z1~6126akJ`G|41Y?VE}7(AnMSIGrRpl%?V>@Vf4Z^MO5xC;G*a}J)WQO01TTh$w4Ts|WWbK$ zK0Q_~h{zj|f;+vyglA-E5L)>vyVt1L1X6?6><(FT0IM^~AW{Tk;pFjQJTm`RZOd|` znZB>c7EvG(b|54{C1~GdIKe)h#Y|K*d=P3`*gN8_$*INY<+h+I9@t@bLn_SV`mfrc zSg>dDfWEFci;jHpW!oO*dq#lzfTQHzXBSgEUUx~sDKNb;gVpEe`1L%$>( zMAi?e@h2}sM?U$8&?`+nX@oa2K&=}H|N1@}u zc26b0UdU8TzA0@n0NMe`&1`+BXv@qknFU{pOpd!lH`4Svj)!9R|KVO+q7Y z5DwH1OSc?S@r=)*bntoe_LYsXbK`Il1`WzKluR4FP?9^5FgqAk_pjg2!()A;_QG#v zUetbp9^nZb$C6}=PAv-WBqu{ZkZ>?$_K->Bbdbh5Ii;l!Q)b46Ba86lW<_u`hWv%z zT2PkoN`ycAv#3NCZbQ;IOD@3Hy7(tLrXo5lW_i{K6ZQ2UPys~006TJP@ZUsKMTK?g z>`v|04=#&`$^AXTlgHDwjt^isQMdvg_N)vve2|Ei^mQSUVD|_wwb^LLgV7rNHH@))bOx2^4UWd^^Y>o7R#E?a!sYO0r zO9sroHw<87)y=Db^{76E?YxmL*;j{`cvMTjwwkONf~0kO*0Z6(MMqak z8s=Whic3oWYSk*n5e(~X9+}7fY1wDo{9p%V^V-`Iu_oNG`XATy+S$%KV}ezN=3fE%Y31gkfve$Mn z{Ml@?-2nZ&Ki|Y$ANdKtJLXL(kFok(3#ZD0U9bIxlCTqSNq@7M1&$WXAphM4k+Ckz(o_qO+$A;dU2@#L z=^B{01r^a2ztD$3Tx>i}9GAZ>RxXP!kkV^WqF2>IYeXro3YFy$r9k@~Uz@x1))GX` zv$AV`n!?JibiTtN5cCB&`fFR%Hfmq%`?B4K^#kO=mb-FiCGhVby=C6aA_T#Ba5%m*#9s`MtcaRPZZVK2> zL{9keh`qiwQP^EdnC2(@#0J=?$g|k$UzOd!-yw$Mb&N}S>kD>f9pso4YZ0+ z?apdj<>vi~8$A1v{>QUrx38jh1h+DOzHP)QB|)H(jqsCQM(kJCTo`>wG8MgWcMf)M z=bZ_gFUzwQ9u(g{5x4dZw*h_rK3v5QPWFr(^1NmQ80^w7!mDMUaSaJ+mbpjQj5~aQ z>=vtP-I)cMkNJm$<^P^1@yrWGZA?F)C@Hp%&w=}=lA@|O%@|HVI{h7_B(iXk+^`#Vp_k9gJ#+=X7I}dO6 zrdng$Zd4ua`c^Bo^wyP$BrO#hI%IS5CP#;%;UvU@AD0YXrz%}R8o!?aF?lKblbEh} z)1L$U&$r!gSf>QGUh?Czl3)u|X}&S|<&Ihu>4$Fi<&cMmzMrZo*wW^3U?UCd^w9N8 zA zfid~=PqIRCK%Ikb>&{{Ev9WaAY3qy4Qv~8G+u?n8rH#H5oL&tdMT461;FnBGfc_wT z%W$Nomr?av(O|b4?cfw(_$XhF>T8j+A{B$%4h|&<96B(uo)(Eyiz<`}UF1t(n_4%Z zkG;H}V_Dc{m#GMr{&{qm$epI5=)nLS{sKB6?spkWlT=pyXMymIcxCAt{uW<?Zi#T5Yl%DBqPcLk$5%!9t61TFWf~pR#d?wq{=5*gqdT=7? z@=HU6H(dQU{;&-x*C;PJ%j~Sp+%nfZkv-C>OC_FM{s}$DfuNkeFyzS7R&kw(AuUepbxXaZ#bk34Z zU>Pk^_G%%gvkH{$u4Nd!QVEB46O&%*a!5S*vsw=eFoPB%SWL>)ZQm>_g0Ty7(1zEq3@Akf&=pgWOgiPS!gDtl%I;l_qLhPZ=z? z6?8z~FGZO!D|Zso5Jjt_hs*Hn9u5b?eB6Qw4#JEBv^7DQecMB!uNe__9kPu&H5dBa zX<8G~pD3b_e0-c7bT(`hb2r_-w#^RKaaprfbwTiT8D59-T_5(GI97|fDzN>P-IS7W zB%kL6Z{@zZ_3sn&v0+}L0+;k*qC?OF+2AGY;9N;f9XIv`(q>^|e6%_x@v3cgNRu*{-J$C@;@Dcd7-SIqU2tBvQsggc~71)LbkM|2;=Lb@%4;Pa9K8d1+1 zdlsG1iEM@ui{Eo)JnKj3&vYIPv-t+rRUQyO-$% z47X}D7QWgs+JpJyGbN~Ayp}!^qcLH3m+_GPS>5?u{*YqzOZp=F&?Sd{=FEev1wmZ^UHdAm5n;)6B-0ofzk>%;(@%&haEcVVN^wCGHN>vUq1Wg&{4k(4|Q8*~v4;YP2cG z=QQ`t>hWZT-8v*`F$q->(0Z~*hqw6hCt~fX_gn)&^6JPVUvqmS;Y*Qqt=GhwuOdz%1?-4$P#nHE|)W21W3jT29Z>f6?siN z4<5gfk`YGfzj*0i`S;D+2gS12m^dF*10=3Qv*!?34~Vr>gumd_#LPyN*YfD99gq;9 z4Q;BBqP9TgXmP@N#;BGQtxg(u_&#wwO+$0ItT?^CiUvh3W`H*~eS_JG#Cm!^2E4i6 z)DF|htawF}Lam!HS-JZcwsR(BPLK^lbYe4yXWXxYgY-h;~{k3sBRZg2KD=SErKB5CWY9^soFz3}{3nL;Ig+W7sp zX##2XeDVVHyS=F-v91L&;Q@V3C%O5CHTLu;A+ZXf6zV9&#Ns`XCXISTv9Ie5v?NqD z({tKNz}QSU@vuV&;d!tM+DrtWA<~WUza6{lz>|Bq0wI+f@&;_48AlXt9IT~yH3?;M>AHwwkQY^aX>g=m*rMJF+)4h=>jS?6-Y3acccbSf2@ z@W<_e*&DQR#KFV*_lihk0q2&HDmx-30Kh^Fl^W<3BKugx&J|=F)-4e-z%K{om!$`? z3yASItQ5)pWl^N=8q{wu#+wG>QBoFEKue$7uDJ`lgVKW_g~L%=WJI~dJmb>8NP}mW8o+&UCRyKr;JfThYozSs^`(-Sqh%8lwb>6ctyZ)d zPPbU=WQ`z3p(?Y=bqs;fE_Zefqiun723{HQ61)cr$=}Kc`q;%$tg$|vZu%cRTeg*t zgO3?6A%%JA!C!Rou_}RNL$2aag}VR{+S?;fF7H8H3SMOI;gL+s)u3l1HPhtr0pmz- zjkR}$l6X02;tQL|u=Dz*r{X5zg#)$^@x$j!MN0w-k+insQFx6TeToqg(cE)4Y@EPA z)JJY@s~3DKZGR5IuI5g>TWNi~g6P!ZS)V8k?4OfE6C=*PmMkzzaQJtzX|&eK^(shO zCTzjO`mL5Gsfb`s4(|}aY|P^l*NY(hHVP^A;=hzcFWJ`^ZEyQ(ZY;6SxZ8%k`cCR~ z6`vFtu6Ku&w3R_#iye{JS+qpCVbE>bu6f-#?LW7C5j!JkeVU0b`VlR4S-3)G^RyLZ zz6FA0uA^UBfsKj%b$_%Z(j1L5FEQ4Xt6ZKtJ}b`R^q8g}m1c8K<<#b8$znCvhpuV~H&!hM6|Mpx+|7iha96Qomh`P8DSva$HOy=xP#Xyby{!$d00E+BDwcByCjB4wHsykzOb#h&m=SBw3#-lZqt^MS-+u9aw5l zYVe`l^hfIy|CeRub5+rDudiNSI=^IA0F2$HFP6FKZ=gpVA3EpUOi%+h1HQRS`J2Y= zT_Z9=eppR-h#(yKc8$~ZelU`JjP8!2koG6roTzETKz>n%V8NOBd2+o=G%%JKZTVKmW@E zq-IF4z{_}dEFLC>L(T1^yf(|z>@eTj$kH5V=Wq()GaGbO(cT!$#3n}laavfoOuMtg zzx+n*XLbHtkHq}hDeChOnIuXUXS1!23K*H*Q8S5t47!GI3zuLL>`>yaqN=aDw$sNN zUXn=rx_}^k1EK>9lnHF`gp+B|k;#N`;|xbYkl#ymq=oiNy+ZPYe=*T^AYlMN6@&*H z*_Vv5eOIL|`P=8er$ZotT`iK*JHsYc^#}QM;NeGAhR-rV;hF6YV#$1Q?K&h!uuO_G zwDvbO&MPAKpX8N2T)#b{2lvg}zC*uB>mS-cJf5bqKCG|@9unMl6+P#mynkG)j__}V zmxS=)t?(HTdJ=n4V_}9Xnt)sK!sh4o-b*}VlEoKrG735-;;7R8I=oieI=x($w13v{ z`^%~wwq6A)9u*f$iWRm7YsbC9B>alX+7Z|?PAy($v-Op_Gt(=E;VO&Cf}k_;m;bI` zO6kqK^9x%}R~^Z9DGu?CI1g#ESJghsG>Ft}jmcxXK)|Oct!ebQA_!@P^sl_iqEZ$j zB_B3jyq<)16Md{rkQV;F$ozFgDeXEh`Rsr_p$IAj#-yRJq?Yj4K?;gr82zH8)j~+u zg5%ctAY4B)&E^R`HvrJzmruWt1!Hc*hwx{aHyqN8ihF+@hM=aNQO952KDzRa;waS; z4_xx#frJ}|bV^i(-8bU2b^Ls9HxZAAo%NndMT%D@$W$MT=|~whVOrMKbl*tO;K%AB zb1*VY3zIPw2fobbNI6Qf;=Z(bp)L9?LEt?GBrNvrEvrac{#vF{_T18b4qt@_)oSg^ z#DPHrtMO85C0Ynj56A0qz4HETSc2|D_SwfiqgIIkM8|ai;!SrzTa~FHJuPW3pBXJt zDGJN5k+r5ggg!awBDBi7D$tG=Yipwn{qVE(xGr2MImfXzGgO|%sod#^p*PsTKL)$RRbAs@U}!=JyJnbEtr zy~jfM#8-O=x9x|ryOX;NdOZIb)&1dkrn@UDrnRK-H1DxOZ_n#Z z!0Ix2yn7f%??{@--mYQ)5Gmb$ve0cn{||c^{3Q`O6w4KSCObg~m$4Q4cRlJ9`8Hix z`+3>T9+`%RzIVC83jzgWhF76xEr6_f+NS=L)+o4}qiWRhUyEaoj7W3ukpAH3K98re zwwqJZgQGuTfz-6Z{fdf3OXQK^E=fc&;N;o?J>pUn4wq+5B!IF--;zvXb>H_{LN7*k zgv`|7xF6k3K*4Oe7Qbd8Dv971D@zABzcX1|TIk3RD#;uZTv+smf(7hK?$ex}*IG6{ zm;P_yegPn0`J9NHHM1g+Vw7;YRz~-8f0X3K0qrO}+Tu#PIIqDYyOO<(NPJ<9e&Fn= z-_Q#HyZCPtWG>VMGR{{i7{a87{t_R#O2yNdKW6j=RcvM0PZs^Yx}C_RDc5)x8tNAG zPoL=mJzleHDjc2Ku$mYf?Vhe6IDuuz3znfd2>v_>J&0KZG+ZmHg`SjNb=a4l=+?K% z-R+$vl1#Q`j%w%gv}h+Z5ig(05|4JD?Xs8O6sDFxZuE9#!fO(V6k}N=A;AhAxC*J9 zbGLe>1HOfLe@)5cAVR)3cu7u*3aKL8b>)V;$L6V zo_fz|ASe|Jx$*Qug%&p;*ERo?zc!yTt{V?ghm|-`&WOaDW_5jlfAK!xRY3Q^cYCW0 z%$0c5{=$$)$lYEY;lX>Ve`R_r{eb8~JR-*0;H`E^5PfTm1fEY@bZH#P zFakhA;1p(&;%iYDnTg6M@~AVJ)pQ?=W;_A=3%!#WtnAuyUU)1+4&dlx>rV>-KNCBw z#~%&Ow3Du)^pGmsS1fotd~HL*s;XD-LO<6EjZ{}2S@U^YuI#U;OH^%Y?)8ZnF3~;p z9;78QiUd+Y=vsw}^hXS*$n|?ZB19vTMim-bJTI=-l3_h8n%i9Wed1G@Ez&d`gc8R! z=#NqsC3~D$l$X~ zy2jm5tr=Mpeklj9f(SBhGIVX4;~Efnh`i0)2OCS0*?w&@uX0zf91l~()D`cx`{;Y? z%FW)pdT$XTry()@2j>8bSDYX3`|ML{Y`q?hHM->}?TIYW$<4@xTpOhbut`YX>&Gma zHjxrrooF7k7KQHrEwa#Hdd(3rp~(b4;XbuAD)A?@pWHo-6hvlM*)_{`vR^hbqdcMK z1V9jrBn^Ki-vbUn}=^d}0HKjR`(fw6Ilqdwyhy+9M_NoM{` z6O}~WYP;}2_;`9hTH#!* z1i-V@R@-?F`cAZq^^96_)O+ddeXHzeD-HL$ey<^qP^OgHLkku5T=8>}@3XVH1-H)t zff>YLS(c)uErEm@66ID4X59hdb{=>(D!Q!KRj()FEp-TeUG2U{yj!j(#ih?Wx1zz! z9a09^+oF2cAN4l*jYl&VV{PJS(kc!qw3yM-$YGs~9t9nZOxm*(ILxC#B_FL^DPv(v zqf0{(6!lFseQ&Hr|GDU14s2XCe@TvQo$`~cil$#jrgK6-Rt{Iexn z0LnyKZ6R;Kq)bml1GB$CkR&0)?DoiDEV?={Q5zx`Z1`hfoVI0rSo$->qCoxEdSmh% zjfd0qOdo%eD6l+!Ae|#w;53gVIu;tuCYE3#Tgr=B%Hq`5+rj46l6%4UWP}A~MyYo4 z4s7SHzw5NBS*6+4GFY{6qjgE2w&yQ7ALKf5?&|9O96?q0B9;Jh-fi>uK> z5T!54(q9s}Nx_AnTm6Yrlj^@(wwWUw9`3X`o#8}8XiyHm(h_PH zRXy}UZmCH z7_xupM$C635P7FxuRmIEXs)r_rJy#Ly$sf*h4X8|py63@xSe6ICpE+y2%0_9Ac8*| z)-hsXKe1i@C_=6TdWvm9$u|u#k?{RNOyl0JrcT~$0pn+&7mDg8qAz&S$~gYlfRT1L zPhu2QVu2?yN=sKc_W73W{%b_sp5 zVftg1f_fANG@oGtKj+QKCqWCNo_(@mg=e@jQ@c&r+_;GDwv*h4Wq~Lxqfrf#YWF%U z5o2tap`1J=xd0bihQiLena7_QTG3B2f2u;UcaeGHdue_=Nx^cXA}de7&>jGEQI8yd zx&c9aPr##Yka~-p zm%F?+!E|;dxVY@ujt9Pj*B9~blTcqQpp=9p#Cs6*3oaxzhuG+}jl-wSDOl!h6d;U3NBAN(ZM zoRnz&fJ}~LpT0(otCq>W7Y^Y6I0Ez$t45_)kn6SdxBb;kk)=;-ON5J}*1-4+wOqEu zwKD0aDJ$XQ&Wkceh5$uf%r`GStTwRGRA!ydhJCw{kkDNNE6)WeNaw`ajWB z97x!nVzZoM)o#nuX(~^Ym47BvbM;->xEN66Stq`}xso|Li1^fAyLfgaTt4)(r~M|_ ztfgtmwhpNWII4(0jx7qLHJAWWCry%#VN*C5RGd{#s6{#O+l5F46j51)F_z6US%KXn ziz*K2BS6FzjjR&B|Jp&EHLMx&k2Y|9e~f3@ne z7{Tgjtgkf``+O8;htY9uJ|CTm>~daz^my!RcJbOES}}A=@cx>_%>slsw?s$_(Ppp` zqm>$AwwXyFd7sZz3h^CRaVYbZcE}}b^dP0X0@NdxtP?IiO*ke`=s||AeO7%szJE|Q zxjlr&35+%D6aR*nNFwLdcw zb(xKWoCdPvRzByQP1Fa3%suoLth}EWl?KjbBPWshQ_?1o!%%1<2lcHd;@W3dNvN>} zz;ecChGWg5BjFBWUJa%NXgNECCGldT-1xw-eEVY?tui20)&)tQ%_7Dx^?-{GJ7m~J zF%%a&d@R%CRFRm8sQfWwVGT?Pydm4HkcR_1$rAf@sj)Y0Pw4pzAgH8y65+C8{l{=; z@$Tsi>3(QU?@P~Dr=={kbjSaC{gTV{G5)^mZvAdF+z@F98=+Ok=8{_R8bnHJSOjX) zR(D}bpZrP%f!Z3MCba5IE2E`?A>=aR z+nF}={1`okPKdGnvxT}q$;(_o{15}_Yt%i7@xE_}p@ZrsufL6oJu#%6>QtRcha0Cz zho8HihuzJ9qseZ4Bj+ML^dL>LAleZX9I=xy`y&RnlL)(orJndc_UIMB2JLFtVzgj6 zP+5+X1cU3~h?p%>aX$MK;BV8blTGd6HAiT086dV+?Kduk^89fD zuZ)=yeC(~vN=cX0Wos7}7i9*16F8fc#F~7gDm#&`Re>2sn3ScTkKw2%+g4U=BRTLr1=PZ{~690 z3Pidr{3Q%vLCqyY2WYS}iX0vY!%Y)U@=4NY@B5M6%69sY-RTo=>0A;K45&)O23Se~ zIo(mqIq>q6$iTCU<`-Tq_!)tJK+J?@DbMI!zs(jTjw*AnDcjN-S3#xJ=&WLYW)bON zzmKPEAyr0WtI8^vQS|HP*L^i^K2_o2wTDH|E|TbC3yZTREESJ`HF4^698qgwfyV@> zpe3mAAZO$N?D( zQ#+-KeM?p9hUj@p(6Aa5TK+Digb?kXtn;eXKB4Cvc?0%BQcgTj`DmZ^_&G{!j(gN{~d zbn-d0iC!Qki7%$MY!6e@#|7Kki5u_^^5o>9ikKYlJPTki5 z?@A5EhyiFQdM~U4nQv)iA{&ma%oVo57CBSA6us%j=FuFE#1I@!A$$n zbcK*WH(Dqlo%IS8SN(0hbt!uNm@*sWpC}5E6c1DxLw|%*VAaz8Ll_$}Q1bNz4JUQR zrFibLHoSUGp{U)@L7%Po)owIbgyLmLog>jBoxK9dFykK2DRR|(NJq`@NeDe=8H}#@=?s=q=o0n z4cel7wUK&-kAcHXlfqIgBuV6hK!dV+U8%~Wr~>O@%J{yAN44zFMbKm!(at6gACPg>iYv@UjL)I&Nh9S_@I>i z#v|aNYl_!3tRb744{Yg;rjanVyxbH+^OqyqG!~~&kCL*Lkk@otxu$l zOyePO_FSY0ri-rN7R0i5$N9&UC#Qfu4Y?DZ{U|<|#PXFtO>+9*1)hrAGaYamSEEmc zC-wX1uW-Z)Eh<;Je^g=N^&byjRoa4O*kqYVH%!hD={vZ_38^F?Y9k>U3@36fN@8~>oATGLuiaE7;03sfXofkI7OWYF~;6N7ogbRlX=47?Qj zgy7t5&J<-C*5EP>c`D=3;sd1( z=nfYIY&>o~niszNo)zU;*=!EOuPm1CZRZp(?BbVXv#y>pNSf#IAID>2{8m8=PcucZ^qR> zCkoUu&7q8F3y%~pl32KpT@w5g$!-NKl51&;noTf-e_Fw2O;o9r{m?A_-Tvzu(_t82 zQ7Jh@s{upFS+2}VW)qz4n#o3yK!*Eq`1uO(qE^fp3uBvTo8 z6!rU0{~?;0g-Ra|rmtVw8T@ax9_FlrMx7(08eSZy)SZsdI3w5X&H?>ytf8WpKC{2GkPb*;Cg*? z4Iw-cEtAg}S;=$yZ&QJMtg^n0*(-4!BxQ1a2!EEL304GlcQlmk_S3127CZlt zQ`|{v|K6JVwslu?hvoa9i9L}8E#}Y+K4D%PqGG6t67))T2;VxaJrrEEe*93CZfFGs z0ITJBh9yTJg`F;hN(!8_P3#}OnBx`J_0F$bHb#i(K?!%5`a?7sG}KE;K8%&nhNSW6IVB*0PwUpl9$79 zZ!OGH>Coh(N@OpTrF4wBW{hr@Z9gqy%~R$&32P}LKAsEIoQ2l>991xN}^?nTNr~%hiCqE73ZkQCqI0{ZMr&Wb4fAoX3$dW_T$? znE!wi`${TVW5d%f{=M3!_T%AtXT@72#}Z%OzUH2cScG^*jisSNL!3p%Jws*Hc&dfj zBG`E%I~v9tX)riKw)HAWn=XD$sjggj{Su5w}cNWa~`voI$=#n)nK|#T$^chxjuH{ge)ZcY8(VPCM#&Q0}wVG7O zBr3@)zuP1_GfZ9dsrMj-CF^s@O@*5UE0rtq%9;-)#eNClAStr=* zzC>~h@46qgPajUZE1j*J5)%FJ`!!i`-V>SAOKr=rS1X$ZZHH`Ch<=o1rv;fpKbk7@ z>gyy7C66#*y!5%BraYcqay-~)S6<2!`ArA%+*6#&?*3b?`}KpV(!D%RkkUR&)N64e zUB-hC*+Kb+*J4Wxl+}$penOzNnsHhhh5a+vfV%*`1Ij}xD7lp$OASDnDx779A?OeI zC&UPzv@Si23AF&FGmaLZXArn#Ghtic$K?+1m+U1tu_Wq!Goc8Wu6?)QQa#16H{I&Y z#~Izhw!8mb;@y|0!d(N1p5-FnX+HEE8Lr4zzIkfidvi(ESaKY$oKt>1E-kdw+wn@Y z%|4T}Bkzkwu{ZT=xlL%~iKi#)pTa+QHMY$EabUc{aBktnm>^>K1oj#aJ2dZ!Fui=Y z;yl!Fw^$rcjL9`Ht*++YNS|i?chg0GV z)9>CcK^F4Bs26E=P{x)Sf;zt_E`@P5D;tr5B6>09+Q4Qe_0x|CzWGH@8D_~@vr^)gjLxJudC^m!Q)(NM1?;6oJczDa(C=8vPCj&6 zw@@r5VNqh7|9TH{&$S)&^xFl~`?dr>%xMByoPie~f>@FXvK3_gFq2u^ruV&)B zx$JT9v**m`;jy?owK6{4PKs?9P{J0N2wPka56w4Q5ZK1iJ7hR;5a3A(R->ho`d%;n zrm3`w3LY+8udH*&dHnTu?>F3jV6EPmsPA7HURuY;@Kg`Tw$jtQBm@8jmOzKG*N5sMPFVBJ;YQ46HOz;P%sl!+5|9Dt@lFYwU< z=_?YW^`Cwrkw$$TMA_U5WPbZzx zQBub;sgRNM8vbqsNHKN#t7T$BeB7wec>C5nJ^!C{fjc(69X^nb5e<*U&1y8$fA~vW zhaT-$V$R#%)W_-d$y8@&r$AjZ?7-~~;bH^Ev`Q5FPw^c8^yabj?Y4&EQLMw$-K)8Y zmAm3*o7yWDkFbTVH#GH3Rc!-ahNb0Rb|FLuzv-hw^deOh)pDEW^TJb*A*i|t%^OU^B7dRhw~J!-O(ur48Zn1J^rQ?4Oq`lShf6|y5uX82oK0hGe57}Cd zf*gTt0u%;#wYzf5*0hsquEZcEKN1@^6sxRtFYfWi|6}PY*rMRN?a)KY44u;5T@pk0 z&?Vg|9V*f=ba!`4Bi$n1-6)`RgRcnO!SDWs^Q?3B*?X^mX4%>|H&G{!O5xVuR2D*f zcgbP6KaBr-?ih8NQdtf+CZMLz`B*3L?%6YiV}ZKdQtesPEyQ%R?K?-d`p4T|&m154 zVBy%~>iTfkrd42$j+tr%gBbB7oKEq=kV|MBBxtJb$8IGxW6b)Rk}tH5AjPq&=-Jku zC0WXforKs#iM57HJp1F~jxQnmfN(|PQrE=ct`cRwo&Kn!^EG4?2RknM6<;)4Mh;@p_aO5c9tTwY zh4Tw-lxdx5^fK_>g78$Nfcp9hvBY2=P$OD9Mn;IbzfnmK0kBhDmtAG()31~PHL)6;{v{y{dyy$8Bex;>GJc4YM zlrjvG_s2PYNNQ`Q`%X_g3CUS0o)1NSg88lfn_t!M+8y*D3`bRS@G;)<S^9lDPv}au8@~y4<0rhAR5s~_$^Oy z*G_u$%?o;t17GRqzFa#NV%nD^r(bV9{R&oy#=~IHkMEwT$J+H~r-@AD8^ABFXhmF&*zU)%oZ*Fg&SCxNoh6O@G{6KFp1dbv{j!@ua zeDpvJQ?61MC;$}**kw+JQ7JV;-!ub5C)G0ED~Qgpg2@)>U`6n@taYH2d;XJTL}(0~ z77{jrQV|ogdBuC#zVlC37o@Mx=E~DjW`APg7RacDW;qVXL@^&SX}C`@NfxU}tL0_XQl6}8vHibC8_2uCL9DSdl(@^Uu zyXi}ArxE5?o#@Y>F00y-HE2*YJcAlR`;N2mn2TjoauW(e!BbMGdryicn(m=iphV9y%+d^0&%nY42i^kWB+}QIgvC!RcS> zVHdFAF(jjwl2P!g%5VA6#t^-{^Rjg*M#~`E0U$+dEHGEhsHlr;!TqLO&aW`l#|ov$ z;A3%7c4GW}R+&cW7d;0(iFW4@tw(P`fkq?e{bqq1BEvsF+0JhXk(M{}-*xt0otfXX z%FUS-dh(k!1{OG{R&rs^nc;3RC58bmfs}RKk|7--)e_!(4>*xzx8AwT^79T09S7gihB6w>yJCFlZ(NdxXP+aD zqLoduH4Ye+VJ}{*bg_TZSh$AU`DPvooS!WaTk+NPvm#VgoW(5usWLkh`y4u$_fH6S z7YJI_gQLd_13&B1KO&RqH*O`k)v7B_ZbaTd5TEznm(=ggYXd%GSONd277stGxEj$k zk3?xRAEP(jkd`xr@-H{i$BwEhD}`*UK+Fl6!%f$M3UEcw9Kk?|?W4rIvKk@B;}*GXoo&4@aWE4et`*g#-Gue;W1^hs(Mz7cs5 z!oAwX{72~(;Cn&b$yI)-Z3?F*&-NRJJ>wkRsV*+PGGQQUC`58ag~i?`a8J6b8vzol zZ|vm1q4lfxq$@LAKij@Y8ki!7OH`pWESYB3iNO+b#G=CJ?9cJDAw($|1q~A|(yB;A zX-0LVWrCzi z!uz%Vb_L}_+=#sBch>oDwyi?43J`jal;%Sl_bjWQ&!vAw&wO6l&hd&n-+Uab9w(tk z%tvh?Y-2~f!jt@B#$F^!NhN|n(X~*qpCHccjQm0O7^PJ=v$h5&h1!8q9=;oc=V1Uq zU%P|gAI2z&iWe=ZuR%&2+L6C5Rfl&DUV_l>N&O3V0g~#*f zk!)lHt{JqCn2j`2d1}^%k7tHyUqe|1zb^@FuJUp7njh?W~-l|6-imupT}s6CIE_1#2CP{QC$g_r$`UK%BP*BKGz6@AmG5HK!cc$E?X6&D=Z z_k+>^GH;8I&$CFt_7?CJ%B4{()ce$P{xmUK-XRA=F_%GOYY76Ps}YhVU}1!dY+0Ut0uucV^ zS(ucD{y0O*7&sCbIOpx{z!{@i!_s%n)+2nF)gxRpMEtcx;oEQhV76e_yrIpdDSOQa zS;7B^9l!8Id5?j~O@s^(1nOYU##&fY&PVyb-1g?D@W{DaT$UYnXrtHM-uc`@A=IOve?12zG_~>8qT*5lM z!S#Sp=f5yPYNWsRA@|{~%+=-S7Xp%~^kw%31|kEM>(zD$zW1CdCHO_q?T#maQ~jlw|+yG%YRd8?9E?LX!QQ zHzgm9AW}aufQAfP*r8K|EM6gj-T|iP&!yCCwsZ_H?s#H~&8AV}IUv{XCKXH)6aE-R~L$q7LIPiiNqhcCj(5O zRN;fYCyjY5L^fBZs-dpf{o0+(uHl%=_vbd%U(NAdHz?6%tgXx{>B~xdyt<75|Hj?7 zwZ*5mAC%*z8aMt_4vFFmtw+%P_bFh4RQg=^Qr(B?Nwv$`Bg*mq-iO7w_4C*~0aL}m zxMo@_Hi#Qkn_iggjT!VuA2l7dmkq&3rgWBBtPXPsElAVHGnaTLNX#u!TP2ZS@msg; zm`~Kzdhy1b?#imk&SR8m-5kuJBwnM5G_xzLc4VPo>LV5#x$$n;3wq%C(?!*Py&WF460h!vngcZseR9*>*B^$vW56pb#guTxBG+VVfnhqsAE}!D>6~tQ zlgdg|T^v+(s2Z1!Z3G1IzE$HN|8rXzUN&yzF+G`M)8dd#F|juAy?piUb3zV6#MS-d zk(Bp!>a;}HP4Dyht!U>KyuPLzSg6uS+LSj8+Xpju@b-{nWG16_lPJ3^ul?!g>CpYO zVtVBJ8hu16oS*M&vWc+cq_V67E=6)qqY}$ePbc}v*ES(HVCM^ZP6A*3{s}i-n>r%N ze<6|EXBG}iK~N&99Ec?e0c;lWqRP}$yrwKsGHRA!QQ#0G79vfuO>^*GglF1CdyKxnF^(_rv_e#=Ul7&pj zla{ioG>XGQ&ZbJ=fRr?+voOQ$laj_u>G}_x?{*DLKd_GceP!=54PvF(6x$DElc&}tr3lXaxvbNX@z&TR3X90xG7U1L6rt{NCAW4d1JW- z1|H0%HlLOmXmF85-v~mz%aNy%m@<554{bPh;a%;RaUrU|C=)kP;uUK19w$SF%bHz>6x1@+BIllVT~vgllKK zk}F-+WvEDzPn$$0HjFOZm!FPpLl>d6$wtp&Jn_}(e-}oC?nNvNZT#YuZiY6Dbf1JR zZ&FgPeka_Ilz(bJaGSS)&@ft*WkO2woC=9tonAMDnH((qeU11>Ba5N+_M`J%@AJ{a zle+~)X(C@FZjh{`6e4qN=vzaMv2*z^F%yE1=$g&+fT|=#t1v{bucaJ~eqCP!3Y_X6 z)GDCbP=J3*4j72@9kPgM1AfLx>4;5+(JG)~aa1wCpyxIagn}1&Lgg0pNO1}OE9qmK zN*tMvJ`tAPNO_yo$5ytukMqh{Oxam~`K4;=XrwY`?VHt@e$Clio@9=Qw(5OHqu4RZ z7xj3yQSGH#980IHkQ3=E3ucdDr_xyU0fg=_v3}gtYC&@tMf#$Zbo%RPJyr^XajC?A z#l&p((Qy2OonPIjaYdKUmc!u`!-%PsbH?J}9P}o!k6Ya5lXp?p6#DS>p$- zsa)C~MP%tXj7edgHQ^=PJ(O>0syX3AD4q9wuD4OdFixwik}N6ZsleirVty4Om2lC% zAAGZ!jIY(m4#ldpMm!RyVX==!Fk&k==v+2j5tu&RYLBolaRT5~cp`o?=$mDC)tuF4 z((Njbh!5UydKJA&Lu!WR1+H>I8I80z@M30S5g}?6VG8yU$oVB)-ny?-DYq8wLdC>t zZ=%DEy0c>Unh9ODAlmsuroE~}H!#|n$*;vJsC(Ng)A4Ll88}n;Rc1gZ(_w*L`>mRl zKpH#kAj9@-!2ISz_ZP0GgH-?$gHckSa*T*1cqpzp?J5gF?how(b1IkbkBXHXq#9O{ zLX1)ca6-DiAZxHg|D0oeOj(ZukVv#-f-d6a;NXTOr?24_qwgTpxeafUaqMQ3X7|I@ z3KOh@^MuNdh0dmgMJ_To7Ic8J5#ZEk(}yodOa19M#Ru8B&w3`O_BJ%1dcz%_*Br~v zdp1VBjjWRRLb*}+l+eYxakY{5Cj!0kRl-$5qQe$kL8vFWX(H1EgvJ4_KVV7Ae&r5X zq!JZU+O!-p%o7sDo=+7@EHTd3_;H$ZhzuiPRWSRvjd+p-uWVLot31;~&0=dhDfrlq z!BzSDubPgMG82O*-Vze)a#ljjUTtd6}qY zvFMe`Q^gDhW5!Z%5KkI6Xf-j?=sXugS!t!|sD@JG(uMY7=U{^DHRlOB@?-LfF`JH= zbXCJLuAAm$Dn>dIACf4>KTdpAerE&zkj(jM@N;~cl{GQ3^rsjE7OEmOiDyhlGgG>a z@_Tb|b1SM_y8eCl!|tY5fCo$ADqSmIBt3wYDv2n8+!G?1bOu@cv{iuz1)*XG6t6`hTF5sz=fK!y8r_`9CiSoBAtauV97kP3JPDiX?g5O z>Xil>VM5|T-vv)%lZN;)PN{Z^Atv)`P%`hsW(p2hTL&W4pgsAUq#W@M>oDckk&A#2 zy(VpV1=Os0oe!XxQh~)xmNgHts{8U2>xz$+bPHFPLF7Ftkv!fjg^Lhd;)dmWt(niU z&zs}zuvWf66uTsPQuG)I%AcB{ai+ICtKiwZ>JOhODZ>h`AqG5kIc!(si7K-y%6J7~ z&0GZ}765i31Hp?(*>D1Qa5QM@<>26tcBcFba}9&3gbV&*rnF3I#R@Gmlh zp)CEzWbxz^ zyl=P;#)FVCa1ub6$jFf4T&&la#m{?S(LEew)w$f9OkTNc&#BhFi7tHoj2~6@Bw; zd>cSezPy(IEeK64Agjc`eBO%l z>Ah0Ai0PGmqc%YFjkjaWN>;Jax>Vh3zAIud)MheIEgC+_y{n)}DV z%JcSPM}@OjYDp?kQEH%`n|3G!YKiZqCv#MBDL1H0>f;}DqgAkbr z2A(mJET>;V`RkzB{^HNe%iyUy?kS|Hqsx3tnqjE>Ur|gxdLdb~=1*9q=p+Z%K|K zV_VW>rV7-(--lqPv>}FRgyrC9Rs&G?N;@$*Lw4+TuQI8%7f~h|Sh`aH+49 zng{tQ<@M#@qLEWjN2Z;^3-Uv60T zE|0DC9+`fs2Jr5SO{u##KEL*2)9U< z@%hlhYi#wH#vcv}olbYxZ8bky3X=})X{qXT4~jF6q}QiUJqX<2xqMV_==9aSd-B$n zHiF041CoT$6P2~z#Maigfw2cTllm%Hz6ER#zha3K!(F)1c+O5_#z0ii{6<1IolO@h zM5ay5!>=Cr<nayjO!^T$3xo1SOK9DhUwMYq8ft6?EWD4_)xyJnNY+v>H8!a5yw zYZ=-?voc9YHGh&oRpm2G=5$iaVlBs;C@aS&qo(pYE!`^rO`s$%G{o*1;MR!p4V~(t zGhLta5Gj)69t~Z?YD$Do$ioS#)gUB2APY-CT$Feyf_v1jGKFNE&u!Zkk7lv{*d>s=fH=;xV<+Od|LLIF3~XrSxiC7 z88fN{7KjB6LZ_P)8PdOwX8o{R*7hLHwK*!wf+Z9}?v1b9ADfY%K)km&DIpmX5j9Yf z2QKk2B=A4HKY2k9+*SM*Dfy*O<7BynH@Hqk)MTS0;mXtexej+rwB^=zwj}G_vEn4n z57tb*$f$;>7_ZF|z9XGG=0Wv$iN!NFu7`?Tzdbx=EuK71jd&|M+0!5^OS(~^#Ndls zp{TgR0z38*Tx)II!y0`AskT198fgba79AS7DHeWf?6b)-ZawH|cn^vc*N8h(GJexu zJhsdu;&h70o!ygYfP&+_G@CrLQH&=-Vl$f({T5#d8wo&|^8p`Q>;V=@Zo=%5F`#Zo zIj(QWV__gvC}6uT`|h2~lg+~Txs?@SXrQMQmce%!>#7SglqV=(PKn}Ih34{7Z0F0! zh0;E{fz!mOm$zp>5LEl)Wi*ROR>}=;H(bFfR89i@Dl!*U^mkQ7W6bK4*YV7>@w29D7dh({ex)y`M3hJP?CSZ4L7In!P`NIhBsYX=rv$+~P%B6Z7Oo*Tzy)0`SDI-SkJyGP&IwG@Fft}& zy#8#Lul+}s=MIwc=ElD8(JBQZE#UG-lQ}V;j-Ek1@9qHS%{tpYYtP%CqlwhE=15bf z552qsrH?K32#5fxa6~?;c2ZE-9t>J0)I(H^7Tdx|pW67i-FO5Gg((1++G-AB1~pn6 zf6_`s{o9C~0zd@+T&99?>A2wpEPly~DN=JQl`;vmuKS9$qX^aEY-9lpA{{f!EKn1y zUxG2|p{QKEkz3tV?0PNJWuaGqSG<6Mm}1C$K#gVC0un(?risenmL?(p6m@d`cRbyQ zP9;H`OHu}+JhK~8!qhUyr)!uQCz>~w9+rm9T2^Q92dxRm+o0YUX2#Q#;IR}}l09LKt1l~^ zK_tEq6ALX9i>o%U$OaWrHUmXqd;WI&ano3uBTZnIc`P#6NIPK!y<(?~WhD+{6|p&u zqm#(!*U7x7OV4{JGgbWZ>KrgkPHu#k#q6tRP$F%~j1dAaM)ozu#57hb%)!cmLA0i} z^}`F|eg}dLHvi@K5dCw-V|&miEoSaopyy$h3>sFiBms?XH0bIA9Y39ax5mGg`_{Bs z{XF24cg=MwaQFOl;+Q}0e-j|l^7J%)-0ENJloW+k6K1AE&x{-?Dia)90TPTp$~vm* zE3oN1=FjrJGU;YpSBOMp3|ir4LCURfO2szRVBN~ftHiVjbmew5tB&FWf@B;2Hb}29 z#g=(9`mxE};D$akd zgY!h&S8H2Z=NK}CEU1{;-C_$A8fG{S^iyIp8TL-Czm?k8iCJh+$0<1*QsEbrP7<#j z6Nf`$41q0M9Z8s$pD1mh?o-k!-f|uy+>;s=2j3S=70;a5ET{R)&mJF8lc|AH4hj0ad5NdEYKV$wHW3}-Ow|71WH$xxUZx@g5&T?f`g<8c zMU|DVvDF4vkom9T5O)qZCx0kBU0`5DU`Gd{K^zEm-jl9T&T?mKw@sHM!7ko2)pI#N zSQI%rmIT!9=%;ODjQ%p*(If~{LY9%!c7Cr}s}r%qvHP3XcMkb;n&b?JpCYk}TNIla za4z{9Cq|5Xqe_nf{6JzZztXjGOm7hS?DN3T~BAPzSrWFGChK~DF2L69x32c zN$2lGMK94c1+Ypn=9}2Jl<$z}D@~8mrUc$U=~APZybHK^ViJYxX3mbDH#e&?vK^gE z;?#Kvkc0ZogWQ8+f<|$>=4Dllhuby+&GZ%YU*jYGl){qHRoV3tsh3RN4Nzw}fh+fR zG?;T+L?+r>KdD)7& z04c#?1MN^lY%r!lr&^TNKBH&hG6if)TbzCCNu?U(&l2i&(Bh3Bs{MiKZMj}`u5Vq0KPOLKNOMcbI!v*4}8~8A^S9!vbpW<#SxV=M+fjssGs% z=5SUy+McY=k1%3$YYtj=lB5a_!$Y8dJ$}upev{!(rRzFPMCSUoK}mmOcbHDD0Bh!R zs0hYpF{MGMLCy|`7Fo1!vw`R^O;Nn5)LH@_AZf6qS{7P#qRt*TC27pc0Y`Jc@Z zlqYCr@kDK8-Z4;9(%lFR3j;MCn;Kn=O6yO~w8Qcv1Xb_CRr}IH_6d#ES z9g}v|szn!h@A13AfX2Hc6SyAM9<)e)K)Q=NqobTadC2UL$rBvN=9`S~R>)Su_8Jc} zgockzNzjc^z?f0%dn3eMM?}#u`C3bVS=p*Fg;mb4$avHm|K$)a196$*QN{4T5-wf? zTxLb`MRRszzrsnf`TZ@o?PJLbWYCgr-#3I*c-iQ)leE1Nq{&!V$!hY@uIZy#>F+KI zE{iqZw|_Ps9&?}l{MJr4AG5q2ot^0>F_`=DzBVCZ^2-5W44F20`x^cvNS5JL_obs5 z!9Tvg0%IiY(k6=+M$Azd){ja5$VJG#mHt5<3wqJEZ+y5Wn@dx>FHl zYZZu;MpKX^coz*3sgFJOW+C9$aG@!{VP^tZ$y>5nbqZL^dBj!TynTjsZ3#93htam94~8 zH2DV-uaM?qU)* zP>&d{i@$D{#_ylJDz-wSrf7s3Plk%6uyRa&X505K71kdLaBw_3%+g z+n2xjnJwQPZxQO337}+|aqY!Y1308Iym98R_HV|os5>zbe-m?E+YZt7X@-vqTUbf= z-LNQd8ir{n3W=*^RL&-9enT~V_mp*dc0LAsm#Y#8h2W(2Cr9hP4U-;K3!+NvNz`A+ z^3rNiz~>?&CxgcDxGQRUC~7+-O=;+_#9=zov(`+6kH*-yIAv`_vx{O2%FU;Upi~uv zGz-93nbZ>#I@utGjpQs1dkmxP*OSVn8#jJ$?p2~`#xqSPo}XC~3XT7Efh_|9s^NN> z&$*|IMF^N93cHxaM*SmTQ7I=F4b;u?`QzVwuq~xZX-<;(eOYBF z%Qz;Ny9O_?uqD0zZs855VvZ*F=NpXy#_CN+*(Iz1>X&PG1;CXegIBJ15K=0)Hz~0< zNOg1`yg2d9V}PVB9^`UPD}Qsof+WGih4?S^Cq}pwvY|zOr5Uawa!#}yueCJBEp7!= zj_KUy)MarG$M9*u;k&7X8CjMa`^f@~j_PY8Ts#TP+#%TECQcM0c))2PZWd25Mxq#$ zkpyDTlEM`c78eSE;?RR(X7T(7xO+-9eYOFaGuUflSA{24iVZmi1(`gO8<*R2iQsQg zTIWn3A%GlJib`sK@xpxuB8>Y$SV}cKE~lat1;E*PK@VJ)Z;<-3k}kqxc`>zh&Y_~t zL!c>^W%_JF5pPxZacfCvn|?Io{YK&OV#1&HC2l}vL7yZLD8pnh3DHN2#gHFJW$LF5O*`MOi^~(;(z*KpcTI}g=&^(F+z2j-xoVbv zt6cFalF4~&&mWWyNL!9khT-g-Ci65m?*CL;4wv(|X8w~YAd3~Jewz-??#Wt-{m}cE z>wexE2>|p%nSgZj`nz@PR7}#dkd)8yJaqdw9O|MwM5xnIcuDe@Jy>x(KiMkNOY%*N z6%lDOUEMQ+H8PN4UzrmHaigyVEG^oL{=-hXdO;67zo%mTpGJg`ssWCk9nfr#W{%}y zE394lU1fUWEg?}#X0mlJ`Bc6)fsB~hQA%qkdBH_-a2);9)5%&!e2a5Ya1a`O4jKg> z8leon76T+iF*UWU;P`}=lZ4OLhFctV`yNvsKWaSQIJm)zg}r(Q@?0I;H!M>&Mm~|? z?dtOU#lVMaugd!Ofgu?Sj!ki>PMLWMv6n8^{PyBRuPq0b86QaE7k1RgP`0kZ?pu=2 zro3wZeZ457ckVvjJZ{rFEeQkw0W`B>zJWW1ixC*?#c3)XEF**9&xud^_Vp}wL#P|y z0~K!wvS%;jd&x$je z6)X)V5*bX)eSeOknR0lUFhBiXOpsY!bZ^Y2SIZS5h=CYtU^WG$^avg_I1U{_(*5z)t>$soMLO7shl4=c{`EmWcz# zi0S6d`AL*NB$>lup9UO$%RZcCm{#;#bH_h+J3jkA!dD89&Ch4gPd3`p_EwQ}+QcB~ zvbgU3y8>yw+GrkVcq}!yTGWpl9`uQ&&(mr>d=!>;_O@_m8JC=3UpM>*$4sVynRB-W zj9`3wox|INZ^P;|KcR}K$_9koD8Fdn*Y00JxCYUSAzT&B=NG#13F!`Z90@xQ;rof$ z{%@tqq=D*ETpyW;F*e=+1dt3y2g3$b8^j_$XskXx!^2qodz?yinY2T`al-AGr*POE zg6mSW^zB6@oy$r63p*mi#*Sq(Y_OaX5*j7f&_x@mWvL-b45v|q1hK~op`4in0{26N z7|f73F`M_1^RBy3q#4)KA*ZmJ5|)FR2_d_>f-v>pdaFwEmh_@@L6l5P3Ai#bWW+iZ z{yeHQ73HQ+Pj?%G&K6cFbUb6M0N~e-Fd~KSsI>?io40xf5~P+1XF?YIfbT@n^OBPc@CZU<=>;OtU4j%+1|`;}X}J zNDkx{9ieLE94j8+*J~h)Gbj~;FST+QLO*@8YngrDd`RKv!RPs*tufmWKPUy4YpUh! z>2xi^o=qXis2)f=K;sLvkD5^4O8o_p65UIULd}I{{0Iaicp{UN@Fo|3OoYq}Ps+ZI zulUcX_`P;Fzb!_+7~5UgJd+`Nn~qx9fp!ct+wW)O^7C~({x$GBj1|vl8w*jjbBfK; z!<*&!2IN09o-~*lA}rR2X_B{Xls6jr%X-k0B}K43LIDt$4OS6@C_|BILxy~!`i)kR zI!Z|cpW{~YmU+3F;y7pfbSp;9@K%c6 znx?W!lWUGV*oyOp#u zZ7G2$inR^bVpS1~Jl6|);7pK5(|-vpob?xfuW`6yenNwhmF+_v-bdpyH1M)wdN65g zhL|{Ra2Ieh^Bl5B$)W_SvB+A^*(H{zF)^T}yb1p7Aup?_z&%q~%9OYEbl&oKy4jKH zT$@-F8>HOq_6bsg!ZyPfz}DbBJ7sck=q+1RcYQ)KbRGo7wU6*qXMy9A@yoyLEA zA)Cdxe`H#RuS~d|k-Me3A+{oPRT_;i^&{Rbwk%#~oyz4g65DC~k^F$0B3=(JI$~$Y zIgwT-9hyMD$iSo_lt~DHnd?WN2Q54Jxsd@9REsrM@#4}Pb5fmcVqJul^OEYG}ws$b^Q3E_oV@0MF z75+G~ot8D=MokVkH27D!WH#Z0eaG*FId1UzG!-k3qqdchDs*C^k4lba;AcB0sc}{_XO&k@CE2aIn#K>vJ&yoElphu1xDz5{PFiGaa6g zRdftOcWRJ?cB`|7BOZStBx5L#7GE&i86zR|17EtXP+2bA-e@y1ki9KlDZ-)-vrF7O zB*8bd2=1)HYOr+LfD3L%}nQ{wiM1_nXAasPju>KoG zjg;E8f&0<8=Ks(GqDFzgJ#G+Lwz^07c0<86Q)LAAf(lioDHsb~OzMrNhA@&3Cy^Cj zg}Tkg4`>;A_m7K_0i=FXF~$tRXd=a~IkYd@IHJgUySD$8>liH-!kI0M>Gp3;EUY4nI{1L(km+5jFAw!#0%2FzdXR@y@F7`V3Eb1ju z=5u~$bJ5J(Ib3SH?I}r%MSaZtxy;kO1+B)v$OU=bZMjaZjygz0G`{a^@AK(4+@fdu zzjQ6EC3z!7S|(p;Uo(vq5ZbKIBG#mh+EcR|^H~Z@0))o)dYIv^E<>an{flG5DoR8m zS2meuC(1wi9(+EXXaLvcyAF`^yy!jHwIyS|7NO%JikxJkIWW{6rhlOYi|R4`Ir6{0 zcB-5%y&zMI#ph!+N5bNI{Gmx}B=^SM66sLPYnKK|EpXnM%=yvTeY&b6Lx(k05(srw zk%7GD2`6v0%c7-rgJATeTCxQgc$WRXz>`-I`n&DWx+!IOYB9O9VGwPe%o7X@UA*T( zwIJC;l@XoQ*vJ5hz?1J9sjU%+rFSz=W-A?FwF6=Y%GN5AtW-4d{KwpR4cK}Xyfu4U zUl-1XYqL3f)zv#ezm3N`)#R}@?`5@cqEl6#ywA5BTkgsL^n-G&25nZbgD1!|O1dw2OqA6%7xT7M2@xknlXEf)* zCSeb+!VDqi z(&H@IvNBp4J<5Ox`DO5_SL}KE@BK+qH#_>e-%x5g z8>fveQ4EaZ4nqKIdGeDW{-lHuwvH}L8cwvN@{|(}g-c`W)aImuj#Ooo$;3_xYkQ}n zivC?Y0BAoyV1n))29OiJ-G~w^Crs30q?n~uU;@sZImqK673?Msi42jlW7N+_U~hj? zaO`xr`Z<6stAHGhs47N?E_BGxrL<~ChVrfSdzoT;zq#b3LR$7pXws*x(XjKU)A0)b z*4CkwNTLZ|AV4x`ltO6bDnzj*%GNW^U8HEJ@(Ef6Z~9tzB`W28>7ZBkTjss~lymF< za&VXMu-SEZwevh8&;Ms&>89u{qAvNz1V8d(ROPPBeBm)UgYiGUXAok)*Yi~E>n~?} z3pumxEG)Wt_V$&}W&=a#w^gST4;2wkKVs=LW}x3`d!k5j?=SF)_(I&5h1x`^Dt^?)y}7CiN#dLN~VW`ba#D4uETnkLqcZs*t^ z3j^<16P-@9#}19IL!U*%*&3#^AS+V5@9QhL!nmiIFW=nRD)V;?$vvL+9!zgP$1V06 zKel^lVb{2|CI+6l##rx2_iOVZ{;tUKYtcPwD%&lysN2vq1FDG^e%HA2Um9)k$;zgV zkefh`sS5_B%Cc>jI*^G9$ZCeixL&`xa*BU|kmQAV^8}XKC%RoJxavqkWnj(ra6Rq6 zeED0vmj)MtLHokFelwPH`2og0W`4*>u1n5lO-1DR_xpR6&OcRUVIupI$n?V~IMIN8TvS#tdNc-7||_SZTtr%YW`kU6WE@U_Ty<~vrs1)}b=jmR+`J)w#L z-?NI?T$L;&6JKHIsf?{&7I)i+*{1}-jb(4HbBE&23%+}8&B*UfA@}#t^_-8&vdvm- z-!9)JE@jWGs!JrR=Zk*mbtqjL{$Wq0i8*lrNTH$Xn=qIErYfBJ{@9iktMv2}I&265 zl=~KpcR$*k9FE5^&FC&b%^j2RMXBVTymkGps)dS;9)`b>=N5B~q}*QprVa#79sb7z zVW)u8_ngs>b1wbiNtv1u{bPxr>wo>`X=VdDCdLkV_AGdK)lEL+sf*9I|J4*5xoq#7 zd){{Zb9DANUYX$s7l27A05ZTuFa`)dVS;+#jC6D$Q))zoY2h!o;7VDJRaayTx+3J3 z4dXbGEqeIvnpQ4s)B3AP7?`l5+0G@HqQJ7e&EsKBZ|3@!c0eXKUwt8lAbQMD^~|Zw z-a066uo>oq0H8EO_SK&skbGDuniQWm-zNo^(U7~APX-*lgiuyQJ1GFPeEq)O%eZmT z@Twrtud*Rf=9dfL1ezb@D^vRK_)cjj8c1=4s48s%*Vb?}XSiA&G-?4Ip)P)JPLW6m z9UNS}64WSLAXnubi0UfknTc1|y$6c9kJ?w=9v;pU@qC%|5BBc@^4KZ;UeE(iPJsOk znjnVHcX(cyYb(})(i1os+>KH^NIw!jSDkFubw)UQ#WoM1kw^=a)DKMaU~}nRtE=Hp zL*)$oIWu@mEkMF#!@wzOV8%}nQ%1vjQi5~3gr*$}DA+hdr0c3Jg|&dxkC8S z`}m47FJYzrS~DnHbS^EfxvjAyX(^t(O6BU5il)nYgU`+I zr&pP2otx#7s4P>a>&+zMngjI^V9{0y;*if1QBC(IUs_NU7$iKXYWn{l#$C?npBZj6 zh%A@gaOcmDjt_EU)ZOg)KQvhknR_E@f|9HGg-~nW{_>x0&Q;dCH|_oW_vG(no3o8G zF2bR2LPntss#Vw@BZar|Q;-z?mVz0>Y}ItZj(O=J#2gI_J`7DJl1t8sT#M9U`>KlVj(v`4z+Z7VFvB6x*)#UtE!=Q z(wQP164|Ma#|pQ28z7o#I#Yoz(+lVyY=e=F<{#UsIacg7Y^B(v9 z#|mzLxc9x~q|d@`elne6lM6Gp<&T0v%bv|bDHTJEjG82+M4LZP)P}~>HA9N})9)t& zmFsd-4hL}Ws+%EC59{6D{x!ADf!{z0`Y5f^O(M|LV2H-MgvAI!7;epPNoPqSKH~wp zB34NZymSMdk{dZMFg;aq;%I8>%DoZ6%+<&QStJgX#tQRN1>y~>i8kA_b=8lg#C0kGfl_=;E!Z%6V-sqQ2jca)ivfe^ZqUU$dga1tjJoUcKdZ_f( zBE<#hUO5bpMx7$bfZVqQOScIf^}Uu5D5Dc76 zXE(ygeW4ktfl%piAD&opa3_qfzBzP*D2cnK#9A^#!`w;FHMHafJ-^|V>k$3`yO}>` zG{U?5)FY82_7qXv`j!*da9&>~Dx>U>PI=nF8^{7ztrM0xE}?Sw#NXATxMGs>ES~7X zvPN!mzdvCW1*24cilgZDVb9yA9TomHvAF6iuSD-4?nnbe&I|^U2CNx<#$L1L^N}5K zUn}Wcm^(pb^KnxJigfiQf07#Qvh6h!`15tAD|}t-J8daiTYDV5t%yB3h=lkqVuG*%$|;J*z&x2SK&|oO`qCv6KA?DXa$@0#B*|h1)uo7 zzCAl<5LYx*#?hF=#cu9vcsmo5{?Xvrdj!PY!99FZ>$D!`oJ)=VogKMjTC_ zh5|RhI<<;GEXp=?_-(||chulaUm?Z}$v}wg8c(JeEW?u(bs$3|EDT1hv7ueiZy;#v zDI@Js6De4KKx8nI!;cb$TP zC9M*K!3UwzNTf!E9=md@YHhr>W!*5TKW6SL9_*)H|J?WBRy>zvFXp)xl(Y?E*Eqfe zJv|%G;qI9OYzmqB{TAQU<`{^;^?p+QHbWO61RY%Tbny%TDOXw7pd~I5R>OLCK7oVI z)AnY&w^2=EiKH_D(98BMd}djItZxw_Pk6MLuB>oO`zilD3n^~@uq+o?+OVSkPb$;` zy+l8=aB)x_b%1T-(6yvss7;u8M^iONB1J>l zv-)XV!7uzEEY6EHDflI#7xOOiNmtNX`*~xB?L6<_wS%+JUcDd=5jCgb4ZO>Lw35mF zKbEe7Ey};?($ehGDYbNWE6pw?ouYJi2`B`CdmH`wxfI;s-71rd6pP!J?miTi7;Fn|rKFO_6|Kr}O@o`2gdT_wI{hIR;!nk0rg)@6%YrG0QH z^-LmYo?PeQ-tGBzL!+;v7Q8G4$CBoZk|7IU?3+bm4>S1Y80EDY%U{$&N0U21cE>9A z{q_c}|5x)kufkH7~to0HKpB$P<rXTX|sF$-EfbOml6W`$CN?GzfSG+Umb*01O}@>SmKi9Qh>I-+Id>Ifn!mpt3P zNsys0DD>3T575d33Gsn|PO92(;ewP9)QpXT(dyMiIW-t`MS9gNFrXzlRz|;?&aYtE zXLY&hE1MFPjLv9i601fCQlNAnVO|Jv9tP6zT>7Y&=X_eQ0h)}!V?>$0kr43^|D$^l z{}BBUmECGBnA8*Rtrx-GojM((IrXlDG>^Ko9Qpt+cPpXi26Fr_DI9zVXT}z+#V47r z#dxZobWJNunE8O6`&_vA{knzZ;mhsUn{B$&TEQ80s*)s3T$LPydLpTxbG4TAQiRP- zOX|0DZhmzdo+V(nfE5A(o27n^g4Fl;u07+vh}D6ZiqNbOuEc(9RvIC06n9y6#%a-7 zR(S$|aVdPLb8VV{P>Tk?lVeK4SpwC7pUEcdK=>6sfEuFLw^A=5EcXQD{AT@{0Ojsc z9U^8nQfBP612T4JegF;LhPh4!yD>kV9Ji%L+9uHl=UU(@V@Ws3(h;88MbnuE{WUfH zA;~HMM7oi_i?K}~-hLcxGf`t9#$}QCV@%4IF~q-H=US#3`OID4XVy}2)I_p>rmqqo zCP%_xUGk29g^-YfVE5+ZT)1~r&}n=4vHJ4Y>r7`v);$3B%i@cf^RhYAYQEB+h&~9$Al-$`HC%*mbf>6J(}AL;d<}`Msg(2N9|*R2$06Cc`h>{*JbvG5 z_0_;BH;Va_${+M$9U>|NwC&tcCYMenPZr|%Z!i2nE!`;@6`>A5m8JCuA4vSPaYfm9 z+ePPm0WR{#d;6p(eCuz<>Q>A`s8l}@+sM`BXEuMN_Y;#DvcG*x@2(SM=&!D3hfm30 z)H})gSG)!nB~G#&kC76P)nwRu(($#ct&a25)+sm49v6Ug`>)P=Sr~=&MQ58udKuRTbWNlC8!$^d#*Pl* zdLDcM<)h&+2|{_YT+XL>Y)7;J0o&bi?}aM6 zofqwA?9LaT@vg3}`=j&6mG%^?k9Gj$lx(U4q8MC!Z>@eYwmg42aR0IMCTe<2!=YK! zwP-Gf7NHd?8z#(ZHB34Vm%_7Z?5~VToOD-fY)WPk1@nhg4X-yR)P7S+h;3))WGGC_ zBqbO0HyJ%Gy+Ixzng}QTd_OCO-Z||hWVG(>LIkP=r@-}TBNdpR)Sq5vT%MbIfrl^r zX3Gk&6X5AKdTs$HQgMh}^$sK8Vsx{Au47Y6c9J4c=SLX>3PyIW9cT@qHs-Cf%zH2T z#6@lfHpJAR{Jy}jgN)cQf!-GTL3;1;~sE`~rJ4ZBS`h)oU>fZJ|ir z+kzT|0V(gbmbH1#%<|c3Y%nM99h2gHu0~mmUUD@@xkbi)@v3o)cvbrBrOSTrHP1(7 zg+rUGEkznnv?EmEmnoBpD!OIPrI=ea&4m%i{oDbTR8%3oALq;zWX4LI&|xOxGdNiR zezmbwkkCe>@GUzF4(O!Sz&XM{Pu|`RSF0a-{mjajU+I>%R3ql<{njf?GAtZjf%sql zOs#D@@^e9F|3R{5U$9ipoNW=v5DSzF%ui*0-~(Pc05H=1RsyH8M-s9PRejA2%1AP;Us6XV zk4$VdSnz)*%uVJ+aY8gipf!(7-p3pGwJyWqcYPDXxlNdJlo5yjkAgQ!?_XYEJ=s~^ zUCZ6q5A3zeGZ3N>T;mZefG(}9-ar=^pTI$-7cdf^mQVIZ!Kg&RE~ujGT(r1cdqe7T zwqODCMO$361U8DOAMe$J<|}$&Y~dZusEyM`lDCl)_U`da&81^Dm-qqz#d%_+o^Pp#_qb`diWPdI3%BtBZK6D`(|B6Hm6>AGhS0t& zn}b^}R{hINpwpPyo zkc1g(@}cBZeP`ik+^mMFiBlXxm)@eE6e6lF=H0&aF(r9bXj5qN!%hs6S)so3E*b zUpmDNwNWx)GfdSFjg2*UMbAH9Ao<$sSV*3N`Ssw=s7jTZ{Bo&@wSeiTiwli>g2o#y zRaD1*WE9l?P|i&Z6jGT`okUq9Aah7Z*OTV?b7xDicX=gm3?n{uTwrfPF+`%i+5(k7 z;}E?N{W-8Hx--075}i^qj8R?DO1^Q(1jP+=iuwsWt}gvRNT(568Yt3jPi&!bB2S<; z(^yLVnNC-Aq;S!fDSP-&wWSU}9vrFj48*S+c}tb+RwrSY*F-jJZ&iiZHik;oQpI8A zA+oBA`{r<|tg=3iendJ5h=yD&4{zJ&AdjFy!kLl0#kF+OP}xlyIUOnJ&;(+;6Icjh zDq9eePx$9r{{Bl<^DBCO!vV28VH;&GlK7zisE(VzKa>b~U9#mMh$&9Gv}6^7`usku zT{n*#)fexd&EEa>OjgU)J}G#>wn75TcNeQt>A)?dus4Vauz$F#4PPDa8cwotv!e-> zHwA}C>CjVupZ?QLuoxvyU9rbwImXvEq)$wOEK7AA5b{Pd490{@M>aN$&*0np&q-QK zfCPlDjh)DLzo(hD|FQl=;p#!2%8D*5gh39YH?^NW2XadvHd;_y&Cnj`S*ge2i*&Vo z{}gz65i941fb>)sqv zs$?%f|1Bk` z)Z*f9Fg?PD?wGxz2j=wR@$2>2SK^xCFRbU{9P*0Dt<75N6b|CV(!76J{eCvg@HoNK z-uuDO79Y#f?lSK5VV-_0Ra&-fj(FkI;` z7q0al)Bem!nmszHDjosme%q&xk?KjT>~>LR-KaO=Se$PS6G}(At%Y>q+A2kfz`Eaa z+~#Zd#y3Vw0}aSRLH_kMe*MV2gA%B^n}24?Tgs&a*yw_k`zA~KJ}0!-{Ne5|M8fmD zMMH`q*iQJJUNwI{(D;aQqZPU*RxWwGV z^20BivLfd-dFP47N&O&cs)z~>;b{yF5>a_-l{)->9`l7nf7Hj0@ghxK5I9a+JRxbG zK?Ok(84QOGMfZ&>1e^m*X<5SBIBoad$brMc}92JJd#4p3m>`RaYn@}|g$I2}R zl}7fNWT=mFzy7#OUm$q&^~cFm)4t{&Dh4gXNYAm+vWHKzqKz%OAI75d&`C81Z5I{l z^70YKpcDs9?_7=gk`qu`4soNh#@VG)%oj_`?aAV0U(1%WVa;6+^vbZsE9(D@!mix;n$(WxFu zslZE^_en<|W8#_$%2tH-H7>U_k*F=tW;t0t>t*L?<$1g` z#Kz949=go~?XHe{l1dLDu=SPY>ZcaFS1-s!XgLw)e;%pqOFA221<`zPym2GflNaPV z(3K4q++G=od-GK@8Cg=l#BnGwEKz)+F9$ixp9@*Hib%zAKujn~}10=fr_wG4LdL1tp7c%9P#+{^QxU^)TLGp=Mc`1;iv;47tgsLS4naIna zwCAB^btI0r8;5mn6jd3#oSlp<+OR14D*37f%9?;kKT#v9Dt1^cpI`=hj+N{Mt0f1H zsJ~%ONJCNK!W_!?sKrbuUE!DQVGydE6|oGnb4bZ~t6L!IpMi-JWorz?_a^0Fi)`0L zvivopb@mHC5ch+r_@R7NwJ0~1Wj@Tdv z9=F>*+Fhk)i14TTMt{FS^~ygdo9(nwLKTmvdQ(%iXR|N$YBxz4Gqt@n5KJ#9VH2 z$=rwB-R*}Aypg2Az0ao?=!Rz;D7hK|B6C;X__OWLIJaAbXALNKh3>sc;x^6e( zoc{M=Md|tZ>T0UTv9vE@wqA}z@**LVcqEffux3Pxd~w@! zYNhY=Vtsbddtj)Uns|a{*ns(uwSPi9#cn?a5c4zR48v7fcBs#7LV~BgGJpOhxWDH5 zIDX8=Nip}{N~>=RoI*t)>cWmn&MwUl!Y%$dv{l&4F6h3CxIfvV5k-|R>Rw{L1u_ACelk3y~E4;T$nMRF6G=#~!|%JlQsGQb%*`v$N1BlZ}rUP2eDmr<}_ z?a_jMQe`*O7`cK{n_$_Wy?)Aoye68z5+uBwK&h7`exy7=blHeNF|7&}T42*3TYHyr zfIYifUu}{*IHy}~{7FZADltzhFkC}49a9AwQ8D`4q{H%YVzn$ZygZIK6agMxlW4Dq zu)Vkb4UUAA%D~`f_w2$IO*1$`Q@+*-lOpH1=gNEpNyqty4l8wXKSiT3d(W@Li>7iZK+jD zkoPB!>g9}1zMRWuS+#mWXpbD5@sQzb$P$yJH*^X8k*LJkqcv2Ej}uWC${;6l zPCNd{U1rY3L12}T(!ODi@sMkZwq+06iXGy@?2R&Y*`gn`Eq2YRUJ+Vd_jWJu?|wZc z$8*l=48bv2{+SKr%FK~ys3C|`^=dB8ogo?N4#MoviK50E<}!5}tX+Fcs~z>X)nW`FNRAN}=RF;cfkgodETMe3XgGcDXe+ic zf!Ua&2#fEqP;&=D(Wy;SYWZ=Hu_L&ASn$YV>Ql^_aDDRrl&D9H_!VV{(-OLp1?Ywn zLHKQm{{^M^6!O(AEjcmrw`r#7ONnMLQDm0M$d1OiA?xs|$0J#OR+!wQr{$OtiW3j! z1`TG@V?<*I&_d~aS>e%o2g0cE-(ZDAWzf^SSeT#hyY;m$+1P}0ds8vk2uIflbo z!+V`nFcUJt3~D2|~UB}>;P9!orIOziM|r@PZDUBuw z95jB(kQ@$Tc-fzZ4th*N6hZOZia<)XsD_WV6fDyB^QV2d3-68W&jruRg$@56&loP` zqNCj5XI~O&H@SRa5svt>P2fWtJXsX?6w`VKya(Iu7R_GrKpZgMGs>b_U2B^2iHPna z**U>q&AywhQI2|EYfE*nYYatYlompe43UQ`hf;IX+)FQB&Vw9M7E`DK*x%t){=Ge~ zE{8HsWqkV8f&8M)=Rs`NRJ=wpwil%3U;MY1OY;{z;bD}`;$GwrM-;>WoLBVR!(=LG zUn^HGQ|arB{SUc)Dxuc^*FP;hPp^@hfm1?#WwOd|Lu02$1Q+$GN7&vd8r1+x6XcP4 z1hK4_IoL~Q$-}_BCO;ejq2JI@yRi37fzCUmNx#0Z6KW=f1(x=mcO(l@3ZILe74o4Ug_BlQ8|$RIY2_)o1;=J2&IqUXt8GB|DC({>GSDaTfIF9 z49ccPWM?zp2PBe<4=c^b)$K+MoG9x^J;MYHf)5Wr3+8{PrZ0@rqw#vpJuun#zh7QA zG@u0Ke>-3nqr_H_emduTjz03jr%`%7nqF)+skxu+`SIUwR_l-4q+$UIvJFPHY=W^& z8qG`+7WIWo==C=nz({wany?fzEDwZO*2 zTX|3r><^;JA%ur(5oK6C@(`+IEk6x!^oTzdRsh@>(}VbSS&m!T6FIm$zldn^ynykco{2Xb7ixeFp_x0?>fyuRrd>7dY_cwR}Ud zi5+3>MoO~2Wx08WO?+~bml*_SVSH{!N3AAQ*ff0|KOhaaB2t$ylE0c+Lm=9PIhP&< zz{$xig9I#*;9pLE98GZpFG|A^srbUHmpI3gE?=_?)*!|8BZuwe)2u@YSla|g7V}!b z&x6FZi^SbhzyW7g<HhS>LV5EmlWO<+qgOq{TwwK-bX~@i9=HjZD*hl5f8%q5c{hU zbc9yO^_=VTPM?Oc%z(hmQA*+aEF%hM5E?(O>OZW*456mqLWr+n2cuad^Zr{Re@g?i z=fbLHo3i{;+UT%b7Dv|c#iK5PeT6$~wEtJF{-YA~>e4>NkzAi=(9c+gUMeYF5;;VsBgRbrWm}Z)wM0l`kZ*8 z<5m)`Ey!zMIt_`1D-&S4n-Qu)1Pv|P`~~ZZqqIz3(oW`C!5=5D)1-$!nsdj7J*4fE z%!Ny0J7|Aa+6QCBFv}G6`Kj6PuFJjXb@9+2P^dL7Q3b#{>g>T;TFyg_0YrkhZQ&ZN z?~lAXwHZU*swMC(yWm*0eY8G0U^&z)_p4AD{%MQ;&Dq?4B>kx`&_DtvQ{gaQnZ$9T&N{6ZKT7gXZ=%K9{oEhsHNct_))oc!_7)`s+=3tF)446 zWb65Umg(W(5&(c(!QR5eCK2BY@=?$X23>os^s5KnT(%C`=Ul{ObU|Af+>h96v-Na0FA0wkJLk_ z1S;Ww;s>yze5svW9!)FKuZYc$eM|r`bEOU9J6JjoMkuR*f@iqHp?mapwmN z?gu)l6ZNh1iQg`?3EMfHw@pyqdJd|&STIdy8O_=%%Kr0|Of!Zosr47+>_lpdl5B8x zRk#eLiQOsB(A?Zwh@MdnhgR+05Us}Z38uc2logl~jv)a*yxbb!+??B;N_WjPf*GB~ zPkM3ED3R}U$LY9kXRE2HrDH8!>*gR2Wq)XA8+amdzTWY8r zb(T1Nqt)jRLf*5_7t7*N z`SDHdM93itgK_zWsjQKN?9>4yuGGp{JNAjXgDABJ1 zYDd|Q%%j+vsrRL!$WRK2=6#ZQg5Dm5dg27;4ZBzLz?P}HkN@L{2(w=oIZsxkd;1if zb=JwZ8a)rdArn`zp@PHmicjPzi|u2%X8OW1R;F@AU4Lr7?mWEtsAS_m z>Y2sX$FPSh#*~%TZs0~jDe6a(bWO4Plq2ZP?`DU?=nh53xeZN%)&lnq!l>yFPbMFv z)-oq|-%*t1kGEGkq5t@#eG?(vm&-@|&QrYi4cZ`(rf=f+%i;6O=tx>*zNN1$HVxI5 zuPkq5IG{!;ynNte|C&qMr8pQlw8$YlO71_GsUtYto&)c(6emgMD#wn1$Svgg@L%l> zvk4ezdaZ|gbq5JE8k;mRVotjeROXBmf-?M40me_5WOGjFpna&PlP#&)O6RS)%|V8mkp}Bo3x48~N1{sHic4 z{+9i4OM#6j`*Ea1P=1l^C8(`h_UgzrZsGsJ4k)1u>+)TUajRa#t{lzTNvYe``mZE8 zU>}A06rz=!a#n+zQ=Ft*Ed!AM@Cjd3qXkuuI5&~?BHw2=Ks&H>dRa0xYtM+}bBNsG zQ~It}523g;!Nb^DY4X<-5Nugi-YTl!ufP<1#%ci$t23NP^M*qc~J0G+ekCd0io;48|xWjq_iOoJ=F< z(9ZX2Gb^y;tyz0#E%E(FB|JM7l!#x$?gkFfe+$c3PLfo0f1h9~o&jSSRpm_1Pa{We zC49AGm4TO+H-nPh$0{8I0K#<#Ri?ty)2Ee|lxW);Plu!ol+Y_< zH0BiC843OFyZ8--Q1P28&v+=1_C2QzAlM6q&?T>4FJl!Tx^@v_j1sF78ER2h#3)Hr zfkhM?>f&@NSrmBPxpK8sKkxH!Y1?f5CgvL#VG{jvnPMfqmD{hE=7P%Nk=6^0^o@tF zFVEpCFI{U-x6bDkk+^8^Dh1T&*jVBrITP#&)Hne$Z>asmBS!Gtehwdg$q9pGfI^Jl zuyV-aDj7QoR#{n_GGWdheF;IM`fn_>50m#VdexuaI%nb*^T%c-j@?!X01I`WD@{Dr z5n%qLmy#}j+tAM)Hp#;yvYA9ci&l}iluc&?>sU6zB&~m$$C7Wgwg6kXjRT~x-3Vbr zPngU(?5O4CtjNmF3Ge|?X_^{289rK&LMxvf8Qw=4qykd0OYQq?DAiXL7SMfJc!F@V zsov*b%UVts(vaq#&~7Ey%M(}=UlnY(bME?i8%a?#?~`c)&^R-^Ugc+6x=V_nm0Jq< z_YSk^P>YF!zxQaQNecV*vKX6aV&k;Ysf5qX%kBEvoM`P}2sI)AK81KtzrKR~4wZv- zPhOfYD%BREut~(W=d(A(JV?cdFbUPmqqH4`Y&1*okdVFKW*l9jz(ec8UN+Bhx$#X>o9>0xD}6i5V02 z=pxT4z$^x-)xcSRsEZ}|*iuAC8HB4$%38(&7t+pjppRj*WjQ>S;_>q)HB}oVKqpGi zL&qycIDkW67v6-H>!3P(T97KHmwefLkbNaU+cjAHfs9(oI{47u=kJpnUff*EQdf&Q zn|nwc*q0^4aJ-e6=m~Kc+LV6HE=5z)+eDCfe+wp%J>P#~6$BT3_Z_HQZCU@S(b1t_xa z(r1T)iX#~t3N8-*6%<7i)Fq#!yCcS`oSv9>XZ~Eh>n^QPu+K*bD{4JIcH@YyDPgZKdb`uh*Gpw?YixX^3#ykp2s1UHgKu}^6(oegRXS4cd-B-@lyuUMkeIjr>!1n(?3 zkQe8?%*Ad00~`8A#~4MWl%;}qfs(M7K+KLYqu%QEStV{Z1?!^ zaEq5R%w-9ey&LArVIDk+{w1A#_tIyTD3>hnRELml>vQ({TZB}$&W-culD_XIB2WA0 z2lo1P$7Xi<w^l{h2_e4#DCN*Y=7GF7DkUu^rC0LDi=wCymZq8n*_<61Mw+37pGtbaIIVVZrOeI@tm2D$BRmfUc|t zx6|jx=45@_1>R*HBaGIva7z`#V)0(K8JwDHng@<%)&PDo_@U6?Hw$*qY^~yptEXd= z&{``1Q$n0o_S|Ro&+is zEBNwMe;!P5NX3-c2|`adud^;azS!_Lo>IlDQ3IMQ-H$n8% zwZ_$o{i-$%+>SrxUab{kikI8dJj_q~cBKD>-dY-hMAl?4f3rnU9DCB|KGhG=K55Eum4;<^drM{P_&F zgDw#sw4y+N(;`{YFhm;7S=-C;enKn2>oi%I6|CVNjen^WK(q z7}1VR{%6;hX;=PIgA7{3rm{!YzQqGt+CF!orW~|vUr6>$45wB4uuPgKM}UUkb_uOw zp*V{{%38eRJs@jib*0#H1-zoDQ%aK(gpg~4V~y_n3y>p%O|!o%t12^O&8^7-kIM*+ zqhdhhHcM1vVyS-3Jus1z{w3I4ehkXN^T!+Z6ZQqv?n%I;!+gr${S%2=>`vO^YTQH1 zMlA?s)}PcNS-a65Yv_JcijmA$n8p-ECa6_qFN3FpNfzF=Svl`+6fVhQQ{TUquj|t1 z$MKM4yK=kwDS4nP;YXOgAm+RDF_{1DHay*_zHxuwG-fMq90uJ(NigBIH4&M?uQoiy z1D2>k1nq%k1R!K6jD0ga$Xd5=(^+b0Nq$NKd$!03 z#H)WB8WYevC5B6<7l?&x+Ebs18P+uY;r9FWnW;jBn_wK%A8hq7o0^ebW@^4o`1q;L zu&JyM!n+u7kVPV90Cq?;S<>I84TJkf#X81^R4V6wI5LrdcRyly)4H(ZI^ubu5lirB z2m~b3boQE7uRjhZ`yLB?Z8v%z@nH5`DJA=8W~MUyobi3YMU9sW!4H(di@)~^V#f&K zAhW$iI!596HUVz=VbFc!<@ExT~nkIM-?oi zz%B^kS_U!lLFuG%fGDnRu9ScADY(^Icn(@+towtqzqi+vb_#mI(3~ z8R^K>#&S~g<2L1bs3eTNOB9+>VP&S4Rri`+cspd?5-ZmEQ~gPMt}Y?j-HLU&%OXNv{zL;Npi+l|LJVrVAhS#x07kaqZVskn&)e(GU=vae;d<21BXRr)s`V_J@xntT9VPCAu;IEMe2$dH0X73y%7z-Od6SA zZp|i$CTgsvd6L{7SKmtp6vu>XhRhYUc@?ar{Ku+?gLGI%rjx>lP2iT-d{!BXedaOZ zqo=#dRzKcAWMQWjK3&h3T~(_mBgsjP{L5CnlD)y=GUx+0B=GLC5MA|Rmz(N{zp-QH zA9(gm+{!96ArI@ue1KxN))^u@0>cw3S}k%C757ptUP(FRYIgPaiQxv3?n2zXIm+l|6|1yRlL#3Mi+gOIBWDS-CVLS zmzQ9qXDnlC0>v+(DUYD3YAYAM{Jpc;@%hF;AY!>F60ufU@0RE?I`WvT_vi8}+Gw*> zD?Vo)4Nn?AZ}nTMBSn4hX`++f3iIpQ@V4)Jv*~WeHlH5#Ee&2?S~oI_v}hMh;Zy-a zEZtVv)nU|SK=PYmvEWooo?mg46X5m)Av^Oe*~>|T?VbPDF>;X>@*s->9* zMAL4m4P$3A>t=}S+Fj;Ei5~gfk>%NF2vb&glUb6|a>VXr_tl zNtzM&l?lhiA+;&UMk?toCLiPNA?=ktev$WboR$Y_KJ}wzk8Sb+RRdz1oh1Brm-Ih1m762<02ifN`p0dhDpT z40z54H)3(9fakkva*NczPZ|%ngIph%#MpI%(f=vI8@@ zzk%a&iS(W}ZVq40*N;kkVEtHVcKInBl0Zz8xLJY88|~0(H%@KL*p7HHHA>Wg*qC<0 zg1dcu2}?o>HIMHfQ~}ld`2f8FGHz7V#<>t70w?PWNq~OVZd*-3Y&4B@eGN+%dgyD| z!KhhJ3Ru`VSly(+29Z%zkK2{s9~aGY|J8Kfd?4YH&CDav*8wRCDm=Bkq|M>L&2K!9 z4=0C%Ea8xln*H!o5HMv>Qut(4QLPiof*gM(Vd{hsl1^Yt2k;Cfr03~$BI?}q%7bE& z%02r#;M7W_^CP8k7OKkdJp6gsR0<>8uOH3o*zhn!jRrMtI;qLAsU(2}0AgOSEUsZc z>qw#2vpT@$d z4p_-|+PcWR5DSRhYh}ly+aKuoy1cKOx)8`T5KRcI6xevov^YHSX_ZQTFZ)2CaDG=5 zvdG)9fkN}o;(2WPmBjAsTLluZUPutF$rJ$ zP1PucTK_}rjjM~Z&5e0`@sJf_Bpb&9O#2U3xsP3#uz)m_JRgo>%R(mTGVjo1ZjFN!H{}C3Q3EYL&Py9ZIjz+M1DvD#M!n1> z36CvkTrUM;-hA;(ug<;c+sDkVe{`v}V{~pr6g0*CdyYjP>ceW@qgP>F{nu{X!6r@} zuU-B&QyFZT3Y#l;C{J5lE}b!Q2D?Eh2{3KGeplB79GKL!MsRrktmLk5yYT|k7I|KM zYz{G?v&&E6G7YeSqZlB>#Snmd;ptX-A92BHOrwc1`{g5(T|jMh{35HM07wFDa7}=E z+P2f#r#Ro3O_fJRgWHXy?UQb$>-e~PSSoWRGE%PlP^?alDjqFqEZer>ofJb5^&4dj zS!}%Q=8rdGy}!BTyZ@06LL1B4EJ_Yv)+dHSy=}oU3bHhuIX}yFdC588t|SosW)l-x zMH7QQJ2ti%_87{22x~R9>60l)#1CaIQ1lx7B5N{UQ#c9(2_<2ZTSb9=M4;Wq7tUjp=a%0OU$33Gz&n0 z;=0l&WTCNA0u|F=o*OpS#)iG@>SGH>0OC|UOPo3obm$THC~gdxlg-osTiANarOEXNG&JYYQ4EC2q2v`mrbFvtV0kIZ7z=kqKHWO~UcKT)}RCPDYczvf9GIm!hLW ztTxfe7NLgSM4-k}xFPH0G;(TEZ?;AUt#V8~cxVZB9;GHMTMs5W%#1L4*;%B4b;@k_ zOEd~qu22Oh)BkK>`zbi3!rf5Cwe=CaYwh( z#CpJSJe&}}e(hA(1$)K6d|tUrc0Rq17wfZ)`(t+nkX?SHDIBJ!I5Yq&G=y;TU2n84vtd~_3Vy4_mg6cGu*V#UBV)DJ zY=+sN;p3op{mjqE&vLFq%P1_l{6Df3w&FINRRJwiMiLgG>BMA&DC)6h#}QtyN)4Q|deoX1ho)X5J+&P9JKU(s{#3pg2oh250ZL&obW z9<}_rg54dRx!Pa64^}H%j-BW%Bc17;gmL z2IAp{(FW?-a|6yt3c%xpQP_pdCpEpB(|2RU!AGR)RS)9_LK|xwO6M-+C(}#L)^=K1 z@*G}Id#9s5TXK(CPj^kcr*o344Nz4QPgSG+|5Ia^bE{sC{PCq zulR^)Y5g)9B>6t=K%;!sJb53r(J*vD8mHWbbh3ueUtiI44hM)-|Bq`XD0)SYcUixJ zt{FMxVxJD9#m1ujj*ofmTAlHQOwUG!U5xEC_9-*Z zpVpU}BKIs26oPc8z{Ke3k<6^35~g%&JvBGi@Q@Mhccg&cZ13KBpiZfx-qvbD&Wr5d z*-WMAlAlW9Im7-XDO+i6_2H}j$0#91W$|$!J-b=0cjNE8Ss4D3Z@e2FiwRk$7CM@q z_GiI3Gnv!Z^GUt?H*M(=yEl=O)$)aGg@%sv0-l#^lO7S~JziiLW?O@? zz0oz|jxY)`JG7N5#Aq1sGIOzbW%>($y9kZIi9<*Sa{KCHzuH z+OU4ew&23tB*638fkL^A&gCm_+q5>C*=gO63D{WZzcpaR>(|LD9iFe94u|Tq)zZhnML0C;NFXEPH<`sSQy`&6?Q`C^7N{2Si?F#n z#f!L9iv-Ciy{WkgbD?+;+p*H@K;ojFr@a5>nu^P{6vZ1#A?Y5ID6)98->{>B!|Z4* zKF#GP6;0pm+Zv7W6M{Af;sz2UuunVwofa>^|;|F0vFbID)umsa<5mFwn8j81g zc!<(09LbA=>#XV2P>~di*UwHvONwM}zW(|XVCWIEgB|YL89iiNhy{^k#c8%$QT2hsek?Y>#i`!4UM$;2GuPnfjMHV<&=$$* zXLULBv)g(=6ZBoQ*30SX@<^n84Ndq}S{O6y%-Nj#D5Gy9(qj>3O&EVUH+du@Ge+Pf z%>6PqoZG~%2=aV@&!ab|FF-YT0-*3ux1fqrU~nKw^JqU(GS|Q)ws2U2n4e}s z*~75OIc~O<$sAh2^n;6{%OaOJ|`ZGQ=k&eu1iCPCsRn*kZ3S zo4l5>G=j{&hh1nvBS=34*-J|oVZ}844?VsBF3MM~IT!8iYx&-D*rV#7n}D)|Xt+}a zI)0)fhLcG^)Ey-V)>(rEL&fn_K?%zvS;jvXmY+{gOG-Y2q~SEObN$7+LVO2CB_$j% z3gdfKRXsG=jDCN*wd=@n-&G7_q8wC>w+6P$N(O9?5B_DM)zYXm{!U4rB*wVS$P_iz zL_oC*WUtOyY3!HN+%x?aQ3hPy!mI78KVtH9-Aa8RDjiM4Q5nlB@t6a9xafgM)m9V83 z|0>*pz_gp@>Vc-bpM)}Im8Yn+M_fRhTf5#Uf!&Fj}U$7%c2*-j-^?{zQOzEjXxX^Ra4JX!SCUs0`-I zd^L8lt=xAqILIUc8VyxoH9J3TYYox|S>cL9l>lxUOX^96;(Q^#uBCDa+0urIBi#0YnAuU&O(|6uz6J&H`@Auim4n`MiU*QU z{F6>D4gb7L=?s(0|;^Xku^y>T{<$Cb9% z+MkA3iY@N-bOKSS7~nSHQ842^s8waxYo_jj8%Vu(*oLwdn<@QxUHpvUK>m)6-f=O5 zg;{3rWP5**snz16l_1W*#Qb4yb#OrV_ptKq!Yu!Kb%;&18E#ltEicRs%rX-&B$a`5 z>bFlVryO$S{U1wL!4_rzbmF$*7?(XiA1_1#{>6VZb>68|U zeV6C|?kCvmzUDV`X6DQ}`H!X|`76INyZ7toXGJuooN6mnUK5@u%9Jo@u~vSOfSlg? z9M?E?p8k8R@X*n$5{06|K*R2ciHpD^qTs=_XG zwMEw{d8k*C;fhPNw?1KcRA;M#q*B6!#~wi$yiU3yDeeWeVz`ETbrWu)7eZ2tn-hVELpH{*zhnDQXtih1c?5okj!N(A|uy_F(L`N!lpR9HCDud&H#8+Yx{XKXlKx zCfRsE0d1*Dofs@*8F5?6c1w3g#jF2RrtSlioQ~mk>{DZa>Oc2z2CT7ce)xU`_M4H~ zFZrqBOz+)`Ulmt}v-i%!{%vp03-0HxSqj1?C&nsm;W=6X0yNr21DL5)^A>l$5d))m z7-cxC3m#}lqRM~%9ziJLEH3+tKS51Dk06yYM_tWj=pj!k^i!7iB0qy-DtlHXf0yPJ z6#O_QHDR8txluXOrqlOZYRmchOa0zKcU@UK%#BYhndTmb_r#HvB;Il-H4X z(NdL&MG$<%t{Z~Jiyax?qiI!{h1Fb##xc7!Z1{8h_9MWk<`VC{ESm+lm!YgZ@ChH&urpEoNbcGw9o&gdPpGkj!Phr`UCH^s<^TC=9* z`N33_#B5BKubkiCn7W|;`}@YLh8&rUhc_};Esq@q6l=aY@jUXaNKkaxKccCp_3;ci zy&OU3;8z%iZt0mUiUt%}N|OmEXXGQhS-hUMwo{~#yw%JYN+b@KvZxydns(djK^<~Z zmV)L!bm`PshDwHL?V9pCqp097+?~oY%HdG{(Qccg7IT5ueWbl2mk*eGgqdaja}=4= zf~mShi!sUHI^*42#L4QX@BCYz;4Q`T-JQewpkQa)oRm9>6m4L7pA1qwsGsj&7*h7P zK-S`)MoO3n!aBZd*=)!dpjRm0hiqQ6ia8O6ruwlWFGdGNE{_!;^4B|wZygL-z6}P((zXKTS9<)sZ%Ex^ z)u0?aW@B5*A9}ScD#>YYHzhpz-vQobv>$&z)JjV?49LqNr#O2XcnoOG&*MH;xwr87 z2OA#q_Z)zEvU9G~ITuO;@epLGrHXbXi;>$kgdr&Y_6H@k#qvK^t;g6K2ZLzwA`|3y zSken{t=9U%T9%7|GkWDPb||9jOZ32duEBwqj@^cl?Pbr!(ui7%%PB0J&=gh@D!};q zXl)5LC|s1Z>~fj1V;+oa=Z@d}y;j}Xrht|*I7aq;hhLPiQIVmWu)x_vY(0CuMd zd)k<2vu}+9$O0n2?S_1lnA5BjGebh!Yb?iUrPPvH6-cX7#)~KvW)fUJdGoHciZ0cg z#nV(3s<;ZdRI*)5p~$wAcX^!GE^vaQYX#ocQJpt zX}08~()pKQyCI?POMA>UFVS-sh(~((f|?caD_(~5j9-+U8yu%XdY>MB_@CN%xg2wY z!atl|{^Is*T7B$Vj?giSYYBt|6aRDIhT4c36)`F@@+TEFhEaOw;awnc5vtbjco zC00loxdxKfm6z{Keio~|Z{wfI;F!PcDuzeZ_OAXG{;Hm?0;;^S9y+`@+Ey48nAm*c zDM9qtl>kz!!lYT$P)^-?U*ao?rnS=^hjq1qQ5!Vs==o@{f#Qm&SR>fpF(fyMzpj2hK+x#Ed~vBC7BiYt@uEfw3C4Cf%9~IL<5yS`oK)OaF$vohOz~2zX!jteJ_g6 zt27ps)~Q7D+a4nD?sReM;Er9bpB#l%lyFBEy3z@}41udj4xE|V$TRAuSxKjs%p>|3 zX!1k`(*-<$FVO>6dRZrUk*UC9XMI81JdYwtN`AY7mB=&^4D)8}?@bgZFN*H-v#MJp zOhw-?=`gUJ!DL_)Ctcxw_N^_Ubcm{4#g%LHGW{_lIEVos#E#9Ub=kfb$Cm5KnY=qm z6bvQDHCD*8Z6r>rB=*6N8tMQZtlpv>CdOI>?Q1d(=bF}D<&@C&gT3jFhl<~hWqr1= zkb#-MQCzprQhBxQf4Q4&7Xg}*yfhT?=?FRQY`qxK4eAJr56udG>j}&- zWXG2gGrU9(oXzU{qU`HfOv3|Dz;P#HG@RAF3f6c$XEGYh#G)V7^ZmvjHjezwBJOi1 zT7<#M``DjDg~N6sxMmS-@hikFtN(fx{f2N#e^$euA6L??IjjPuq+|)nac#UJ<&y^j zjYcU8j|@ZY4tt_ovQ>dnku>arTk%nB9r%|o2rnJ5SXDRHix?nEOJizD#6D%iPS*M;F9h6 z)2HYT44eFG&9(K%%m{l1YkDZkwDF<9C1cJQUJ7Hfyw3ds=oB08IRq3-3BgrC{p%^-ANrPLS1@wCTZ(>R_x zKD+M@K3&-pg5(6K#VlCI#8S*#%&-;=d8{fHyt9;a2c;W60T9^N-VK~IB0PNhTX_8+ z?l}p>Q;Yd8dZ>$D+6^A(VfSP^*AK4N?>fTBY?Q2@KcDiUn>mWhsj0?~U2uMJB{sGI zO~}fxBZBx_b^y{S+20f_|0wl8+^;Vt^w#!>&CYUw&;Uas)$B*>Qn2UA+G-z<*hC1s zQXqd6S~8G{8p*3(a0w0j)vc94%xF{tOAGNjD@I~4qltB?{VK0(L356?n?+PPiB>u> zL+ZffNsgVS%lBzMu@>6Md2aR&Hr`zPfo1qYfB2Th!Cd|St=`2F$9rlO(5vtBgSgE zlCTq^R5_K*S5~Fa)uqvUKttkZ5|obJ_WE{b$N^9~f23R#eMBN(>w(FFjp@IVe}jN8 z=mSU1j?tL3FDsrKEC7ZgMi8w6vQ)g223VVRHxcziXs&cbC=S_5gGB@KbP zJgVxao8y|bKK9kMGWFGohm1(Y6Z>LXXT%YN>|r|APX~%2#N_E2yzQCVS`qxX;vD$K zO_Q&q-;Eqoo<#l1<)5(=PB$1W#S(8kRLU^g1@!o8rJ)XPtnw`k3JDwG;+k@*dFl!6 z?#kNxIA+gRejV024#*pK0vQ!uqXFF2=`ILf;YPC6S-mQ>P319Agn+8Je(|{AuaF0A zb`-eto!i3?A-*UC=KLO(37%x+kkcxiwavG%MB)Vnsqdl7&^IHO@?R@te9`F6$gLcx zbfq2`6~yWrru!|owOzi2gC(jx$Z3PkH(3_hF*wsI*gA?4zYA$nA$ZSx|MKjf;M)x< z_~noD5gE~o?}pJcC}NId39@0X|8Rc;ibcjT>iF;_dehDgA|S=($rq{k$23Mi$ zinMQSV@e4Or!x&r?P8pl@$S$wo|fHpW--V1)}GSwt{CXk3bPvgtL6b1NNE|jn>gZ9 z(ekQN=1^g0#WPb9iu07T8blw6O~NG*;&zS8mW+Yp|qR~QiOcNpZ_Io zSUk;(imFP>_U|(65E@_mbK@kAb8-_td_3Lsi{QSnUIm*3znhZb1bj^(ODL$W z^x}>tCA{WpB%_a+ao|5S9*hpz(s@4PDr)GuqRxyaVLxL-tLJld4SwwM?K$mMk#`0w zT18DZF67QD4jVN!q2s5j64Gqp1{>muIdrSD`>BELq=qYn|` zyqkNfn(fUg$Z+{LvTKb^n1!JrUxaB89vf37vRbT=9B5rqlL4N~89Cv3?5i_D{ltdG z_PXRNN$4qI6rJMG+DUp`HTpJZNa*CX&yG1nz=LQ16i`VQ2E^ET7xf>j;|>9^_4_4X z1yl3?M`!>C=B-h*x^K>38er|sMB-b>$x)gK2r3Z7WRD~vmL}1oPG=Drk=4C>u48+e z?9EKK)l~q>2t|fXbNI8`$k#eO>sruF+3Ea?%Updd9C!^I+{r0MWU zIBqiNfcE~fWFgM3HS^wKDyjUY24d+7b+XV%A0>Kl=la48E5?OcY5^Zx%trk>=20px z1HXnqv98?8J0Yxi8acR$vqmdlWdI8L?|>)wpPqluFL3tvH!Q|KFKW$8qm%OqlW2k? z2W84ii)vX~D>BfbcNtP_j3>W)CmdYr1Iek~tC>m56s_>oLQn3d0=9JmCs_0iSFONst zRIBIwkLHdJn7n+rYXtbr8~*H^#(?W&nD`~fp?${R*fzz@)`dX&u=c|!G{9};mH^y{upGPSNC`&Xu9Fsoy z1G|mG0Zj8`Vl(rTj(!|42qd&H5ste!Sh^-P8W2b;)$+-x;cDO&f7FWU1BziqGp>?! ztLTI-66LgzWp^})P(?W!Wem+8Emvzx zgxoE+tE+#|jMyWez(47S%h(eTF4RKf1_n(QxtsMHF!^!|CAWt<->To){(gLE#1~q=iks=bT(*lB;~7MF&*uLTZJyUnWCYyW z1u9MD_RVN(u+Y+(17>p@(AEv>unX6CV_S7@7kZZ1JU$$8YBkKV&XlNpzstVvrFRn6_T#ay~ zeQk%+|Ha0lZ&)Fd&PZ_eykLJcDX)ndtDcv=T4k}l|HHJ!z&{_@p866!@Bmced$uHKwHTZwXPYivn&SH)0S z{Wds&jv`NF1*S79GWFmt(Xn(IZ;^Kfprc|=Me`PyayEfKOs%c}K72$^PAuxh&MQi6 zan5+dC9weTRm(E>$gxKh*DV@FjFx5r8tG%u6YHTu!er}NLV^Md6O)hv)k5CaO>d-z z?`El+VXZLT)@ldh1s=8eiS`g|Jg!w%=$Xb5#;{Ze0)x`|jEzd29fPK$8Rl$Qn;p)2 z)!yloB8_6;C6W+DwUf2nCh$iM0Wl)xbhlbf1>6O%gkGWt-lwhOMV&O*_TyH*2rP*h z^m4C+Q|;k@wb|)3#MMKlgmTOa!%YdYRG?#iq7Q_3}&+i zl2LjTf{C7HKn>r4KuXu}IZseCI7LV|YE6m$SmZ>ZOx~Kgk>Jia1S(78n^tcwaO?mZLxk<0G3Zb!lFfj0!v!?=c z)gE{o$MEf?zs3>gEwPY`PUXbh;D7^FxYJO_efCTA{6)Z%>Ut^p{p`6f-mLe?Eb+E< zWIZu-!&i*|JWG8ta!sZJa9~{DEp}dOy%jOxrAv$b(&ro>Z*GcdsHqy-?>Jfw+nip_ zim8iCRI;HW)cJ@bF%0lfiWCq|A|NKyF09RI{(K4@`P>cIaenG-+)8yJ2vTT7?i*uO z2zBI`fd zzOJlZw;}mf%aW)&Z^0WxK(JV-)Kh;eQzaygO4P}YGV#ThhB3W`lYKQQIbeT(T`$&& zaJ@e5S>|_nL;|?6Pa%VhRC&Fd?WQH|368Ma{mktWgKcz@%B74@>3#&FO7W2JniFWr z&rl8(KYW|aid4*_rQgMu3r!3x9UbKb`p9KU-w#usO~z@vpk>5=6cvd=N{VQD7aA!a zT0OOJ!yM}nCgPJ8b3T@C>Fs$9tG1kz{Am#Yd(F*1GBviw#~=QWomBMI$3wjVCb*JD zW|=LVmmD2LW}G?QbWUx;UBz3LTJ> zcGI&umj5nPDK=b2Tnk)gd)~V3vg?YQhuFN5qoA&4%oEZ$Z9>`m>L`NX^lbv z#YfZwj);qciVs<`6arL5tl7H*n+Xfuy*`-%*S&%itWidXQ>Gp&S*j3Xq&Nv(Ro-U2 zv8xR>+gPXY_Vvws(=>m_tNlYgrM15K&=vaCrZ(YuHPbCRIRj5%cA%&wCWvsj$5V&s zYvy2?y+T_A10B)w^b^&3POs)`yD9*tIl&ewiVb&_!>D5GuLUFwIYwQ`x{;wak|DAL zQa-3TG`+55%#gzkcfYuXO;I3CD5|@v2uikgonfFDp*j`5SE61x>)KGL9W2wh|JPKdaGO^0XciQ2ip_2~FW|AdTyp zLd=`Bp*iypev`5hX3)koG>*7K*1Hg_7Z4EeW`h!Gs`q4><^2Y<3& zJJzz_n))jQrzQowJ#gn#ue0iHyv5Pqb`a1L;=h4CT0X%IGcElgYt^F^*7O{M+$eGP zvW?PnEePn8B6c3Y4IHGjMGH>BkK*|EkJU4yDQHE^PlSJZa9x($Qn2I!DkaJ~C<-l3 zx*G(a>8~{vTaGS~-_4zcR}Ol&zI+5YiTvagem6Ezj3DqbT)Wom5R2im-r@CX*=fb6 z=-SPm*yDZClTkB(`yk^mX*1AS?^Lebuw>_>;`b}wozgG z{3vm4INVwPVbZ0%*iq7Ts9ztX`??7jIF;izB=`~6REf*%)3UIw*qCdo^#b*jB2NR`tBZhEG4&om~I+1&K)JChGaYf^YhvVY`L2~Fq zjPL9O_POklCZG|_{2d+8i=dY$1SgSe48g~&vsh#T4e-jPjj^H}Yup4q%B{x(ufmhz9c&Mt-_ug;DZT3}yYeGMrZ+^{) zbGJ%P0*nbTG7V}-Atp2XAac88r7L%|CyXn$tW|77my{53WMsZg%0{xr?~fuk2`qqd zB>FIaeCkgzI|yH|VkIss5l5LCoE~G;bZzLWFHTpz+OHT;bOec>U95~e6km7xD}V32 zWq5Xxw%PPsUgqSV%q!5x)L(yGU+2&Eg9cuW6tk$wve@L%DT-qZcPItd9!_LHm*T~h zmD|lb@gaeKK1Lrhdzj5&6c2G_ZLTRine*v)X9)4uZ9PoQ64~xokceC=e_&COR=Dve zZD*w!k3F!fU2aAp1W0U7yhP7sAOKtfr^8HD{b70;?4MS==bptH&i&YPSuC;<_WPml zDB|koFxHlh6qpk#d(pAYz_kaqm~r;N4t1Mr>um$7IcWalGVQ}DmV(qILgHxQc(%{GHW8~@PA$&>E~ zZ8WTnP(A)jzQ-bbX6Z*)0rnqfu6E>@1X7893U~{|#&^UlrbZI^T~9Q(~2oyJL=sSH<5#;xo~iqr0(@zR17g<+)W@S)2N*q=^BH z)wAY=)X5h^SWE=n7C*ri?p_?iU*CBCmq&PMUqntsJHa|4A5-Ta*rziM2X(Y?W-|`s zr~UWb?{?k`BR2WFIeue==*3ak_D(*2+7Ea>dWJh1Rv6f&HAO^9s0|P|ka?Um%CK}M zcVjwIU}~er{#Mc<(Du(;Y?9gv&T^IdIbc>ABfo6SlBuS-)wu$xUqKKcmH(rZOw?zX zjc%+8>DR>@aD-q)YDD3r7vX6s7v0NZm443gy>6Jhfbm_)e0+pW-0nSzYFRQnnUKaM zkbD9T=l;HSi_4lkAFuMTH*ahK|1l0aL7EXkm?JO}LrEkoHZy$3dYf)3i+#N4Nx1%@ zbnSkue=t8&o}5n*_?>uFStCmB=$|ViWl&vnIU@^M*nH=Q#xCU9I*pOj42Dj*x-j2S zK->c}=_eK|1UnrN#!K|vA-rCJ6B>Bz>5eF0qGvaJt+*sOWFV4?bgm*0*QxlN!bfK@ zC#+j<_4D)k!(^nrtsR27(N*Cql9=*r`?c0uv-Y??)2Y^7Hg__aUXfSmp`~HS#~tke z6ZIm>s5Ew>sML5tRD7_+B(spRmZdUaU}rljOj_$iQ3?D>gPcd;x1F(}qJU;dkZTan z30as|{k8sSkM%o6OS#YIc!P7$^OB?9?q_cZ?B>2J%av;p{8O1i9@pkQDp=2CAw;!7 zuD}#0?;Qc^r!S{;PYJ0qXc%FpF(ubQq^jFtTMBg3WcYmT0AETi1%+RWFxyZWl??FY524hu_gOla&b(2UEJDlAF(l>|!d$ zESmlQtY}Ff3N~Wy;D#Sq$)ITuulPIt?D>4<$nJNVlo`X$|2oHhh|!H5o9;UgH6B*N ztJ8klAmrVx!j8c=)c-J4Z>lGs*Cs06+dz@1|CsoYBBj!#zA?~>utcx63!ry8{g(N( zwG?fdILMQQhn5M0N(%uIXq#GsGhFvhTAT*(#CQs_MM~l|R^q?fP`~Dp_JTOQPw9xZ z=-;+@{0Gh)J8>I(iJr&6*N+460~SXcDQ+h?YW{OIotf#%eB*kKYoWBTX^$^+f>AiAEkbG{Ylhm-U&j7p#<+l}fIbK~ ziMml*P^ikggDp4vMp80ckpI9T{F5~?(RL)t?;)u`+M3>7Hc9u;?>$JlnbBE$W(mnr z-D`D*jz^j}DV)uGIgcIXpyUl(R_9M22Ry^UgTAu!qco|#7tcpk=%-7t+p|+m>2c3H z5Bsjxq*4TKURL?kzz>;Ur$lR6S>i{BK|})nROP|XGr--zX!AzJ_a_W^mcc4M>~>|S z$)UOi$x!osiY(Ym?tyPN@Z{hfyIVg6pR*raG~j8t1P?OE3He$>%9e%QkTyn=1;Zuc zv#iN6&r1FGC50!+8HJM;yCWVi*S%~6ncit~7x@601RLL43GvUbMB&ZN`J(5i?&ENu z7Uz~lQY?WKQtc6p*ur1|9Nag-2N!-t%rR>dyJ??Cw)@ATutfu7-klXmSxT0!wS&=I zK>K(WE3Qp#I|BoYqkT8@%QA+nmYJ5g3#s}18lEuTZ;eS6XwsM1IQ^F?w}E)5S@6BQ(-?jseBKjxt>PhWT2yBu(llE$xO3KPe`~Ru-TI~- z_FVb}($-TyZeq=?eld9Rql;s=>8;q~Xh)WZ4jD@!A{HlNpM_SS{P?@b23GH+`Dk>J z@)MnJ9D=E-(P?b@dYt{o=B<2P+0b753!VoJ(cY?X|FQGzN$F+>!A<^%4CB^gmSCR7 z;ZNqQSB%}^@r{OVLj>q?lv+;X2lNYK8~o=TT|}q*utS0Rr=Ea${M}W~+L{1g*g8dy z-ojjf$DP)~o2HQ{X)>N5k#CHoeB!d^yE5&Cv>ejMzIuAfoo6AxBuc8pEy#hy(7)HZ z(!<1h_5*k|@J+>w5;-6az8iz>>YJ8$N%H#$?ga;3pLJRv25^`EI>iQ^Nfyq&HWqz8wG7q51D#WQxFYg3NOtMCUcE z9Cr3RK9cvGL?5KCj5?)33$!^DkqcH$4>lBPyRA>xXGi}|EAlo^;-9@eqOs0y@;Icp z=1kruJtEHlOr94KhR(j?oysItw(t|RbQ3p!uD|Szym6aOJ@40Z7Z(j18W$ojMtg)% z;$R9n9qeNRLb~`U6w18%xloz5fy$fbS$#ZSiXt&kh4N+x^zVH^rtmwVoCG zlKs!>@D1aR%-- zV9&iU*e$GkEW_=ijTBWP&+uBLOb`(yZRlQ_*M=%A)GFFo(uQ^^c&qW7E+m8TRT7|z zFxy*5&lrTdoh?Y2o2*oogf34^MG#KG3nT`xJ=Ef6bqtD!<1;31`Np;djqK8<&aHJ& z(majYKMxj!4aODzW$Jzu^DVvGNt6$7FKa&OQmJBJn5SFaxRl5j{FV3M-hs2&mSRiDtaXWLrN!}&cD z0QiGCA>%L6a}M8baKn2p`y*Pa3;2SN?%meuy@m!Gxcf;Hh2lV|g7Ba7uNp-OdBU>P za%cnzrtMQ!Kpj2*M0^U5s#%KVYYHB>Boii-QaL=(ZR`hj+x#Dz=Nso^fhSCH@7EQVp>;AuACP0BBtj}&0Uz|Cy@{>jLPC# zzH(|IaI9opnVJ1w1Jh6aqGdr|Ic?Bri8rB*GD;SH{|1m1v;Ad#w0BgF@!w^ukl-Q4 zM8upQ?GH~reY^0dO&F|q^Su2**ul88wpf~LR8Tg48yO2|L??6XmedVdtz~tuagH=Y zq;!f`bwMuI*43#H_Mk0s(DRPq*8Im>r~A)PC#H7LGd9I@p^S3G?H~BZd{R-(-&-2e z=@WRVJ= z8AE)&SsD$#iM3D3HSAoa6cBq9UHt(Y1+MlP&FE(f;g zn!_q=HK5Bgys*>EyGu&sc7J{o1v9h&YU*o9GpXHN=}z(^jS-zpPmWdE+s6j0m(oT< z1BJCawhoFI>DGg1#1*xBR-1L(4yh>dFro$!Q)l^->@~}B->Ko6I{QE?7cixDoxW*N9v#g z^V_(NJT_0$WgS{wE#NDVrrA~e>+SNmG=_U4SknfP(zEg6Ws@c1H2{9lBT$g*igU2~ zNhYv&MnY(i$CFXxC!)-|mY|qu*sbYU=Kik7b?kL#<|9(q7c`rvQiB)UQoav=z=3=|cdq@>K1 zMcB=wIghXZ85JlasR;H4vSTW<^xeAJWX}Io90Lv!DDF-h=Db4Fd}|M5-sn1Hq_+EA zPMxska*tQbMMJ0P$1;57b(>A%??WhZn=#RPxm|JNCE`UBS^PPbGDK>Cc)-LXp*xgK z(^*&7i>y1q)8)7}Sw1QBbJ}|PeStd`u27D{SzKv1z@Wwr_ z()nNX;3>clSm5k?J{}%8YQD(n8Ti{D|CQ^DD-LCxk{TZ3$Zv+klGzWGiY9KzSWqLn zT!7~HQD+$`$T$vRlr16%508?34jS|$QZK=P&*!y(WUuhfww>9Uw`CUkfH8epbV#Mq zjQO{B$RWZNL%zarvT${#y_r1%fRq92<15Lg^e9sR;(+u%BTp8CvcWAoy4)7uGSrMQ zU1dpek>rgIn<4Ym2wyC9Ua|hjnxN`ga#_bg^~m8`@ky5}J!BB4Y*F95d%gR+DaA)~ z8q{2UGu~zv1VXksBV>DoG7DPuI|-zjm{6f={YF_7TAxH>tQHC3qRpqbu+6TF_n#Y6 zRS~#@5zsQRw*DY8*>P-9683$lK}Bx1RBpAMd{jYBPh>(&QXVm?LcC7q>rrumDwp2; zm$VV^IL+bFR9aUluMJ%p~xLiAXP+cxQ=DMP9JEk~5Knw2{Y(5V`+fvb-3MD{yL zoT>hY@E@@R9jV%y#wk{55^?waD+p8j3e<0$qrX0!W*W_qa`^tOT&AUs4w&0`T3^lb zGj9SdeKL|pkYfE51bknJsEG6>Gl-2cbjGEEK9%DLg^@M3u^76ekYESBHpobs;6DGp z^1YqyLxyuof!r=L*Y|GDvz~S~LA_Q_8vF^zyv7om-ECvfL~&V%hWHj78O*o**-rsa zH@9u#2<%bqT|Y*Ggk(XiA0B$|o>o`e3IDAEfT3=wa@FAUYKc%TXUiGz8QqmRv^9!7 zNS81K^S%n@Bp={x9<G`;vpF-mWl5^NxPfOwMR+E=5C=8`v{p*Rv8ipq_$3=hb92BsxngBO? zr$+04wSMaU@%%VmRpwZi)RHuUjfkAi>k~5g13!k>RSW(bLzy)w%Nd{K66JO7j{8n=HuT_JDYs$}uCd*hB%&b5USOfQsN^WU*A zTtS#}KMsEEt8hd80y6E9&bbOx`aBSg#wO4xhtVhP{#na>`BxQTDwc?#LT8RHc_)aI zOeY2Aq69|h&*AIDX+4}i~>>|Ct_-bn=0y3E?vFx=a!1- z+}z)2H*q{|A3j-JGJ9aredN&z<@wH~iOx&N_YN&Am0LJLmfZNSL)0>u@duG`)8US3 z-fQWBK8+!PHhBT8>RGgjKOhiB6cQ#)VS&?8I_W?R`a5NxR+0l8QggEV)htcbjo~B& z1a-8=3#m{RUKxDh8iiJM(ePWY*+pDN6pVNDzZQwg9on|PFXbl;YHQ^`Un^}U{Fk)h zY73mm@M`BQ!^#Z5S;cB-{aH5cNs{w6jTw@2L^s4t>}9nSghWs)Y@LLwggd~T28(td zqh#mAl%XSzpaPy76Y;D)8@E18UX7o;A-WIwC9;7(j_~hLozb zss=;Ih$5=V@zYhG7;w;-u7ybGv!0TM_puNoc|s=#v8fKNQxD3T$fjG1PeN&3=0%cO zYM1RX7R0yOe&JJ_tk%u*P5g7G$DPF_%D$H!dq}i}q*F2}8rXGZ+`N&j7{yubvS=%M z#`7&;fSc`#nYBQaHGOn9QlhZx{8pG~x>|p5&AQeVE0Fe|$|P$8LXD1+5R^J#4}pVw z2!xXRK5*Oz6xzr)6V6ojtoJu(j-v$0%$OrSA7!?&RgvC zAFhkpL%--s;S2e|K^ts$ts>wnOPVxA%GUlyl8=8OWoWE)(TYNfju@{DLQC!Y*Tvb5 z)LA-w6dNViFA^Q7Zw^FW=gb#cx^5kVov+t;`j|x`NEd5sZ6RVra#*242{ON}&4EB* zNS)6Q$1|)H0d^3_Oqrd%8apqZ0%3mA!DNogNfP2s-KB{is{AePmH8mEDy^;201+J< zHzbwyW6srKy5cQ0TN(e<_3%iY1Fq#LYZA5jYe|Z58*=In;{5Y7(Ih)3KVA&;Z_A*- zDh9vG8$SyRv+=q%tvTs9WJ!6l$g~fCo0dW(nFx%H6p&^YoKqJq8buz&a-%;cDB;VD zh-sCqf3`D0ixY%6#Yy7uH(#y99y~+k%MVs|X?P%63o#Otq@#wb3M0nvzuNrQq6FgA zWre^Ky&^5;pO?8(eTK*TdKD7)jEBUL%XE45ChDkzf<@Tn{wi~T$REY3(lsqV;+Waz zex�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 kUKe_)H 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�vL~pKG$I5-o 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 diff --git a/test/common_utils/backend_utils.py b/test/common_utils/backend_utils.py index 158fde87ed..beceb6cafb 100644 --- a/test/common_utils/backend_utils.py +++ b/test/common_utils/backend_utils.py @@ -29,8 +29,8 @@ def supports_mp3(backend): def set_audio_backend(backend): """Allow additional backend value, 'default'""" if backend == 'default': - if 'sox' in BACKENDS: - be = 'sox' + if 'sox_io' in BACKENDS: + be = 'sox_io' elif 'soundfile' in BACKENDS: be = 'soundfile' else: diff --git a/test/common_utils/case_utils.py b/test/common_utils/case_utils.py index f3b0c343a6..9c89ef6891 100644 --- a/test/common_utils/case_utils.py +++ b/test/common_utils/case_utils.py @@ -14,33 +14,28 @@ class TempDirMixin: """Mixin to provide easy access to temp dir""" temp_dir_ = None - base_temp_dir = None - temp_dir = None @classmethod - def setUpClass(cls): - super().setUpClass() + def get_base_temp_dir(cls): # If TORCHAUDIO_TEST_TEMP_DIR is set, use it instead of temporary directory. # this is handy for debugging. key = 'TORCHAUDIO_TEST_TEMP_DIR' if key in os.environ: - cls.base_temp_dir = os.environ[key] - else: + return os.environ[key] + if cls.temp_dir_ is None: cls.temp_dir_ = tempfile.TemporaryDirectory() - cls.base_temp_dir = cls.temp_dir_.name + return cls.temp_dir_.name @classmethod def tearDownClass(cls): super().tearDownClass() - if isinstance(cls.temp_dir_, tempfile.TemporaryDirectory): + if cls.temp_dir_ is not None: cls.temp_dir_.cleanup() - - def setUp(self): - super().setUp() - self.temp_dir = os.path.join(self.base_temp_dir, self.id()) + cls.temp_dir_ = None def get_temp_path(self, *paths): - path = os.path.join(self.temp_dir, *paths) + temp_dir = os.path.join(self.get_base_temp_dir(), self.id()) + path = os.path.join(temp_dir, *paths) os.makedirs(os.path.dirname(path), exist_ok=True) return path diff --git a/test/common_utils/data_utils.py b/test/common_utils/data_utils.py index b948ce334a..de19d8174f 100644 --- a/test/common_utils/data_utils.py +++ b/test/common_utils/data_utils.py @@ -13,6 +13,28 @@ def get_asset_path(*paths): return os.path.join(_TEST_DIR_PATH, 'assets', *paths) +def convert_tensor_encoding( + tensor: torch.tensor, + dtype: torch.dtype, +): + """Convert input tensor with values between -1 and 1 to integer encoding + Args: + tensor: input tensor, assumed between -1 and 1 + dtype: desired output tensor dtype + Returns: + Tensor: shape of (n_channels, sample_rate * duration) + """ + if dtype == torch.int32: + tensor *= (tensor > 0) * 2147483647 + (tensor < 0) * 2147483648 + if dtype == torch.int16: + tensor *= (tensor > 0) * 32767 + (tensor < 0) * 32768 + if dtype == torch.uint8: + tensor *= (tensor > 0) * 127 + (tensor < 0) * 128 + tensor += 128 + tensor = tensor.to(dtype) + return tensor + + def get_whitenoise( *, sample_rate: int = 16000, @@ -43,25 +65,17 @@ def get_whitenoise( if dtype not in [torch.float32, torch.int32, torch.int16, torch.uint8]: raise NotImplementedError(f'dtype {dtype} is not supported.') # According to the doc, folking rng on all CUDA devices is slow when there are many CUDA devices, - # so we only folk on CPU, generate values and move the data to the given device + # so we only fork on CPU, generate values and move the data to the given device with torch.random.fork_rng([]): torch.random.manual_seed(seed) - tensor = torch.randn([sample_rate * duration], dtype=torch.float32, device='cpu') + tensor = torch.randn([int(sample_rate * duration)], dtype=torch.float32, device='cpu') tensor /= 2.0 tensor *= scale_factor tensor.clamp_(-1.0, 1.0) - if dtype == torch.int32: - tensor *= (tensor > 0) * 2147483647 + (tensor < 0) * 2147483648 - if dtype == torch.int16: - tensor *= (tensor > 0) * 32767 + (tensor < 0) * 32768 - if dtype == torch.uint8: - tensor *= (tensor > 0) * 127 + (tensor < 0) * 128 - tensor += 128 - tensor = tensor.to(dtype) tensor = tensor.repeat([n_channels, 1]) if not channels_first: tensor = tensor.t() - return tensor.to(device=device) + return convert_tensor_encoding(tensor, dtype) def get_sinusoid( @@ -72,6 +86,7 @@ def get_sinusoid( n_channels: int = 1, dtype: Union[str, torch.dtype] = "float32", device: Union[str, torch.device] = "cpu", + channels_first: bool = True, ): """Generate pseudo audio data with sine wave. @@ -90,5 +105,8 @@ def get_sinusoid( dtype = getattr(torch, dtype) pie2 = 2 * 3.141592653589793 end = pie2 * frequency * duration - theta = torch.linspace(0, end, sample_rate * duration, dtype=dtype, device=device) - return torch.sin(theta, out=None).repeat([n_channels, 1]) + theta = torch.linspace(0, end, int(sample_rate * duration), dtype=torch.float32, device=device) + tensor = torch.sin(theta, out=None).repeat([n_channels, 1]) + if not channels_first: + tensor = tensor.t() + return convert_tensor_encoding(tensor, dtype) diff --git a/test/common_utils/sox_utils.py b/test/common_utils/sox_utils.py index cd1c247b72..db131cdec5 100644 --- a/test/common_utils/sox_utils.py +++ b/test/common_utils/sox_utils.py @@ -77,3 +77,24 @@ def convert_audio_file( command += [dst_path] print(' '.join(command)) subprocess.run(command, check=True) + + +def _flattern(effects): + if not effects: + return effects + if isinstance(effects[0], str): + return effects + return [item for sublist in effects for item in sublist] + + +def run_sox_effect(input_file, output_file, effect, *, output_sample_rate=None, output_bitdepth=None): + """Run sox effects""" + effect = _flattern(effect) + command = ['sox', '-V', '--no-dither', input_file] + if output_bitdepth: + command += ['--bits', str(output_bitdepth)] + command += [output_file] + effect + if output_sample_rate: + command += ['rate', str(output_sample_rate)] + print(' '.join(command)) + subprocess.run(command, check=True) diff --git a/test/datasets/__init__.py b/test/datasets/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/test/test_datasets.py b/test/datasets/datasets_test.py similarity index 71% rename from test/test_datasets.py rename to test/datasets/datasets_test.py index c3b0c917da..b8a980f346 100644 --- a/test/test_datasets.py +++ b/test/datasets/datasets_test.py @@ -1,25 +1,20 @@ -import unittest - from torchaudio.datasets.commonvoice import COMMONVOICE from torchaudio.datasets.librispeech import LIBRISPEECH from torchaudio.datasets.speechcommands import SPEECHCOMMANDS from torchaudio.datasets.utils import diskcache_iterator, bg_iterator from torchaudio.datasets.vctk import VCTK -from torchaudio.datasets.yesno import YESNO from torchaudio.datasets.ljspeech import LJSPEECH -from torchaudio.datasets.gtzan import GTZAN from torchaudio.datasets.cmuarctic import CMUARCTIC -from . import common_utils +from ..common_utils import ( + TorchaudioTestCase, + get_asset_path, +) -class TestDatasets(common_utils.TorchaudioTestCase): +class TestDatasets(TorchaudioTestCase): backend = 'default' - path = common_utils.get_asset_path() - - def test_yesno(self): - data = YESNO(self.path) - data[0] + path = get_asset_path() def test_vctk(self): data = VCTK(self.path) @@ -37,18 +32,14 @@ def test_speechcommands(self): data = SPEECHCOMMANDS(self.path) data[0] - def test_gtzan(self): - data = GTZAN(self.path) - data[0] - def test_cmuarctic(self): data = CMUARCTIC(self.path) data[0] -class TestCommonVoice(common_utils.TorchaudioTestCase): +class TestCommonVoice(TorchaudioTestCase): backend = 'default' - path = common_utils.get_asset_path() + path = get_asset_path() def test_commonvoice(self): data = COMMONVOICE(self.path, url="tatar") @@ -67,7 +58,3 @@ def test_commonvoice_bg(self): data = bg_iterator(data, 5) for _ in data: pass - - -if __name__ == "__main__": - unittest.main() diff --git a/test/datasets/gtzan_test.py b/test/datasets/gtzan_test.py new file mode 100644 index 0000000000..14c82a512a --- /dev/null +++ b/test/datasets/gtzan_test.py @@ -0,0 +1,88 @@ +import os + +from torchaudio.datasets import gtzan + +from ..common_utils import ( + TempDirMixin, + TorchaudioTestCase, + get_whitenoise, + save_wav, + normalize_wav, +) + + +class TestGTZAN(TempDirMixin, TorchaudioTestCase): + backend = 'default' + + root_dir = None + samples = [] + training = [] + validation = [] + testing = [] + + @classmethod + def setUpClass(cls): + cls.root_dir = cls.get_base_temp_dir() + sample_rate = 22050 + seed = 0 + for genre in gtzan.gtzan_genres: + base_dir = os.path.join(cls.root_dir, 'genres', genre) + os.makedirs(base_dir, exist_ok=True) + for i in range(100): + filename = f'{genre}.{i:05d}' + path = os.path.join(base_dir, f'{filename}.wav') + data = get_whitenoise(sample_rate=sample_rate, duration=0.01, n_channels=1, dtype='int16', seed=seed) + save_wav(path, data, sample_rate) + sample = (normalize_wav(data), sample_rate, genre) + cls.samples.append(sample) + if filename in gtzan.filtered_test: + cls.testing.append(sample) + if filename in gtzan.filtered_train: + cls.training.append(sample) + if filename in gtzan.filtered_valid: + cls.validation.append(sample) + seed += 1 + + def test_no_subset(self): + dataset = gtzan.GTZAN(self.root_dir) + + n_ite = 0 + for i, (waveform, sample_rate, label) in enumerate(dataset): + self.assertEqual(waveform, self.samples[i][0], atol=5e-5, rtol=1e-8) + assert sample_rate == self.samples[i][1] + assert label == self.samples[i][2] + n_ite += 1 + assert n_ite == len(self.samples) + + def test_training(self): + dataset = gtzan.GTZAN(self.root_dir, subset='training') + + n_ite = 0 + for i, (waveform, sample_rate, label) in enumerate(dataset): + self.assertEqual(waveform, self.training[i][0], atol=5e-5, rtol=1e-8) + assert sample_rate == self.training[i][1] + assert label == self.training[i][2] + n_ite += 1 + assert n_ite == len(self.training) + + def test_validation(self): + dataset = gtzan.GTZAN(self.root_dir, subset='validation') + + n_ite = 0 + for i, (waveform, sample_rate, label) in enumerate(dataset): + self.assertEqual(waveform, self.validation[i][0], atol=5e-5, rtol=1e-8) + assert sample_rate == self.validation[i][1] + assert label == self.validation[i][2] + n_ite += 1 + assert n_ite == len(self.validation) + + def test_testing(self): + dataset = gtzan.GTZAN(self.root_dir, subset='testing') + + n_ite = 0 + for i, (waveform, sample_rate, label) in enumerate(dataset): + self.assertEqual(waveform, self.testing[i][0], atol=5e-5, rtol=1e-8) + assert sample_rate == self.testing[i][1] + assert label == self.testing[i][2] + n_ite += 1 + assert n_ite == len(self.testing) diff --git a/test/datasets/libritts_test.py b/test/datasets/libritts_test.py new file mode 100644 index 0000000000..f31561d211 --- /dev/null +++ b/test/datasets/libritts_test.py @@ -0,0 +1,71 @@ +import os + +from torchaudio.datasets.libritts import LIBRITTS + +from ..common_utils import ( + TempDirMixin, + TorchaudioTestCase, + get_whitenoise, + save_wav, + normalize_wav, +) + + +class TestLibriTTS(TempDirMixin, TorchaudioTestCase): + backend = 'default' + + root_dir = None + data = [] + utterance_ids = [ + [19, 198, '000000', '000000'], + [26, 495, '000004', '000000'], + ] + original_text = 'this is the original text.' + normalized_text = 'this is the normalized text.' + + @classmethod + def setUpClass(cls): + cls.root_dir = cls.get_base_temp_dir() + base_dir = os.path.join(cls.root_dir, 'LibriTTS', 'train-clean-100') + for i, utterance_id in enumerate(cls.utterance_ids): + filename = f'{"_".join(str(u) for u in utterance_id)}.wav' + file_dir = os.path.join(base_dir, str(utterance_id[0]), str(utterance_id[1])) + os.makedirs(file_dir, exist_ok=True) + path = os.path.join(file_dir, filename) + + data = get_whitenoise(sample_rate=8000, duration=6, n_channels=1, dtype='int16', seed=i) + save_wav(path, data, 8000) + cls.data.append(normalize_wav(data)) + + original_text_filename = f'{"_".join(str(u) for u in utterance_id)}.original.txt' + path_original = os.path.join(file_dir, original_text_filename) + with open(path_original, 'w') as file_: + file_.write(cls.original_text) + + normalized_text_filename = f'{"_".join(str(u) for u in utterance_id)}.normalized.txt' + path_normalized = os.path.join(file_dir, normalized_text_filename) + with open(path_normalized, 'w') as file_: + file_.write(cls.normalized_text) + + def test_libritts(self): + dataset = LIBRITTS(self.root_dir) + n_ites = 0 + for i, (waveform, + sample_rate, + original_text, + normalized_text, + speaker_id, + chapter_id, + utterance_id) in enumerate(dataset): + + expected_ids = self.utterance_ids[i] + expected_data = self.data[i] + self.assertEqual(expected_data, waveform, atol=5e-5, rtol=1e-8) + assert sample_rate == 8000 + assert speaker_id == expected_ids[0] + assert chapter_id == expected_ids[1] + assert original_text == self.original_text + assert normalized_text == self.normalized_text + assert utterance_id == f'{"_".join(str(u) for u in expected_ids[-4:])}' + n_ites += 1 + assert n_ites == len(self.utterance_ids) diff --git a/test/datasets/utils_test.py b/test/datasets/utils_test.py new file mode 100644 index 0000000000..e77df09f4c --- /dev/null +++ b/test/datasets/utils_test.py @@ -0,0 +1,47 @@ +import os +from pathlib import Path + +from torchaudio.datasets import utils as dataset_utils + +from ..common_utils import ( + TempDirMixin, + TorchaudioTestCase, +) + + +class TestWalkFiles(TempDirMixin, TorchaudioTestCase): + root = None + expected = None + + def _add_file(self, *parts): + path = self.get_temp_path(*parts) + self.expected.append(path) + Path(path).touch() + + def setUp(self): + self.root = self.get_temp_path() + self.expected = [] + + # level 1 + for filename in ['a.txt', 'b.txt', 'c.txt']: + self._add_file(filename) + + # level 2 + for dir1 in ['d1', 'd2', 'd3']: + for filename in ['d.txt', 'e.txt', 'f.txt']: + self._add_file(dir1, filename) + # level 3 + for dir2 in ['d1', 'd2', 'd3']: + for filename in ['g.txt', 'h.txt', 'i.txt']: + self._add_file(dir1, dir2, filename) + + print('\n'.join(self.expected)) + + def test_walk_files(self): + """walk_files should traverse files in alphabetical order""" + n_ites = 0 + for i, path in enumerate(dataset_utils.walk_files(self.root, '.txt', prefix=True)): + found = os.path.join(self.root, path) + assert found == self.expected[i] + n_ites += 1 + assert n_ites == len(self.expected) diff --git a/test/datasets/yesno_test.py b/test/datasets/yesno_test.py new file mode 100644 index 0000000000..f9c4d0b051 --- /dev/null +++ b/test/datasets/yesno_test.py @@ -0,0 +1,49 @@ +import os + +from torchaudio.datasets import yesno + +from ..common_utils import ( + TempDirMixin, + TorchaudioTestCase, + get_whitenoise, + save_wav, + normalize_wav, +) + + +class TestYesNo(TempDirMixin, TorchaudioTestCase): + backend = 'default' + + root_dir = None + data = [] + labels = [ + [0, 0, 0, 0, 0, 0, 0, 0], + [0, 0, 0, 0, 1, 1, 1, 1], + [0, 1, 0, 1, 0, 1, 1, 0], + [1, 1, 1, 1, 0, 0, 0, 0], + [1, 1, 1, 1, 1, 1, 1, 1], + ] + + @classmethod + def setUpClass(cls): + cls.root_dir = cls.get_base_temp_dir() + base_dir = os.path.join(cls.root_dir, 'waves_yesno') + os.makedirs(base_dir, exist_ok=True) + for label in cls.labels: + filename = f'{"_".join(str(l) for l in label)}.wav' + path = os.path.join(base_dir, filename) + data = get_whitenoise(sample_rate=8000, duration=6, n_channels=1, dtype='int16') + save_wav(path, data, 8000) + cls.data.append(normalize_wav(data)) + + def test_yesno(self): + dataset = yesno.YESNO(self.root_dir) + n_ite = 0 + for i, (waveform, sample_rate, label) in enumerate(dataset): + expected_label = self.labels[i] + expected_data = self.data[i] + self.assertEqual(expected_data, waveform, atol=5e-5, rtol=1e-8) + assert sample_rate == 8000 + assert label == expected_label + n_ite += 1 + assert n_ite == len(self.data) diff --git a/test/functional_cpu_test.py b/test/functional_cpu_test.py index ab5fdaed95..b162df2ebc 100644 --- a/test/functional_cpu_test.py +++ b/test/functional_cpu_test.py @@ -4,6 +4,7 @@ import torch import torchaudio import torchaudio.functional as F +from parameterized import parameterized import pytest from . import common_utils @@ -299,24 +300,18 @@ def test_linearity_of_istft4(self): class TestDetectPitchFrequency(common_utils.TorchaudioTestCase): - def test_pitch(self): - test_filepath_100 = common_utils.get_asset_path("100Hz_44100Hz_16bit_05sec.wav") - test_filepath_440 = common_utils.get_asset_path("440Hz_44100Hz_16bit_05sec.wav") + @parameterized.expand([(100,), (440,)]) + def test_pitch(self, frequency): + sample_rate = 44100 + test_sine_waveform = common_utils.get_sinusoid( + frequency=frequency, sample_rate=sample_rate, duration=5, + ) - # Files from https://www.mediacollege.com/audio/tone/download/ - tests = [ - (test_filepath_100, 100), - (test_filepath_440, 440), - ] + freq = torchaudio.functional.detect_pitch_frequency(test_sine_waveform, sample_rate) - for filename, freq_ref in tests: - waveform, sample_rate = common_utils.load_wav(filename) - - freq = torchaudio.functional.detect_pitch_frequency(waveform, sample_rate) - - threshold = 1 - s = ((freq - freq_ref).abs() > threshold).sum() - self.assertFalse(s) + threshold = 1 + s = ((freq - frequency).abs() > threshold).sum() + self.assertFalse(s) class TestDB_to_amplitude(common_utils.TorchaudioTestCase): @@ -410,7 +405,3 @@ def test_mask_along_axis_iid(mask_param, mask_value, axis): assert mask_specgrams.size() == specgrams.size() assert (num_masked_columns < mask_param).sum() == num_masked_columns.numel() - - -if __name__ == '__main__': - unittest.main() diff --git a/test/sox_effect/__init__.py b/test/sox_effect/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/test/sox_effect/common.py b/test/sox_effect/common.py new file mode 100644 index 0000000000..86edcf6476 --- /dev/null +++ b/test/sox_effect/common.py @@ -0,0 +1,26 @@ +import json + +from parameterized import param + +from ..common_utils import get_asset_path + + +def name_func(func, _, params): + if isinstance(params.args[0], str): + args = "_".join([str(arg) for arg in params.args]) + else: + args = "_".join([str(arg) for arg in params.args[0]]) + return f'{func.__name__}_{args}' + + +def load_params(*paths): + params = [] + with open(get_asset_path(*paths), 'r') as file: + for line in file: + data = json.loads(line) + for effect in data['effects']: + for i, arg in enumerate(effect): + if arg.startswith(""): + effect[i] = arg.replace("", get_asset_path()) + params.append(param(data)) + return params diff --git a/test/sox_effect/smoke_test.py b/test/sox_effect/smoke_test.py new file mode 100644 index 0000000000..4997002170 --- /dev/null +++ b/test/sox_effect/smoke_test.py @@ -0,0 +1,59 @@ +from torchaudio import sox_effects +from parameterized import parameterized + +from ..common_utils import ( + TempDirMixin, + TorchaudioTestCase, + skipIfNoExtension, + get_wav_data, + get_sinusoid, + save_wav, +) +from .common import ( + name_func, + load_params, +) + + +@skipIfNoExtension +class SmokeTest(TempDirMixin, TorchaudioTestCase): + """Run smoke test on various effects + + The purpose of this test suite is to verify that sox_effect functionalities do not exhibit + abnormal behaviors. + + This test suite should be able to run without any additional tools (such as sox command), + however without such tools, the correctness of each function cannot be verified. + """ + @parameterized.expand( + load_params("sox_effect_test_args.json"), + name_func=lambda f, i, p: f'{f.__name__}_{i}_{p.args[0]["effects"][0][0]}', + ) + def test_apply_effects_tensor(self, args): + """`apply_effects_tensor` should not crash""" + effects = args['effects'] + num_channels = args.get("num_channels", 2) + input_sr = args.get("input_sample_rate", 8000) + original = get_sinusoid( + frequency=800, sample_rate=input_sr, + n_channels=num_channels, dtype='float32') + _found, _sr = sox_effects.apply_effects_tensor(original, input_sr, effects) + + @parameterized.expand( + load_params("sox_effect_test_args.json"), + name_func=lambda f, i, p: f'{f.__name__}_{i}_{p.args[0]["effects"][0][0]}', + ) + def test_apply_effects(self, args): + """`apply_effects_file` should return identical data as sox command""" + dtype = 'int32' + channels_first = True + effects = args['effects'] + num_channels = args.get("num_channels", 2) + input_sr = args.get("input_sample_rate", 8000) + + input_path = self.get_temp_path('input.wav') + data = get_wav_data(dtype, num_channels, channels_first=channels_first) + save_wav(input_path, data, input_sr, channels_first=channels_first) + + _found, _sr = sox_effects.apply_effects_file( + input_path, effects, normalize=False, channels_first=channels_first) diff --git a/test/test_sox_effects.py b/test/sox_effect/sox_effects_chain_test.py similarity index 82% rename from test/test_sox_effects.py rename to test/sox_effect/sox_effects_chain_test.py index 6b12d7cd06..765ab62094 100644 --- a/test/test_sox_effects.py +++ b/test/sox_effect/sox_effects_chain_test.py @@ -5,7 +5,7 @@ import torch import torchaudio -from . import common_utils +from .. import common_utils @common_utils.skipIfNoSoxBackend @@ -45,8 +45,8 @@ def test_lowpass_speed(self): E.append_effect_to_chain("speed", speed) E.append_effect_to_chain("rate", si.rate) x, sr = E.sox_build_flow_effects() - # check if effects worked - self.assertEqual(x.size(1), int((si.length / si.channels) / speed)) + # check if effects worked, add small tolerance for rounding effects + self.assertEqual(x.size(1), int((si.length / si.channels) / speed), atol=1, rtol=1e-8) def test_ulaw_and_siginfo(self): si_out = torchaudio.sox_signalinfo_t() @@ -222,55 +222,3 @@ def test_invalid_effect_options(self): E.append_effect_to_chain("compand", ["0.3", "1", "6:-70,-60,-20", "-5", "-90", "0.2"]) with self.assertRaises(RuntimeError): E.sox_build_flow_effects() - - def test_fade(self): - x_orig, _ = torchaudio.load(self.test_filepath) - fade_in_len = 44100 - fade_out_len = 44100 - - for fade_shape_sox, fade_shape_torchaudio in (("q", "quarter_sine"), ("h", "half_sine"), ("t", "linear")): - E = torchaudio.sox_effects.SoxEffectsChain() - E.set_input_file(self.test_filepath) - E.append_effect_to_chain("fade", [fade_shape_sox, 1, "0", 1]) - x, sr = E.sox_build_flow_effects() - - fade = torchaudio.transforms.Fade(fade_in_len, fade_out_len, fade_shape_torchaudio) - - # check if effect worked - self.assertTrue(x.allclose(fade(x_orig), rtol=1e-4, atol=1e-4)) - - def test_vol(self): - x_orig, _ = torchaudio.load(self.test_filepath) - - for gain, gain_type in ((1.1, "amplitude"), (2, "db"), (2, "power")): - E = torchaudio.sox_effects.SoxEffectsChain() - E.set_input_file(self.test_filepath) - E.append_effect_to_chain("vol", [gain, gain_type]) - x, sr = E.sox_build_flow_effects() - - vol = torchaudio.transforms.Vol(gain, gain_type) - z = vol(x_orig) - # check if effect worked - self.assertTrue(x.allclose(z, rtol=1e-4, atol=1e-4)) - - def test_vad(self): - sample_files = [ - common_utils.get_asset_path("vad-go-stereo-44100.wav"), - common_utils.get_asset_path("vad-go-mono-32000.wav") - ] - - for sample_file in sample_files: - E = torchaudio.sox_effects.SoxEffectsChain() - E.set_input_file(sample_file) - E.append_effect_to_chain("vad") - x, _ = E.sox_build_flow_effects() - - x_orig, sample_rate = torchaudio.load(sample_file) - vad = torchaudio.transforms.Vad(sample_rate) - - y = vad(x_orig) - self.assertTrue(x.allclose(y, rtol=1e-4, atol=1e-4)) - - -if __name__ == '__main__': - unittest.main() diff --git a/test/sox_effect/test_dataset.py b/test/sox_effect/test_dataset.py new file mode 100644 index 0000000000..f1b71eb806 --- /dev/null +++ b/test/sox_effect/test_dataset.py @@ -0,0 +1,114 @@ +from typing import List, Tuple + +import numpy as np +import torch +import torchaudio + +from ..common_utils import ( + TempDirMixin, + PytorchTestCase, + skipIfNoExtension, + get_whitenoise, + save_wav, +) + + +class RandomPerturbationFile(torch.utils.data.Dataset): + """Given flist, apply random speed perturbation""" + def __init__(self, flist: List[str], sample_rate: int): + super().__init__() + self.flist = flist + self.sample_rate = sample_rate + self.rng = None + + def __getitem__(self, index): + speed = self.rng.uniform(0.5, 2.0) + effects = [ + ['gain', '-n', '-10'], + ['speed', f'{speed:.5f}'], # duration of data is 0.5 ~ 2.0 seconds. + ['rate', f'{self.sample_rate}'], + ['pad', '0', '1.5'], # add 1.5 seconds silence at the end + ['trim', '0', '2'], # get the first 2 seconds + ] + data, _ = torchaudio.sox_effects.apply_effects_file(self.flist[index], effects) + return data + + def __len__(self): + return len(self.flist) + + +class RandomPerturbationTensor(torch.utils.data.Dataset): + """Apply speed purturbation to (synthetic) Tensor data""" + def __init__(self, signals: List[Tuple[torch.Tensor, int]], sample_rate: int): + super().__init__() + self.signals = signals + self.sample_rate = sample_rate + self.rng = None + + def __getitem__(self, index): + speed = self.rng.uniform(0.5, 2.0) + effects = [ + ['gain', '-n', '-10'], + ['speed', f'{speed:.5f}'], # duration of data is 0.5 ~ 2.0 seconds. + ['rate', f'{self.sample_rate}'], + ['pad', '0', '1.5'], # add 1.5 seconds silence at the end + ['trim', '0', '2'], # get the first 2 seconds + ] + tensor, sample_rate = self.signals[index] + data, _ = torchaudio.sox_effects.apply_effects_tensor(tensor, sample_rate, effects) + return data + + def __len__(self): + return len(self.signals) + + +def init_random_seed(worker_id): + dataset = torch.utils.data.get_worker_info().dataset + dataset.rng = np.random.RandomState(worker_id) + + +@skipIfNoExtension +class TestSoxEffectsDataset(TempDirMixin, PytorchTestCase): + """Test `apply_effects_file` in multi-process dataloader setting""" + + def _generate_dataset(self, num_samples=128): + flist = [] + for i in range(num_samples): + sample_rate = np.random.choice([8000, 16000, 44100]) + dtype = np.random.choice(['float32', 'int32', 'int16', 'uint8']) + data = get_whitenoise(n_channels=2, sample_rate=sample_rate, duration=1, dtype=dtype) + path = self.get_temp_path(f'{i:03d}_{dtype}_{sample_rate}.wav') + save_wav(path, data, sample_rate) + flist.append(path) + return flist + + def test_apply_effects_file(self): + sample_rate = 12000 + flist = self._generate_dataset() + dataset = RandomPerturbationFile(flist, sample_rate) + loader = torch.utils.data.DataLoader( + dataset, batch_size=32, num_workers=16, + worker_init_fn=init_random_seed, + ) + for batch in loader: + assert batch.shape == (32, 2, 2 * sample_rate) + + def _generate_signals(self, num_samples=128): + signals = [] + for _ in range(num_samples): + sample_rate = np.random.choice([8000, 16000, 44100]) + data = get_whitenoise( + n_channels=2, sample_rate=sample_rate, duration=1, dtype='float32') + signals.append((data, sample_rate)) + return signals + + def test_apply_effects_tensor(self): + sample_rate = 12000 + signals = self._generate_signals() + dataset = RandomPerturbationTensor(signals, sample_rate) + loader = torch.utils.data.DataLoader( + dataset, batch_size=32, num_workers=16, + worker_init_fn=init_random_seed, + ) + for batch in loader: + assert batch.shape == (32, 2, 2 * sample_rate) diff --git a/test/sox_effect/test_sox_effect.py b/test/sox_effect/test_sox_effect.py new file mode 100644 index 0000000000..38ab0fa772 --- /dev/null +++ b/test/sox_effect/test_sox_effect.py @@ -0,0 +1,221 @@ +import itertools + +from torchaudio import sox_effects +from parameterized import parameterized + +from ..common_utils import ( + TempDirMixin, + PytorchTestCase, + skipIfNoExtension, + get_sinusoid, + get_wav_data, + save_wav, + load_wav, + sox_utils, +) +from .common import ( + load_params, + name_func, +) + + +@skipIfNoExtension +class TestSoxEffects(PytorchTestCase): + def test_init(self): + """Calling init_sox_effects multiple times does not crush""" + for _ in range(3): + sox_effects.init_sox_effects() + + +@skipIfNoExtension +class TestSoxEffectsTensor(TempDirMixin, PytorchTestCase): + """Test suite for `apply_effects_tensor` function""" + @parameterized.expand(list(itertools.product( + ['float32', 'int32', 'int16', 'uint8'], + [8000, 16000], + [1, 2, 4, 8], + [True, False] + )), name_func=name_func) + def test_apply_no_effect(self, dtype, sample_rate, num_channels, channels_first): + """`apply_effects_tensor` without effects should return identical data as input""" + original = get_wav_data(dtype, num_channels, channels_first=channels_first) + expected = original.clone() + found, output_sample_rate = sox_effects.apply_effects_tensor( + expected, sample_rate, [], channels_first) + + assert output_sample_rate == sample_rate + # SoxEffect should not alter the input Tensor object + self.assertEqual(original, expected) + # SoxEffect should not return the same Tensor object + assert expected is not found + # Returned Tensor should equal to the input Tensor + self.assertEqual(expected, found) + + @parameterized.expand( + load_params("sox_effect_test_args.json"), + name_func=lambda f, i, p: f'{f.__name__}_{i}_{p.args[0]["effects"][0][0]}', + ) + def test_apply_effects(self, args): + """`apply_effects_tensor` should return identical data as sox command""" + effects = args['effects'] + num_channels = args.get("num_channels", 2) + input_sr = args.get("input_sample_rate", 8000) + output_sr = args.get("output_sample_rate") + + input_path = self.get_temp_path('input.wav') + reference_path = self.get_temp_path('reference.wav') + + original = get_sinusoid( + frequency=800, sample_rate=input_sr, + n_channels=num_channels, dtype='float32') + save_wav(input_path, original, input_sr) + sox_utils.run_sox_effect( + input_path, reference_path, effects, output_sample_rate=output_sr) + + expected, expected_sr = load_wav(reference_path) + found, sr = sox_effects.apply_effects_tensor(original, input_sr, effects) + + assert sr == expected_sr + self.assertEqual(expected, found) + + +@skipIfNoExtension +class TestSoxEffectsFile(TempDirMixin, PytorchTestCase): + """Test suite for `apply_effects_file` function""" + @parameterized.expand(list(itertools.product( + ['float32', 'int32', 'int16', 'uint8'], + [8000, 16000], + [1, 2, 4, 8], + [False, True], + )), name_func=name_func) + def test_apply_no_effect(self, dtype, sample_rate, num_channels, channels_first): + """`apply_effects_file` without effects should return identical data as input""" + path = self.get_temp_path('input.wav') + expected = get_wav_data(dtype, num_channels, channels_first=channels_first) + save_wav(path, expected, sample_rate, channels_first=channels_first) + + found, output_sample_rate = sox_effects.apply_effects_file( + path, [], normalize=False, channels_first=channels_first) + + assert output_sample_rate == sample_rate + self.assertEqual(expected, found) + + @parameterized.expand( + load_params("sox_effect_test_args.json"), + name_func=lambda f, i, p: f'{f.__name__}_{i}_{p.args[0]["effects"][0][0]}', + ) + def test_apply_effects(self, args): + """`apply_effects_file` should return identical data as sox command""" + dtype = 'int32' + channels_first = True + effects = args['effects'] + num_channels = args.get("num_channels", 2) + input_sr = args.get("input_sample_rate", 8000) + output_sr = args.get("output_sample_rate") + + input_path = self.get_temp_path('input.wav') + reference_path = self.get_temp_path('reference.wav') + data = get_wav_data(dtype, num_channels, channels_first=channels_first) + save_wav(input_path, data, input_sr, channels_first=channels_first) + sox_utils.run_sox_effect( + input_path, reference_path, effects, output_sample_rate=output_sr) + + expected, expected_sr = load_wav(reference_path) + found, sr = sox_effects.apply_effects_file( + input_path, effects, normalize=False, channels_first=channels_first) + + assert sr == expected_sr + self.assertEqual(found, expected) + + +@skipIfNoExtension +class TestFileFormats(TempDirMixin, PytorchTestCase): + """`apply_effects_file` gives the same result as sox on various file formats""" + @parameterized.expand(list(itertools.product( + ['float32', 'int32', 'int16', 'uint8'], + [8000, 16000], + [1, 2], + )), name_func=lambda f, _, p: f'{f.__name__}_{"_".join(str(arg) for arg in p.args)}') + def test_wav(self, dtype, sample_rate, num_channels): + """`apply_effects_file` works on various wav format""" + channels_first = True + effects = [['band', '300', '10']] + + input_path = self.get_temp_path('input.wav') + reference_path = self.get_temp_path('reference.wav') + data = get_wav_data(dtype, num_channels, channels_first=channels_first) + save_wav(input_path, data, sample_rate, channels_first=channels_first) + sox_utils.run_sox_effect(input_path, reference_path, effects) + + expected, expected_sr = load_wav(reference_path) + found, sr = sox_effects.apply_effects_file( + input_path, effects, normalize=False, channels_first=channels_first) + + assert sr == expected_sr + self.assertEqual(found, expected) + + @parameterized.expand(list(itertools.product( + [8000, 16000], + [1, 2], + )), name_func=lambda f, _, p: f'{f.__name__}_{"_".join(str(arg) for arg in p.args)}') + def test_mp3(self, sample_rate, num_channels): + """`apply_effects_file` works on various mp3 format""" + channels_first = True + effects = [['band', '300', '10']] + + input_path = self.get_temp_path('input.mp3') + reference_path = self.get_temp_path('reference.wav') + sox_utils.gen_audio_file(input_path, sample_rate, num_channels) + sox_utils.run_sox_effect(input_path, reference_path, effects) + + expected, expected_sr = load_wav(reference_path) + found, sr = sox_effects.apply_effects_file( + input_path, effects, channels_first=channels_first) + save_wav(self.get_temp_path('result.wav'), found, sr, channels_first=channels_first) + + assert sr == expected_sr + self.assertEqual(found, expected, atol=1e-4, rtol=1e-8) + + @parameterized.expand(list(itertools.product( + [8000, 16000], + [1, 2], + )), name_func=lambda f, _, p: f'{f.__name__}_{"_".join(str(arg) for arg in p.args)}') + def test_flac(self, sample_rate, num_channels): + """`apply_effects_file` works on various flac format""" + channels_first = True + effects = [['band', '300', '10']] + + input_path = self.get_temp_path('input.flac') + reference_path = self.get_temp_path('reference.wav') + sox_utils.gen_audio_file(input_path, sample_rate, num_channels) + sox_utils.run_sox_effect(input_path, reference_path, effects, output_bitdepth=32) + + expected, expected_sr = load_wav(reference_path) + found, sr = sox_effects.apply_effects_file( + input_path, effects, channels_first=channels_first) + save_wav(self.get_temp_path('result.wav'), found, sr, channels_first=channels_first) + + assert sr == expected_sr + self.assertEqual(found, expected) + + @parameterized.expand(list(itertools.product( + [8000, 16000], + [1, 2], + )), name_func=lambda f, _, p: f'{f.__name__}_{"_".join(str(arg) for arg in p.args)}') + def test_vorbis(self, sample_rate, num_channels): + """`apply_effects_file` works on various vorbis format""" + channels_first = True + effects = [['band', '300', '10']] + + input_path = self.get_temp_path('input.vorbis') + reference_path = self.get_temp_path('reference.wav') + sox_utils.gen_audio_file(input_path, sample_rate, num_channels) + sox_utils.run_sox_effect(input_path, reference_path, effects, output_bitdepth=32) + + expected, expected_sr = load_wav(reference_path) + found, sr = sox_effects.apply_effects_file( + input_path, effects, channels_first=channels_first) + save_wav(self.get_temp_path('result.wav'), found, sr, channels_first=channels_first) + + assert sr == expected_sr + self.assertEqual(found, expected) diff --git a/test/sox_effect/test_torchscript.py b/test/sox_effect/test_torchscript.py new file mode 100644 index 0000000000..ded923ab11 --- /dev/null +++ b/test/sox_effect/test_torchscript.py @@ -0,0 +1,100 @@ +from typing import List + +import torch +from torchaudio import sox_effects +from parameterized import parameterized + +from ..common_utils import ( + TempDirMixin, + PytorchTestCase, + skipIfNoExtension, + get_sinusoid, + save_wav, +) +from .common import ( + load_params, +) + + +class SoxEffectTensorTransform(torch.nn.Module): + effects: List[List[str]] + + def __init__(self, effects: List[List[str]], sample_rate: int, channels_first: bool): + super().__init__() + self.effects = effects + self.sample_rate = sample_rate + self.channels_first = channels_first + + def forward(self, tensor: torch.Tensor): + return sox_effects.apply_effects_tensor( + tensor, self.sample_rate, self.effects, self.channels_first) + + +class SoxEffectFileTransform(torch.nn.Module): + effects: List[List[str]] + channels_first: bool + + def __init__(self, effects: List[List[str]], channels_first: bool): + super().__init__() + self.effects = effects + self.channels_first = channels_first + + def forward(self, path: str): + return sox_effects.apply_effects_file(path, self.effects, self.channels_first) + + +@skipIfNoExtension +class TestTorchScript(TempDirMixin, PytorchTestCase): + @parameterized.expand( + load_params("sox_effect_test_args.json"), + name_func=lambda f, i, p: f'{f.__name__}_{i}_{p.args[0]["effects"][0][0]}', + ) + def test_apply_effects_tensor(self, args): + effects = args['effects'] + channels_first = True + num_channels = args.get("num_channels", 2) + input_sr = args.get("input_sample_rate", 8000) + + trans = SoxEffectTensorTransform(effects, input_sr, channels_first) + + path = self.get_temp_path('sox_effect.zip') + torch.jit.script(trans).save(path) + trans = torch.jit.load(path) + + wav = get_sinusoid( + frequency=800, sample_rate=input_sr, + n_channels=num_channels, dtype='float32', channels_first=channels_first) + found, sr_found = trans(wav) + expected, sr_expected = sox_effects.apply_effects_tensor( + wav, input_sr, effects, channels_first) + + assert sr_found == sr_expected + self.assertEqual(expected, found) + + @parameterized.expand( + load_params("sox_effect_test_args.json"), + name_func=lambda f, i, p: f'{f.__name__}_{i}_{p.args[0]["effects"][0][0]}', + ) + def test_apply_effects_file(self, args): + effects = args['effects'] + channels_first = True + num_channels = args.get("num_channels", 2) + input_sr = args.get("input_sample_rate", 8000) + + trans = SoxEffectFileTransform(effects, channels_first) + + path = self.get_temp_path('sox_effect.zip') + torch.jit.script(trans).save(path) + trans = torch.jit.load(path) + + path = self.get_temp_path('input.wav') + wav = get_sinusoid( + frequency=800, sample_rate=input_sr, + n_channels=num_channels, dtype='float32', channels_first=channels_first) + save_wav(path, wav, sample_rate=input_sr, channels_first=channels_first) + + found, sr_found = trans(path) + expected, sr_expected = sox_effects.apply_effects_file(path, effects, channels_first) + + assert sr_found == sr_expected + self.assertEqual(expected, found) diff --git a/test/sox_io_backend/smoke_test.py b/test/sox_io_backend/smoke_test.py new file mode 100644 index 0000000000..1ae9a8d938 --- /dev/null +++ b/test/sox_io_backend/smoke_test.py @@ -0,0 +1,87 @@ +import itertools +import unittest + +from torchaudio.utils import sox_utils +from torchaudio.backend import sox_io_backend +from torchaudio._internal.module_utils import is_module_available +from parameterized import parameterized + +from ..common_utils import ( + TempDirMixin, + TorchaudioTestCase, + skipIfNoExtension, + get_wav_data, +) +from .common import name_func + + +skipIfNoMP3 = unittest.skipIf( + not is_module_available('torchaudio._torchaudio') or + 'mp3' not in sox_utils.list_read_formats() or + 'mp3' not in sox_utils.list_write_formats(), + '"sox_io" backend does not support MP3') + + +@skipIfNoExtension +class SmokeTest(TempDirMixin, TorchaudioTestCase): + """Run smoke test on various audio format + + The purpose of this test suite is to verify that sox_io_backend functionalities do not exhibit + abnormal behaviors. + + This test suite should be able to run without any additional tools (such as sox command), + however without such tools, the correctness of each function cannot be verified. + """ + def run_smoke_test(self, ext, sample_rate, num_channels, *, compression=None, dtype='float32'): + duration = 1 + num_frames = sample_rate * duration + path = self.get_temp_path(f'test.{ext}') + original = get_wav_data(dtype, num_channels, normalize=False, num_frames=num_frames) + + # 1. run save + sox_io_backend.save(path, original, sample_rate, compression=compression) + # 2. run info + info = sox_io_backend.info(path) + assert info.sample_rate == sample_rate + assert info.num_channels == num_channels + # 3. run load + loaded, sr = sox_io_backend.load(path, normalize=False) + assert sr == sample_rate + assert loaded.shape[0] == num_channels + + @parameterized.expand(list(itertools.product( + ['float32', 'int32', 'int16', 'uint8'], + [8000, 16000], + [1, 2], + )), name_func=name_func) + def test_wav(self, dtype, sample_rate, num_channels): + """Run smoke test on wav format""" + self.run_smoke_test('wav', sample_rate, num_channels, dtype=dtype) + + @parameterized.expand(list(itertools.product( + [8000, 16000], + [1, 2], + [-4.2, -0.2, 0, 0.2, 96, 128, 160, 192, 224, 256, 320], + ))) + @skipIfNoMP3 + def test_mp3(self, sample_rate, num_channels, bit_rate): + """Run smoke test on mp3 format""" + self.run_smoke_test('mp3', sample_rate, num_channels, compression=bit_rate) + + @parameterized.expand(list(itertools.product( + [8000, 16000], + [1, 2], + [-1, 0, 1, 2, 3, 3.6, 5, 10], + ))) + def test_vorbis(self, sample_rate, num_channels, quality_level): + """Run smoke test on vorbis format""" + self.run_smoke_test('vorbis', sample_rate, num_channels, compression=quality_level) + + @parameterized.expand(list(itertools.product( + [8000, 16000], + [1, 2], + list(range(9)), + )), name_func=name_func) + def test_flac(self, sample_rate, num_channels, compression_level): + """Run smoke test on flac format""" + self.run_smoke_test('flac', sample_rate, num_channels, compression=compression_level) diff --git a/test/test_batch_consistency.py b/test/test_batch_consistency.py index 2a88598f88..e7040fdc0b 100644 --- a/test/test_batch_consistency.py +++ b/test/test_batch_consistency.py @@ -1,5 +1,7 @@ """Test numerical consistency among single input and batched input.""" import unittest +import itertools +from parameterized import parameterized import torch import torchaudio @@ -47,17 +49,15 @@ def test_griffinlim(self): F.griffinlim, tensor, window, n_fft, hop, ws, power, normalize, n_iter, momentum, length, 0, atol=5e-5 ) - def test_detect_pitch_frequency(self): - filenames = [ - 'steam-train-whistle-daniel_simon.wav', # 2ch 44100Hz - # Files from https://www.mediacollege.com/audio/tone/download/ - '100Hz_44100Hz_16bit_05sec.wav', # 1ch - '440Hz_44100Hz_16bit_05sec.wav', # 1ch - ] - for filename in filenames: - filepath = common_utils.get_asset_path(filename) - waveform, sample_rate = torchaudio.load(filepath) - self.assert_batch_consistencies(F.detect_pitch_frequency, waveform, sample_rate) + @parameterized.expand(list(itertools.product( + [100, 440], + [8000, 16000, 44100], + [1, 2], + )), name_func=lambda f, _, p: f'{f.__name__}_{"_".join(str(arg) for arg in p.args)}') + def test_detect_pitch_frequency(self, frequency, sample_rate, n_channels): + waveform = common_utils.get_sinusoid(frequency=frequency, sample_rate=sample_rate, + n_channels=n_channels, duration=5) + self.assert_batch_consistencies(F.detect_pitch_frequency, waveform, sample_rate) def test_istft(self): stft = torch.tensor([ @@ -80,8 +80,10 @@ def test_overdrive(self): self.assert_batch_consistencies(F.overdrive, waveform, gain=45, colour=30) def test_phaser(self): - filepath = common_utils.get_asset_path("whitenoise.wav") - waveform, sample_rate = torchaudio.load(filepath) + sample_rate = 44100 + waveform = common_utils.get_whitenoise( + sample_rate=sample_rate, duration=5, + ) self.assert_batch_consistencies(F.phaser, waveform, sample_rate) def test_flanger(self): @@ -286,7 +288,3 @@ def test_batch_Vol(self): # Batch then transform computed = torchaudio.transforms.Vol(gain=1.1)(waveform.repeat(3, 1, 1)) self.assertEqual(computed, expected) - - -if __name__ == '__main__': - unittest.main() diff --git a/test/test_compliance_kaldi.py b/test/test_compliance_kaldi.py index f9e097e09c..450183d6b3 100644 --- a/test/test_compliance_kaldi.py +++ b/test/test_compliance_kaldi.py @@ -47,14 +47,25 @@ def first_sample_of_frame(frame, window_size, window_shift, snip_edges): @common_utils.skipIfNoSoxBackend -class Test_Kaldi(common_utils.TorchaudioTestCase): +class Test_Kaldi(common_utils.TempDirMixin, common_utils.TorchaudioTestCase): backend = 'sox' - test_filepath = common_utils.get_asset_path('kaldi_file.wav') - test_8000_filepath = common_utils.get_asset_path('kaldi_file_8000.wav') kaldi_output_dir = common_utils.get_asset_path('kaldi') + test_filepath = common_utils.get_asset_path('kaldi_file.wav') test_filepaths = {prefix: [] for prefix in compliance_utils.TEST_PREFIX} + def setUp(self): + super().setUp() + + # 1. test signal for testing resampling + self.test1_signal_sr = 16000 + self.test1_signal = common_utils.get_whitenoise( + sample_rate=self.test1_signal_sr, duration=0.5, + ) + + # 2. test audio file corresponding to saved kaldi ark files + self.test2_filepath = common_utils.get_asset_path('kaldi_file_8000.wav') + # separating test files by their types (e.g 'spec', 'fbank', etc.) for f in os.listdir(kaldi_output_dir): dash_idx = f.find('-') @@ -94,7 +105,6 @@ def test_get_strided(self): def _create_data_set(self): # used to generate the dataset to test on. this is not used in testing (offline procedure) - test_filepath = common_utils.get_asset_path('kaldi_file.wav') sr = 16000 x = torch.arange(0, 20).float() # between [-6,6] @@ -103,8 +113,8 @@ def _create_data_set(self): y = (y / 6 * (1 << 30)).long() # clear the last 16 bits because they aren't used anyways y = ((y >> 16) << 16).float() - torchaudio.save(test_filepath, y, sr) - sound, sample_rate = torchaudio.load(test_filepath, normalization=False) + torchaudio.save(self.test_filepath, y, sr) + sound, sample_rate = torchaudio.load(self.test_filepath, normalization=False) print(y >> 16) self.assertTrue(sample_rate == sr) torch.testing.assert_allclose(y, sound) @@ -123,7 +133,7 @@ def _print_diagnostic(self, output, expect_output): print('relative_mse:', relative_mse.item(), 'relative_max_error:', relative_max_error.item()) def _compliance_test_helper(self, sound_filepath, filepath_key, expected_num_files, - expected_num_args, get_output_fn, atol=1e-5, rtol=1e-8): + expected_num_args, get_output_fn, atol=1e-5, rtol=1e-7): """ Inputs: sound_filepath (str): The location of the sound file @@ -135,7 +145,7 @@ def _compliance_test_helper(self, sound_filepath, filepath_key, expected_num_fil atol (float): absolute tolerance rtol (float): relative tolerance """ - sound, sample_rate = torchaudio.load_wav(sound_filepath) + sound, sr = torchaudio.load_wav(sound_filepath) files = self.test_filepaths[filepath_key] assert len(files) == expected_num_files, ('number of kaldi %s file changed to %d' % (filepath_key, len(files))) @@ -170,22 +180,19 @@ def get_output_fn(sound, args): output = kaldi.resample_waveform(sound, args[1], args[2]) return output - self._compliance_test_helper(self.test_8000_filepath, 'resample', 32, 3, get_output_fn, atol=1e-2, rtol=1e-5) + self._compliance_test_helper(self.test2_filepath, 'resample', 32, 3, get_output_fn, atol=1e-2, rtol=1e-5) def test_resample_waveform_upsample_size(self): - sound, sample_rate = torchaudio.load_wav(self.test_8000_filepath) - upsample_sound = kaldi.resample_waveform(sound, sample_rate, sample_rate * 2) - self.assertTrue(upsample_sound.size(-1) == sound.size(-1) * 2) + upsample_sound = kaldi.resample_waveform(self.test1_signal, self.test1_signal_sr, self.test1_signal_sr * 2) + self.assertTrue(upsample_sound.size(-1) == self.test1_signal.size(-1) * 2) def test_resample_waveform_downsample_size(self): - sound, sample_rate = torchaudio.load_wav(self.test_8000_filepath) - downsample_sound = kaldi.resample_waveform(sound, sample_rate, sample_rate // 2) - self.assertTrue(downsample_sound.size(-1) == sound.size(-1) // 2) + downsample_sound = kaldi.resample_waveform(self.test1_signal, self.test1_signal_sr, self.test1_signal_sr // 2) + self.assertTrue(downsample_sound.size(-1) == self.test1_signal.size(-1) // 2) def test_resample_waveform_identity_size(self): - sound, sample_rate = torchaudio.load_wav(self.test_8000_filepath) - downsample_sound = kaldi.resample_waveform(sound, sample_rate, sample_rate) - self.assertTrue(downsample_sound.size(-1) == sound.size(-1)) + downsample_sound = kaldi.resample_waveform(self.test1_signal, self.test1_signal_sr, self.test1_signal_sr) + self.assertTrue(downsample_sound.size(-1) == self.test1_signal.size(-1)) def _test_resample_waveform_accuracy(self, up_scale_factor=None, down_scale_factor=None, atol=1e-1, rtol=1e-4): @@ -226,20 +233,16 @@ def test_resample_waveform_upsample_accuracy(self): def test_resample_waveform_multi_channel(self): num_channels = 3 - sound, sample_rate = torchaudio.load_wav(self.test_8000_filepath) # (1, 8000) - multi_sound = sound.repeat(num_channels, 1) # (num_channels, 8000) + multi_sound = self.test1_signal.repeat(num_channels, 1) # (num_channels, 8000 smp) for i in range(num_channels): multi_sound[i, :] *= (i + 1) * 1.5 - multi_sound_sampled = kaldi.resample_waveform(multi_sound, sample_rate, sample_rate // 2) + multi_sound_sampled = kaldi.resample_waveform(multi_sound, self.test1_signal_sr, self.test1_signal_sr // 2) # check that sampling is same whether using separately or in a tensor of size (c, n) for i in range(num_channels): - single_channel = sound * (i + 1) * 1.5 - single_channel_sampled = kaldi.resample_waveform(single_channel, sample_rate, sample_rate // 2) - torch.testing.assert_allclose(multi_sound_sampled[i, :], single_channel_sampled[0], rtol=1e-4, atol=1e-8) - - -if __name__ == '__main__': - unittest.main() + single_channel = self.test1_signal * (i + 1) * 1.5 + single_channel_sampled = kaldi.resample_waveform(single_channel, self.test1_signal_sr, + self.test1_signal_sr // 2) + torch.testing.assert_allclose(multi_sound_sampled[i, :], single_channel_sampled[0], rtol=1e-4, atol=1e-7) diff --git a/test/test_dataloader.py b/test/test_dataloader.py index 1bf73ebb64..6d1518b70c 100644 --- a/test/test_dataloader.py +++ b/test/test_dataloader.py @@ -37,7 +37,3 @@ def test_1(self): dl = DataLoader(ds, batch_size=2) for x in dl: self.assertTrue(x.size() == expected_size) - - -if __name__ == '__main__': - unittest.main() diff --git a/test/test_io.py b/test/test_io.py index 2c8aece85e..b55885059a 100644 --- a/test/test_io.py +++ b/test/test_io.py @@ -282,6 +282,3 @@ def _test_5_get_info(self): self.assertEqual(si.length, samples) self.assertEqual(si.rate, rate) self.assertEqual(ei.bits_per_sample, precision) - -if __name__ == '__main__': - unittest.main() diff --git a/test/test_kaldi_io.py b/test/test_kaldi_io.py index 4bd0fd56a4..80e6b3dc5a 100644 --- a/test/test_kaldi_io.py +++ b/test/test_kaldi_io.py @@ -33,7 +33,3 @@ def test_read_vec_flt_ark(self): def test_read_mat_ark(self): self._test_helper("mat.ark", [self.data1, self.data2], kio.read_mat_ark, torch.float32) - - -if __name__ == '__main__': - unittest.main() diff --git a/test/test_librosa_compatibility.py b/test/test_librosa_compatibility.py index aa933535e8..01b0f23732 100644 --- a/test/test_librosa_compatibility.py +++ b/test/test_librosa_compatibility.py @@ -270,16 +270,13 @@ def test_basics4(self): } self.assert_compatibilities(**kwargs) - @unittest.skipIf(not common_utils.BACKENDS_MP3, 'no backend to read mp3') def test_MelScale(self): """MelScale transform is comparable to that of librosa""" n_fft = 2048 n_mels = 256 hop_length = n_fft // 4 - - # Prepare spectrogram input. We use torchaudio to compute one. - common_utils.set_audio_backend('default') - sound, sample_rate = _load_audio_asset('whitenoise_1min.mp3') + sample_rate = 44100 + sound = common_utils.get_whitenoise(sample_rate=sample_rate, duration=60) sound = sound.mean(dim=0, keepdim=True) spec_ta = F.spectrogram( sound, pad=0, window=torch.hann_window(n_fft), n_fft=n_fft, @@ -347,7 +344,3 @@ def test_InverseMelScale(self): # torch.dist(spec_lr, spec_ta, p=1) # >>> tensor(943.2759) assert torch.dist(spec_orig, spec_ta, p=1) < threshold - - -if __name__ == '__main__': - unittest.main() diff --git a/test/test_models.py b/test/test_models.py index c54a57cebd..10ca5c827b 100644 --- a/test/test_models.py +++ b/test/test_models.py @@ -74,7 +74,12 @@ def test_waveform(self): for upsample_scale in upsample_scales: total_scale *= upsample_scale - model = _UpsampleNetwork(upsample_scales, n_res_block, n_freq, n_hidden, n_output, kernel_size) + model = _UpsampleNetwork(upsample_scales, + n_res_block, + n_freq, + n_hidden, + n_output, + kernel_size) x = torch.rand(n_batch, n_freq, n_time) out1, out2 = model(x) @@ -86,14 +91,13 @@ def test_waveform(self): class TestWaveRNN(common_utils.TorchaudioTestCase): def test_waveform(self): - """Validate the output dimensions of a _WaveRNN model in waveform mode. + """Validate the output dimensions of a _WaveRNN model. """ upsample_scales = [5, 5, 8] n_rnn = 512 n_fc = 512 - n_bits = 9 - sample_rate = 24000 + n_classes = 512 hop_length = 200 n_batch = 2 n_time = 200 @@ -102,41 +106,12 @@ def test_waveform(self): n_res_block = 10 n_hidden = 128 kernel_size = 5 - mode = 'waveform' - model = _WaveRNN(upsample_scales, n_bits, sample_rate, hop_length, n_res_block, - n_rnn, n_fc, kernel_size, n_freq, n_hidden, n_output, mode) + model = _WaveRNN(upsample_scales, n_classes, hop_length, n_res_block, + n_rnn, n_fc, kernel_size, n_freq, n_hidden, n_output) x = torch.rand(n_batch, 1, hop_length * (n_time - kernel_size + 1)) mels = torch.rand(n_batch, 1, n_freq, n_time) out = model(x, mels) - assert out.size() == (n_batch, 1, hop_length * (n_time - kernel_size + 1), 2 ** n_bits) - - def test_mol(self): - """Validate the output dimensions of a _WaveRNN model in mol mode. - """ - - upsample_scales = [5, 5, 8] - n_rnn = 512 - n_fc = 512 - n_bits = 9 - sample_rate = 24000 - hop_length = 200 - n_batch = 2 - n_time = 200 - n_freq = 100 - n_output = 256 - n_res_block = 10 - n_hidden = 128 - kernel_size = 5 - mode = 'mol' - - model = _WaveRNN(upsample_scales, n_bits, sample_rate, hop_length, n_res_block, - n_rnn, n_fc, kernel_size, n_freq, n_hidden, n_output, mode) - - x = torch.rand(n_batch, 1, hop_length * (n_time - kernel_size + 1)) - mels = torch.rand(n_batch, 1, n_freq, n_time) - out = model(x, mels) - - assert out.size() == (n_batch, 1, hop_length * (n_time - kernel_size + 1), 30) + assert out.size() == (n_batch, 1, hop_length * (n_time - kernel_size + 1), n_classes) diff --git a/test/test_sox_compatibility.py b/test/test_sox_compatibility.py index a5d9f8633c..260c435b83 100644 --- a/test/test_sox_compatibility.py +++ b/test/test_sox_compatibility.py @@ -1,492 +1,296 @@ import unittest import torch -import torchaudio import torchaudio.functional as F import torchaudio.transforms as T - -from . import common_utils - - -@common_utils.skipIfNoSoxBackend -class TestFunctionalFiltering(common_utils.TempDirMixin, common_utils.TorchaudioTestCase): - backend = 'sox' - - def setUp(self): - # 1. Create int16 signal to save as PCM wav - # 2. Write to temp file - # 3. Load temp file into tensor to reuse in downstream tests - # Prefer to use common_utils.load_wav() but this implementation does - # not match torchaudio.load and errors on downstream tests - super().setUp() - - self.NOISE_SAMPLE_RATE = 44100 # N.B. 44.1 kHz required by SoX deemph effect - noise_waveform_as_int = common_utils.get_whitenoise( - sample_rate=self.NOISE_SAMPLE_RATE, duration=5, dtype=torch.int16, scale_factor=0.9, +from parameterized import parameterized + +from .common_utils import ( + skipIfNoSoxBackend, + skipIfNoExec, + TempDirMixin, + TorchaudioTestCase, + get_asset_path, + sox_utils, + load_wav, + save_wav, + get_whitenoise, +) + + +@skipIfNoSoxBackend +@skipIfNoExec('sox') +class TestFunctionalFiltering(TempDirMixin, TorchaudioTestCase): + def run_sox_effect(self, input_file, effect): + output_file = self.get_temp_path('expected.wav') + sox_utils.run_sox_effect(input_file, output_file, [str(e) for e in effect]) + return load_wav(output_file) + + def assert_sox_effect(self, result, input_path, effects, atol=1e-04, rtol=1e-5): + expected, _ = self.run_sox_effect(input_path, effects) + self.assertEqual(result, expected, atol=atol, rtol=rtol) + + def get_whitenoise(self, sample_rate=8000): + noise = get_whitenoise( + sample_rate=sample_rate, duration=3, scale_factor=0.9, ) - self.noise_filepath = self.get_temp_path("whitenoise.wav") - common_utils.save_wav( - self.noise_filepath, noise_waveform_as_int, self.NOISE_SAMPLE_RATE - ) - self.noise_waveform, _ = torchaudio.load(self.noise_filepath, normalization=True) + path = self.get_temp_path("whitenoise.wav") + save_wav(path, noise, sample_rate) + return noise, path def test_gain(self): - test_filepath = common_utils.get_asset_path('steam-train-whistle-daniel_simon.wav') - waveform, _ = common_utils.load_wav(test_filepath) - - waveform_gain = F.gain(waveform, 3) - self.assertTrue(waveform_gain.abs().max().item(), 1.) - - E = torchaudio.sox_effects.SoxEffectsChain() - E.set_input_file(test_filepath) - E.append_effect_to_chain("gain", [3]) - sox_gain_waveform = E.sox_build_flow_effects()[0] - - self.assertEqual(waveform_gain, sox_gain_waveform, atol=1e-04, rtol=1e-5) + path = get_asset_path('steam-train-whistle-daniel_simon.wav') + data, _ = load_wav(path) + result = F.gain(data, 3) + self.assert_sox_effect(result, path, ['gain', 3]) def test_dither(self): - test_filepath = common_utils.get_asset_path('steam-train-whistle-daniel_simon.wav') - waveform, _ = common_utils.load_wav(test_filepath) - - waveform_dithered = F.dither(waveform) - waveform_dithered_noiseshaped = F.dither(waveform, noise_shaping=True) + path = get_asset_path('steam-train-whistle-daniel_simon.wav') + data, _ = load_wav(path) + result = F.dither(data) + self.assert_sox_effect(result, path, ['dither']) - E = torchaudio.sox_effects.SoxEffectsChain() - E.set_input_file(test_filepath) - E.append_effect_to_chain("dither", []) - sox_dither_waveform = E.sox_build_flow_effects()[0] - - self.assertEqual(waveform_dithered, sox_dither_waveform, atol=1e-04, rtol=1e-5) - E.clear_chain() - - E.append_effect_to_chain("dither", ["-s"]) - sox_dither_waveform_ns = E.sox_build_flow_effects()[0] - - self.assertEqual(waveform_dithered_noiseshaped, sox_dither_waveform_ns, atol=1e-02, rtol=1e-5) - - def test_vctk_transform_pipeline(self): - test_filepath_vctk = common_utils.get_asset_path('VCTK-Corpus', 'wav48', 'p224', 'p224_002.wav') - wf_vctk, sr_vctk = common_utils.load_wav(test_filepath_vctk) - - # rate - sample = T.Resample(sr_vctk, 16000, resampling_method='sinc_interpolation') - wf_vctk = sample(wf_vctk) - # dither - wf_vctk = F.dither(wf_vctk, noise_shaping=True) - - E = torchaudio.sox_effects.SoxEffectsChain() - E.set_input_file(test_filepath_vctk) - E.append_effect_to_chain("gain", ["-h"]) - E.append_effect_to_chain("channels", [1]) - E.append_effect_to_chain("rate", [16000]) - E.append_effect_to_chain("gain", ["-rh"]) - E.append_effect_to_chain("dither", ["-s"]) - wf_vctk_sox = E.sox_build_flow_effects()[0] - - self.assertEqual(wf_vctk, wf_vctk_sox, rtol=1e-03, atol=1e-03) + def test_dither_noise(self): + path = get_asset_path('steam-train-whistle-daniel_simon.wav') + data, _ = load_wav(path) + result = F.dither(data, noise_shaping=True) + self.assert_sox_effect(result, path, ['dither', '-s'], atol=1.5e-4) def test_lowpass(self): - """ - Test biquad lowpass filter, compare to SoX implementation - """ cutoff_freq = 3000 + sample_rate = 8000 - E = torchaudio.sox_effects.SoxEffectsChain() - E.set_input_file(self.noise_filepath) - E.append_effect_to_chain("lowpass", [cutoff_freq]) - sox_output_waveform, sr = E.sox_build_flow_effects() - - output_waveform = F.lowpass_biquad(self.noise_waveform, self.NOISE_SAMPLE_RATE, cutoff_freq) - - self.assertEqual(output_waveform, sox_output_waveform, atol=1e-4, rtol=1e-5) + data, path = self.get_whitenoise(sample_rate) + result = F.lowpass_biquad(data, sample_rate, cutoff_freq) + self.assert_sox_effect(result, path, ['lowpass', cutoff_freq], atol=1.5e-4) def test_highpass(self): - """ - Test biquad highpass filter, compare to SoX implementation - """ cutoff_freq = 2000 + sample_rate = 8000 - E = torchaudio.sox_effects.SoxEffectsChain() - E.set_input_file(self.noise_filepath) - E.append_effect_to_chain("highpass", [cutoff_freq]) - sox_output_waveform, sr = E.sox_build_flow_effects() - - output_waveform = F.highpass_biquad(self.noise_waveform, self.NOISE_SAMPLE_RATE, cutoff_freq) - - self.assertEqual(output_waveform, sox_output_waveform, atol=1.5e-3, rtol=1e-5) + data, path = self.get_whitenoise(sample_rate) + result = F.highpass_biquad(data, sample_rate, cutoff_freq) + self.assert_sox_effect(result, path, ['highpass', cutoff_freq], atol=1.5e-4) def test_allpass(self): - """ - Test biquad allpass filter, compare to SoX implementation - """ central_freq = 1000 q = 0.707 + sample_rate = 8000 - E = torchaudio.sox_effects.SoxEffectsChain() - E.set_input_file(self.noise_filepath) - E.append_effect_to_chain("allpass", [central_freq, str(q) + 'q']) - sox_output_waveform, sr = E.sox_build_flow_effects() - - output_waveform = F.allpass_biquad(self.noise_waveform, self.NOISE_SAMPLE_RATE, central_freq, q) - - self.assertEqual(output_waveform, sox_output_waveform, atol=1e-4, rtol=1e-5) + data, path = self.get_whitenoise(sample_rate) + result = F.allpass_biquad(data, sample_rate, central_freq, q) + self.assert_sox_effect(result, path, ['allpass', central_freq, f'{q}q']) def test_bandpass_with_csg(self): - """ - Test biquad bandpass filter, compare to SoX implementation - """ central_freq = 1000 q = 0.707 const_skirt_gain = True + sample_rate = 8000 - E = torchaudio.sox_effects.SoxEffectsChain() - E.set_input_file(self.noise_filepath) - E.append_effect_to_chain("bandpass", ["-c", central_freq, str(q) + 'q']) - sox_output_waveform, sr = E.sox_build_flow_effects() - - output_waveform = F.bandpass_biquad(self.noise_waveform, self.NOISE_SAMPLE_RATE, - central_freq, q, const_skirt_gain) - - self.assertEqual(output_waveform, sox_output_waveform, atol=1e-4, rtol=1e-5) + data, path = self.get_whitenoise(sample_rate) + result = F.bandpass_biquad(data, sample_rate, central_freq, q, const_skirt_gain) + self.assert_sox_effect(result, path, ['bandpass', '-c', central_freq, f'{q}q']) def test_bandpass_without_csg(self): - """ - Test biquad bandpass filter, compare to SoX implementation - """ central_freq = 1000 q = 0.707 const_skirt_gain = False + sample_rate = 8000 - E = torchaudio.sox_effects.SoxEffectsChain() - E.set_input_file(self.noise_filepath) - E.append_effect_to_chain("bandpass", [central_freq, str(q) + 'q']) - sox_output_waveform, sr = E.sox_build_flow_effects() - - output_waveform = F.bandpass_biquad(self.noise_waveform, self.NOISE_SAMPLE_RATE, - central_freq, q, const_skirt_gain) - - self.assertEqual(output_waveform, sox_output_waveform, atol=1e-4, rtol=1e-5) + data, path = self.get_whitenoise(sample_rate) + result = F.bandpass_biquad(data, sample_rate, central_freq, q, const_skirt_gain) + self.assert_sox_effect(result, path, ['bandpass', central_freq, f'{q}q']) def test_bandreject(self): - """ - Test biquad bandreject filter, compare to SoX implementation - """ central_freq = 1000 q = 0.707 + sample_rate = 8000 - E = torchaudio.sox_effects.SoxEffectsChain() - E.set_input_file(self.noise_filepath) - E.append_effect_to_chain("bandreject", [central_freq, str(q) + 'q']) - sox_output_waveform, sr = E.sox_build_flow_effects() - - output_waveform = F.bandreject_biquad(self.noise_waveform, self.NOISE_SAMPLE_RATE, - central_freq, q) - - self.assertEqual(output_waveform, sox_output_waveform, atol=1e-4, rtol=1e-5) + data, path = self.get_whitenoise(sample_rate) + result = F.bandreject_biquad(data, sample_rate, central_freq, q) + self.assert_sox_effect(result, path, ['bandreject', central_freq, f'{q}q']) def test_band_with_noise(self): - """ - Test biquad band filter with noise mode, compare to SoX implementation - """ central_freq = 1000 q = 0.707 noise = True + sample_rate = 8000 - E = torchaudio.sox_effects.SoxEffectsChain() - E.set_input_file(self.noise_filepath) - E.append_effect_to_chain("band", ["-n", central_freq, str(q) + 'q']) - sox_output_waveform, sr = E.sox_build_flow_effects() - - output_waveform = F.band_biquad(self.noise_waveform, self.NOISE_SAMPLE_RATE, central_freq, q, noise) - - self.assertEqual(output_waveform, sox_output_waveform, atol=1e-4, rtol=1e-5) + data, path = self.get_whitenoise(sample_rate) + result = F.band_biquad(data, sample_rate, central_freq, q, noise) + self.assert_sox_effect(result, path, ['band', '-n', central_freq, f'{q}q']) def test_band_without_noise(self): - """ - Test biquad band filter without noise mode, compare to SoX implementation - """ - central_freq = 1000 q = 0.707 noise = False + sample_rate = 8000 - E = torchaudio.sox_effects.SoxEffectsChain() - E.set_input_file(self.noise_filepath) - E.append_effect_to_chain("band", [central_freq, str(q) + 'q']) - sox_output_waveform, sr = E.sox_build_flow_effects() - - output_waveform = F.band_biquad(self.noise_waveform, self.NOISE_SAMPLE_RATE, central_freq, q, noise) - - self.assertEqual(output_waveform, sox_output_waveform, atol=1e-4, rtol=1e-5) + data, path = self.get_whitenoise(sample_rate) + result = F.band_biquad(data, sample_rate, central_freq, q, noise) + self.assert_sox_effect(result, path, ['band', central_freq, f'{q}q']) def test_treble(self): - """ - Test biquad treble filter, compare to SoX implementation - """ - central_freq = 1000 q = 0.707 gain = 40 + sample_rate = 8000 - E = torchaudio.sox_effects.SoxEffectsChain() - E.set_input_file(self.noise_filepath) - E.append_effect_to_chain("treble", [gain, central_freq, str(q) + 'q']) - sox_output_waveform, sr = E.sox_build_flow_effects() - - output_waveform = F.treble_biquad(self.noise_waveform, self.NOISE_SAMPLE_RATE, gain, central_freq, q) - - self.assertEqual(output_waveform, sox_output_waveform, atol=1e-4, rtol=1e-5) + data, path = self.get_whitenoise(sample_rate) + result = F.treble_biquad(data, sample_rate, gain, central_freq, q) + self.assert_sox_effect(result, path, ['treble', gain, central_freq, f'{q}q']) def test_bass(self): - """ - Test biquad bass filter, compare to SoX implementation - """ - central_freq = 1000 q = 0.707 gain = 40 + sample_rate = 8000 - E = torchaudio.sox_effects.SoxEffectsChain() - E.set_input_file(self.noise_filepath) - E.append_effect_to_chain("bass", [gain, central_freq, str(q) + 'q']) - sox_output_waveform, sr = E.sox_build_flow_effects() - - output_waveform = F.bass_biquad(self.noise_waveform, self.NOISE_SAMPLE_RATE, gain, central_freq, q) - - self.assertEqual(output_waveform, sox_output_waveform, atol=1.5e-4, rtol=1e-5) + data, path = self.get_whitenoise(sample_rate) + result = F.bass_biquad(data, sample_rate, gain, central_freq, q) + self.assert_sox_effect(result, path, ['bass', gain, central_freq, f'{q}q'], atol=1.5e-4) def test_deemph(self): - """ - Test biquad deemph filter, compare to SoX implementation - """ - E = torchaudio.sox_effects.SoxEffectsChain() - E.set_input_file(self.noise_filepath) - E.append_effect_to_chain("deemph") - sox_output_waveform, sr = E.sox_build_flow_effects() - - output_waveform = F.deemph_biquad(self.noise_waveform, self.NOISE_SAMPLE_RATE) - - self.assertEqual(output_waveform, sox_output_waveform, atol=1e-4, rtol=1e-5) + sample_rate = 44100 + data, path = self.get_whitenoise(sample_rate) + result = F.deemph_biquad(data, sample_rate) + self.assert_sox_effect(result, path, ['deemph']) def test_riaa(self): - """ - Test biquad riaa filter, compare to SoX implementation - """ - E = torchaudio.sox_effects.SoxEffectsChain() - E.set_input_file(self.noise_filepath) - E.append_effect_to_chain("riaa") - sox_output_waveform, sr = E.sox_build_flow_effects() - - output_waveform = F.riaa_biquad(self.noise_waveform, self.NOISE_SAMPLE_RATE) - - self.assertEqual(output_waveform, sox_output_waveform, atol=1e-4, rtol=1e-5) + sample_rate = 44100 + data, path = self.get_whitenoise(sample_rate) + result = F.riaa_biquad(data, sample_rate) + self.assert_sox_effect(result, path, ['riaa']) def test_contrast(self): - """ - Test contrast effect, compare to SoX implementation - """ enhancement_amount = 80. - E = torchaudio.sox_effects.SoxEffectsChain() - E.set_input_file(self.noise_filepath) - E.append_effect_to_chain("contrast", [enhancement_amount]) - sox_output_waveform, sr = E.sox_build_flow_effects() - - output_waveform = F.contrast(self.noise_waveform, enhancement_amount) - - self.assertEqual(output_waveform, sox_output_waveform, atol=1e-4, rtol=1e-5) + data, path = self.get_whitenoise() + result = F.contrast(data, enhancement_amount) + self.assert_sox_effect(result, path, ['contrast', enhancement_amount]) def test_dcshift_with_limiter(self): - """ - Test dcshift effect, compare to SoX implementation - """ shift = 0.5 limiter_gain = 0.05 - E = torchaudio.sox_effects.SoxEffectsChain() - E.set_input_file(self.noise_filepath) - E.append_effect_to_chain("dcshift", [shift, limiter_gain]) - sox_output_waveform, sr = E.sox_build_flow_effects() - - output_waveform = F.dcshift(self.noise_waveform, shift, limiter_gain) - - self.assertEqual(output_waveform, sox_output_waveform, atol=1e-4, rtol=1e-5) + data, path = self.get_whitenoise() + result = F.dcshift(data, shift, limiter_gain) + self.assert_sox_effect(result, path, ['dcshift', shift, limiter_gain]) def test_dcshift_without_limiter(self): - """ - Test dcshift effect, compare to SoX implementation - """ shift = 0.6 - E = torchaudio.sox_effects.SoxEffectsChain() - E.set_input_file(self.noise_filepath) - E.append_effect_to_chain("dcshift", [shift]) - sox_output_waveform, sr = E.sox_build_flow_effects() - - output_waveform = F.dcshift(self.noise_waveform, shift) - - self.assertEqual(output_waveform, sox_output_waveform, atol=1e-4, rtol=1e-5) + data, path = self.get_whitenoise() + result = F.dcshift(data, shift) + self.assert_sox_effect(result, path, ['dcshift', shift]) def test_overdrive(self): - """ - Test overdrive effect, compare to SoX implementation - """ gain = 30 colour = 40 - E = torchaudio.sox_effects.SoxEffectsChain() - E.set_input_file(self.noise_filepath) - E.append_effect_to_chain("overdrive", [gain, colour]) - sox_output_waveform, sr = E.sox_build_flow_effects() - - output_waveform = F.overdrive(self.noise_waveform, gain, colour) - - self.assertEqual(output_waveform, sox_output_waveform, atol=1e-4, rtol=1e-5) + data, path = self.get_whitenoise() + result = F.overdrive(data, gain, colour) + self.assert_sox_effect(result, path, ['overdrive', gain, colour]) def test_phaser_sine(self): - """ - Test phaser effect with sine moduldation, compare to SoX implementation - """ gain_in = 0.5 gain_out = 0.8 delay_ms = 2.0 decay = 0.4 speed = 0.5 + sample_rate = 8000 - E = torchaudio.sox_effects.SoxEffectsChain() - E.set_input_file(self.noise_filepath) - E.append_effect_to_chain("phaser", [gain_in, gain_out, delay_ms, decay, speed, "-s"]) - sox_output_waveform, sr = E.sox_build_flow_effects() - - output_waveform = F.phaser(self.noise_waveform, self.NOISE_SAMPLE_RATE, - gain_in, gain_out, delay_ms, decay, speed, sinusoidal=True) - - self.assertEqual(output_waveform, sox_output_waveform, atol=1e-4, rtol=1e-5) + data, path = self.get_whitenoise(sample_rate) + result = F.phaser(data, sample_rate, gain_in, gain_out, delay_ms, decay, speed, sinusoidal=True) + self.assert_sox_effect(result, path, ['phaser', gain_in, gain_out, delay_ms, decay, speed, '-s']) def test_phaser_triangle(self): - """ - Test phaser effect with triangle modulation, compare to SoX implementation - """ gain_in = 0.5 gain_out = 0.8 delay_ms = 2.0 decay = 0.4 speed = 0.5 + sample_rate = 8000 - E = torchaudio.sox_effects.SoxEffectsChain() - E.set_input_file(self.noise_filepath) - E.append_effect_to_chain("phaser", [gain_in, gain_out, delay_ms, decay, speed, "-t"]) - sox_output_waveform, sr = E.sox_build_flow_effects() - - output_waveform = F.phaser(self.noise_waveform, self.NOISE_SAMPLE_RATE, - gain_in, gain_out, delay_ms, decay, speed, sinusoidal=False) - - self.assertEqual(output_waveform, sox_output_waveform, atol=1e-4, rtol=1e-5) + data, path = self.get_whitenoise(sample_rate) + result = F.phaser(data, sample_rate, gain_in, gain_out, delay_ms, decay, speed, sinusoidal=False) + self.assert_sox_effect(result, path, ['phaser', gain_in, gain_out, delay_ms, decay, speed, '-t']) def test_flanger_triangle_linear(self): - """ - Test flanger effect with triangle modulation and linear interpolation, compare to SoX implementation - """ delay = 0.6 depth = 0.87 regen = 3.0 width = 0.9 speed = 0.5 phase = 30 + sample_rate = 8000 - E = torchaudio.sox_effects.SoxEffectsChain() - E.set_input_file(self.noise_filepath) - E.append_effect_to_chain("flanger", [delay, depth, regen, width, speed, "triangle", phase, "linear"]) - sox_output_waveform, sr = E.sox_build_flow_effects() - - output_waveform = F.flanger(self.noise_waveform, self.NOISE_SAMPLE_RATE, delay, depth, regen, - width, speed, phase, modulation='triangular', interpolation='linear') - - torch.testing.assert_allclose(output_waveform, sox_output_waveform, atol=1e-4, rtol=1e-5) + data, path = self.get_whitenoise(sample_rate) + result = F.flanger( + data, sample_rate, delay, depth, regen, width, speed, phase, + modulation='triangular', interpolation='linear') + self.assert_sox_effect( + result, path, ['flanger', delay, depth, regen, width, speed, 'triangle', phase, 'linear']) def test_flanger_triangle_quad(self): - """ - Test flanger effect with triangle modulation and quadratic interpolation, compare to SoX implementation - """ delay = 0.8 depth = 0.88 regen = 3.0 width = 0.4 speed = 0.5 phase = 40 + sample_rate = 8000 - E = torchaudio.sox_effects.SoxEffectsChain() - E.set_input_file(self.noise_filepath) - E.append_effect_to_chain("flanger", [delay, depth, regen, width, speed, "triangle", phase, "quadratic"]) - sox_output_waveform, sr = E.sox_build_flow_effects() - - output_waveform = F.flanger(self.noise_waveform, self.NOISE_SAMPLE_RATE, delay, depth, - regen, width, speed, phase, modulation='triangular', interpolation='quadratic') - - torch.testing.assert_allclose(output_waveform, sox_output_waveform, atol=1e-4, rtol=1e-5) + data, path = self.get_whitenoise(sample_rate) + result = F.flanger( + data, sample_rate, delay, depth, regen, width, speed, phase, + modulation='triangular', interpolation='quadratic') + self.assert_sox_effect( + result, path, ['flanger', delay, depth, regen, width, speed, 'triangle', phase, 'quadratic']) def test_flanger_sine_linear(self): - """ - Test flanger effect with sine modulation and linear interpolation, compare to SoX implementation - """ delay = 0.8 depth = 0.88 regen = 3.0 width = 0.23 speed = 1.3 phase = 60 + sample_rate = 8000 - E = torchaudio.sox_effects.SoxEffectsChain() - E.set_input_file(self.noise_filepath) - E.append_effect_to_chain("flanger", [delay, depth, regen, width, speed, "sine", phase, "linear"]) - sox_output_waveform, sr = E.sox_build_flow_effects() - - output_waveform = F.flanger(self.noise_waveform, self.NOISE_SAMPLE_RATE, delay, depth, - regen, width, speed, phase, modulation='sinusoidal', interpolation='linear') - - torch.testing.assert_allclose(output_waveform, sox_output_waveform, atol=1e-4, rtol=1e-5) + data, path = self.get_whitenoise(sample_rate) + result = F.flanger( + data, sample_rate, delay, depth, regen, width, speed, phase, + modulation='sinusoidal', interpolation='linear') + self.assert_sox_effect( + result, path, ['flanger', delay, depth, regen, width, speed, 'sine', phase, 'linear']) def test_flanger_sine_quad(self): - """ - Test flanger effect with sine modulation and quadratic interpolation, compare to SoX implementation - """ delay = 0.9 depth = 0.9 regen = 4.0 width = 0.23 speed = 1.3 phase = 25 + sample_rate = 8000 - E = torchaudio.sox_effects.SoxEffectsChain() - E.set_input_file(self.noise_filepath) - E.append_effect_to_chain("flanger", [delay, depth, regen, width, speed, "sine", phase, "quadratic"]) - sox_output_waveform, sr = E.sox_build_flow_effects() - - output_waveform = F.flanger(self.noise_waveform, self.NOISE_SAMPLE_RATE, delay, depth, - regen, width, speed, phase, modulation='sinusoidal', interpolation='quadratic') - - torch.testing.assert_allclose(output_waveform, sox_output_waveform, atol=1e-4, rtol=1e-5) + data, path = self.get_whitenoise(sample_rate) + result = F.flanger( + data, sample_rate, delay, depth, regen, width, speed, phase, + modulation='sinusoidal', interpolation='quadratic') + self.assert_sox_effect( + result, path, ['flanger', delay, depth, regen, width, speed, 'sine', phase, 'quadratic']) def test_equalizer(self): - """ - Test biquad peaking equalizer filter, compare to SoX implementation - """ - center_freq = 300 q = 0.707 gain = 1 + sample_rate = 8000 - E = torchaudio.sox_effects.SoxEffectsChain() - E.set_input_file(self.noise_filepath) - E.append_effect_to_chain("equalizer", [center_freq, q, gain]) - sox_output_waveform, sr = E.sox_build_flow_effects() - - output_waveform = F.equalizer_biquad(self.noise_waveform, self.NOISE_SAMPLE_RATE, center_freq, gain, q) - - self.assertEqual(output_waveform, sox_output_waveform, atol=1e-4, rtol=1e-5) + data, path = self.get_whitenoise(sample_rate) + result = F.equalizer_biquad(data, sample_rate, center_freq, gain, q) + self.assert_sox_effect(result, path, ['equalizer', center_freq, q, gain]) def test_perf_biquad_filtering(self): - b0 = 0.4 b1 = 0.2 b2 = 0.9 @@ -494,18 +298,34 @@ def test_perf_biquad_filtering(self): a1 = 0.2 a2 = 0.6 - # SoX method - E = torchaudio.sox_effects.SoxEffectsChain() - E.set_input_file(self.noise_filepath) - E.append_effect_to_chain("biquad", [b0, b1, b2, a0, a1, a2]) - waveform_sox_out, _ = E.sox_build_flow_effects() - - waveform_lfilter_out = F.lfilter( - self.noise_waveform, torch.tensor([a0, a1, a2]), torch.tensor([b0, b1, b2]) - ) - - self.assertEqual(waveform_lfilter_out, waveform_sox_out, atol=1e-4, rtol=1e-5) - - -if __name__ == "__main__": - unittest.main() + data, path = self.get_whitenoise() + result = F.lfilter(data, torch.tensor([a0, a1, a2]), torch.tensor([b0, b1, b2])) + self.assert_sox_effect(result, path, ['biquad', b0, b1, b2, a0, a1, a2]) + + @parameterized.expand([ + ('q', 'quarter_sine'), + ('h', 'half_sine'), + ('t', 'linear'), + ]) + def test_fade(self, fade_shape_sox, fade_shape): + fade_in_len, fade_out_len = 44100, 44100 + data, path = self.get_whitenoise(sample_rate=44100) + result = T.Fade(fade_in_len, fade_out_len, fade_shape)(data) + self.assert_sox_effect(result, path, ['fade', fade_shape_sox, '1', '0', '1']) + + @parameterized.expand([ + ('amplitude', 1.1), + ('db', 2), + ('power', 2), + ]) + def test_vol(self, gain_type, gain): + data, path = self.get_whitenoise() + result = T.Vol(gain, gain_type)(data) + self.assert_sox_effect(result, path, ['vol', f'{gain}', gain_type]) + + @parameterized.expand(['vad-go-stereo-44100.wav', 'vad-go-mono-32000.wav']) + def test_vad(self, filename): + path = get_asset_path(filename) + data, sample_rate = load_wav(path) + result = T.Vad(sample_rate)(data) + self.assert_sox_effect(result, path, ['vad']) diff --git a/test/test_transforms.py b/test/test_transforms.py index 6df9562bc8..f6942e18a5 100644 --- a/test/test_transforms.py +++ b/test/test_transforms.py @@ -219,7 +219,3 @@ def test_compute_deltas_twochannel(self): computed = transform(specgram) assert computed.shape == expected.shape, (computed.shape, expected.shape) self.assertEqual(computed, expected, atol=1e-6, rtol=1e-8) - - -if __name__ == '__main__': - unittest.main() diff --git a/test/utils/__init__.py b/test/utils/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/test/utils/test_sox_utils.py b/test/utils/test_sox_utils.py new file mode 100644 index 0000000000..55a46a235e --- /dev/null +++ b/test/utils/test_sox_utils.py @@ -0,0 +1,49 @@ +from torchaudio.utils import sox_utils + +from ..common_utils import ( + PytorchTestCase, + skipIfNoExtension, +) + + +@skipIfNoExtension +class TestSoxUtils(PytorchTestCase): + """Smoke tests for sox_util module""" + def test_set_seed(self): + """`set_seed` does not crush""" + sox_utils.set_seed(0) + + def test_set_verbosity(self): + """`set_verbosity` does not crush""" + for val in range(6, 0, -1): + sox_utils.set_verbosity(val) + + def test_set_buffer_size(self): + """`set_buffer_size` does not crush""" + sox_utils.set_buffer_size(131072) + # back to default + sox_utils.set_buffer_size(8192) + + def test_set_use_threads(self): + """`set_use_threads` does not crush""" + sox_utils.set_use_threads(True) + # back to default + sox_utils.set_use_threads(False) + + def test_list_effects(self): + """`list_effects` returns the list of available effects""" + effects = sox_utils.list_effects() + # We cannot infer what effects are available, so only check some of them. + assert 'highpass' in effects + assert 'phaser' in effects + assert 'gain' in effects + + def test_list_read_formats(self): + """`list_read_formats` returns the list of supported formats""" + formats = sox_utils.list_read_formats() + assert 'wav' in formats + + def test_list_write_formats(self): + """`list_write_formats` returns the list of supported formats""" + formats = sox_utils.list_write_formats() + assert 'opus' not in formats diff --git a/torchaudio/__init__.py b/torchaudio/__init__.py index 16419ff3ff..9a6a5e3c16 100644 --- a/torchaudio/__init__.py +++ b/torchaudio/__init__.py @@ -4,6 +4,7 @@ compliance, datasets, kaldi_io, + utils, sox_effects, transforms ) @@ -34,10 +35,10 @@ @_mod_utils.deprecated( "Please remove the function call to initialize_sox. " "Resource initialization is now automatically handled.") -def initialize_sox() -> int: +def initialize_sox(): """Initialize sox effects. - This function is deprecated. See ``torchaudio.sox_effects.init_sox_effects`` + This function is deprecated. See :py:func:`torchaudio.sox_effects.init_sox_effects` """ _init_sox_effects() @@ -50,6 +51,6 @@ def initialize_sox() -> int: def shutdown_sox(): """Shutdown sox effects. - This function is deprecated. See ``torchaudio.sox_effects.shutdown_sox_effects`` + This function is deprecated. See :py:func:`torchaudio.sox_effects.shutdown_sox_effects` """ _shutdown_sox_effects() diff --git a/torchaudio/_internal/module_utils.py b/torchaudio/_internal/module_utils.py index 575a76c1ed..31bc2f1a31 100644 --- a/torchaudio/_internal/module_utils.py +++ b/torchaudio/_internal/module_utils.py @@ -48,7 +48,7 @@ def decorator(func): def wrapped(*args, **kwargs): message = ( f'{func.__module__}.{func.__name__} has been deprecated ' - f'and will be removed from {"future" if version is None else version} release.' + f'and will be removed from {"future" if version is None else version} release. ' f'{direction}') warnings.warn(message, stacklevel=2) return func(*args, **kwargs) diff --git a/torchaudio/backend/common.py b/torchaudio/backend/common.py index 0593c34bd5..bc61df4746 100644 --- a/torchaudio/backend/common.py +++ b/torchaudio/backend/common.py @@ -2,6 +2,18 @@ class SignalInfo: + """Data class returned ``info`` functions. + + Used by :ref:`sox backend` and :ref:`soundfile backend` + + See https://fossies.org/dox/sox-14.4.2/structsox__signalinfo__t.html + + :ivar Optional[int] channels: The number of channels + :ivar Optional[float] rate: Sampleing rate + :ivar Optional[int] precision: Bit depth + :ivar Optional[int] length: For :ref:`sox backend`, the number of samples. + (frames * channels). For :ref:`soundfile backend`, the number of frames. + """ def __init__(self, channels: Optional[int] = None, rate: Optional[float] = None, @@ -14,6 +26,20 @@ def __init__(self, class EncodingInfo: + """Data class returned ``info`` functions. + + Used by :ref:`sox backend` and :ref:`soundfile backend` + + See https://fossies.org/dox/sox-14.4.2/structsox__encodinginfo__t.html + + :ivar Optional[int] encoding: sox_encoding_t + :ivar Optional[int] bits_per_sample: bit depth + :ivar Optional[float] compression: Compression option + :ivar Any reverse_bytes: + :ivar Any reverse_nibbles: + :ivar Any reverse_bits: + :ivar Optional[bool] opposite_endian: + """ def __init__(self, encoding: Any = None, bits_per_sample: Optional[int] = None, diff --git a/torchaudio/backend/sox_io_backend.py b/torchaudio/backend/sox_io_backend.py index 4664f733c6..57d8db7723 100644 --- a/torchaudio/backend/sox_io_backend.py +++ b/torchaudio/backend/sox_io_backend.py @@ -7,6 +7,12 @@ class AudioMetaData: + """Data class to be returned by :py:func:`~torchaudio.backend.sox_io_backend.info`. + + :ivar int sample_rate: Sample rate + :ivar int num_frames: The number of frames + :ivar int num_channels: The number of channels + """ def __init__(self, sample_rate: int, num_frames: int, num_channels: int): self.sample_rate = sample_rate self.num_frames = num_frames @@ -15,7 +21,14 @@ def __init__(self, sample_rate: int, num_frames: int, num_channels: int): @_mod_utils.requires_module('torchaudio._torchaudio') def info(filepath: str) -> AudioMetaData: - """Get signal information of an audio file.""" + """Get signal information of an audio file. + + Args: + filepath (str): Path to audio file + + Returns: + AudioMetaData: meta data of the given audio. + """ sinfo = torch.ops.torchaudio.sox_io_get_info(filepath) return AudioMetaData(sinfo.get_sample_rate(), sinfo.get_num_frames(), sinfo.get_num_channels()) @@ -30,21 +43,28 @@ def load( ) -> Tuple[torch.Tensor, int]: """Load audio data from file. - This function can handle all the codecs that underlying libsox can handle, however note the - followings. - Note: - This function is tested on the following formats; - - WAV - - 32-bit floating-point - - 32-bit signed integer - - 16-bit signed integer - - 8-bit unsigned integer - - MP3 - - FLAC - - OGG/VORBIS - - By default, this function returns Tensor with ``float32`` dtype and the shape of ``[channel, time]``. + This function can handle all the codecs that underlying libsox can handle, + however it is tested on the following formats; + + * WAV + + * 32-bit floating-point + * 32-bit signed integer + * 16-bit signed integer + * 8-bit unsigned integer + + * MP3 + * FLAC + * OGG/VORBIS + * OPUS + + To load ``MP3``, ``FLAC``, ``OGG/VORBIS``, ``OPUS`` and other codecs ``libsox`` does not + handle natively, your installation of ``torchaudio`` has to be linked to ``libsox`` + and corresponding codec libraries such as ``libmad`` or ``libmp3lame`` etc. + + By default (``normalize=True``, ``channels_first=True``), this function returns Tensor with + ``float32`` dtype and the shape of ``[channel, time]``. The samples are normalized to fit in the range of ``[-1.0, 1.0]``. When the input format is WAV with integer type, such as 32-bit signed integer, 16-bit @@ -54,24 +74,33 @@ def load( for 32-bit signed PCM, ``int16`` for 16-bit signed PCM and ``uint8`` for 8-bit unsigned PCM. ``normalize`` parameter has no effect on 32-bit floating-point WAV and other formats, such as - flac and mp3. For these formats, this function always returns ``float32`` Tensor with values - normalized to ``[-1.0, 1.0]``. + ``flac`` and ``mp3``. + For these formats, this function always returns ``float32`` Tensor with values normalized to + ``[-1.0, 1.0]``. Args: - filepath: Path to audio file - frame_offset: Number of frames to skip before start reading data. - num_frames: Maximum number of frames to read. -1 reads all the remaining samples, starting - from ``frame_offset``. This function may return the less number of frames if there is - not enough frames in the given file. - normalize: When ``True``, this function always return ``float32``, and sample values are - normalized to ``[-1.0, 1.0]``. If input file is integer WAV, giving ``False`` will change - the resulting Tensor type to integer type. This argument has no effect for formats other - than integer WAV type. - channels_first: When True, the returned Tensor has dimension ``[channel, time]``. + filepath (str): + Path to audio file + frame_offset (int): + Number of frames to skip before start reading data. + num_frames (int): + Maximum number of frames to read. ``-1`` reads all the remaining samples, + starting from ``frame_offset``. + This function may return the less number of frames if there is not enough + frames in the given file. + normalize (bool): + When ``True``, this function always return ``float32``, and sample values are + normalized to ``[-1.0, 1.0]``. + If input file is integer WAV, giving ``False`` will change the resulting Tensor type to + integer type. + This argument has no effect for formats other than integer WAV type. + channels_first (bool): + When True, the returned Tensor has dimension ``[channel, time]``. Otherwise, the returned Tensor's dimension is ``[time, channel]``. Returns: - torch.Tensor: If the input file has integer wav format and normalization is off, then it has + torch.Tensor: + If the input file has integer wav format and normalization is off, then it has integer type, else ``float32`` type. If ``channels_first=True``, it has ``[channel, time]`` else ``[time, channel]``. """ @@ -83,37 +112,49 @@ def load( @_mod_utils.requires_module('torchaudio._torchaudio') def save( filepath: str, - tensor: torch.Tensor, + src: torch.Tensor, sample_rate: int, channels_first: bool = True, compression: Optional[float] = None, ): """Save audio data to file. - Supported formats are; - - WAV - - 32-bit floating-point - - 32-bit signed integer - - 16-bit signed integer - - 8-bit unsigned integer - - MP3 - - FLAC - - OGG/VORBIS + Note: + Supported formats are; + + * WAV + + * 32-bit floating-point + * 32-bit signed integer + * 16-bit signed integer + * 8-bit unsigned integer + + * MP3 + * FLAC + * OGG/VORBIS + + To save ``MP3``, ``FLAC``, ``OGG/VORBIS``, and other codecs ``libsox`` does not + handle natively, your installation of ``torchaudio`` has to be linked to ``libsox`` + and corresponding codec libraries such as ``libmad`` or ``libmp3lame`` etc. Args: - filepath: Path to save file. - tensor: Audio data to save. must be 2D tensor. - sample_rate: sampling rate - channels_first: If True, the given tensor is interpreted as ``[channel, time]``. - compression: Used for formats other than WAV. This corresponds to ``-C`` option - of ``sox`` command. + filepath (str): Path to save file. + tensor (torch.Tensor): Audio data to save. must be 2D tensor. + sample_rate (int): sampling rate + channels_first (bool): + If ``True``, the given tensor is interpreted as ``[channel, time]``, + otherwise ``[time, channel]``. + compression (Optional[float]): + Used for formats other than WAV. This corresponds to ``-C`` option of ``sox`` command. + + * | ``MP3``: Either bitrate (in ``kbps``) with quality factor, such as ``128.2``, or + | VBR encoding with quality factor such as ``-4.2``. Default: ``-4.5``. + * | ``FLAC``: compression level. Whole number from ``0`` to ``8``. + | ``8`` is default and highest compression. + * | ``OGG/VORBIS``: number from ``-1`` to ``10``; ``-1`` is the highest compression + | and lowest quality. Default: ``3``. + See the detail at http://sox.sourceforge.net/soxformat.html. - - MP3: Either bitrate [kbps] with quality factor, such as ``128.2`` or - VBR encoding with quality factor such as ``-4.2``. Default: ``-4.5`` - - FLAC: compression level. Whole number from ``0`` to ``8``. - ``8`` is default and highest compression. - - OGG/VORBIS: number from -1 to 10; -1 is the highest compression and lowest - quality. Default: ``3``. """ if compression is None: ext = str(filepath)[-3:].lower() @@ -127,8 +168,22 @@ def save( compression = 3. else: raise RuntimeError(f'Unsupported file type: "{ext}"') - signal = torch.classes.torchaudio.TensorSignal(tensor, sample_rate, channels_first) + signal = torch.classes.torchaudio.TensorSignal(src, sample_rate, channels_first) torch.ops.torchaudio.sox_io_save_audio_file(filepath, signal, compression) -load_wav = load +@_mod_utils.requires_module('torchaudio._torchaudio') +def load_wav( + filepath: str, + frame_offset: int = 0, + num_frames: int = -1, + channels_first: bool = True, +) -> Tuple[torch.Tensor, int]: + """Load wave file. + + + This function is defined only for the purpose of compatibility against other backend + for simple usecases, such as ``torchaudio.load_wav(filepath)``. + The implementation is same as :py:func:`load`. + """ + return load(filepath, frame_offset, num_frames, normalize=False, channels_first=channels_first) diff --git a/torchaudio/backend/utils.py b/torchaudio/backend/utils.py index cb53b3e02f..84ec2fa3f5 100644 --- a/torchaudio/backend/utils.py +++ b/torchaudio/backend/utils.py @@ -19,7 +19,11 @@ def list_audio_backends() -> List[str]: - """List available backends""" + """List available backends + + Returns: + List[str]: The list of available backends. + """ backends = [] if is_module_available('soundfile'): backends.append('soundfile') @@ -29,12 +33,13 @@ def list_audio_backends() -> List[str]: return backends -def set_audio_backend(backend: Optional[str]) -> None: +def set_audio_backend(backend: Optional[str]): """Set the backend for I/O operation Args: - backend (str): Name of the backend. One of "sox" or "soundfile", - based on availability of the system. + backend (Optional[str]): Name of the backend. + One of ``"sox"``, ``"sox_io"`` or ``"soundfile"`` based on availability + of the system. If ``None`` is provided the current backend is unassigned. """ if backend is not None and backend not in list_audio_backends(): raise RuntimeError( @@ -68,7 +73,11 @@ def _init_audio_backend(): def get_audio_backend() -> Optional[str]: - """Get the name of the current backend""" + """Get the name of the current backend + + Returns: + Optional[str]: The name of the current backend or ``None`` if no backend is assigned. + """ if torchaudio.load == no_backend.load: return None if torchaudio.load == sox_backend.load: diff --git a/torchaudio/csrc/register.cpp b/torchaudio/csrc/register.cpp index 3c03232941..476dcc3ebb 100644 --- a/torchaudio/csrc/register.cpp +++ b/torchaudio/csrc/register.cpp @@ -18,6 +18,20 @@ static auto registerTensorSignal = .def("get_sample_rate", &sox_utils::TensorSignal::getSampleRate) .def("get_channels_first", &sox_utils::TensorSignal::getChannelsFirst); +static auto registerSetSoxOptions = + torch::RegisterOperators() + .op("torchaudio::sox_utils_set_seed", &sox_utils::set_seed) + .op("torchaudio::sox_utils_set_verbosity", &sox_utils::set_verbosity) + .op("torchaudio::sox_utils_set_use_threads", + &sox_utils::set_use_threads) + .op("torchaudio::sox_utils_set_buffer_size", + &sox_utils::set_buffer_size) + .op("torchaudio::sox_utils_list_effects", &sox_utils::list_effects) + .op("torchaudio::sox_utils_list_read_formats", + &sox_utils::list_read_formats) + .op("torchaudio::sox_utils_list_write_formats", + &sox_utils::list_write_formats); + //////////////////////////////////////////////////////////////////////////////// // sox_io.h //////////////////////////////////////////////////////////////////////////////// @@ -53,12 +67,23 @@ static auto registerSaveAudioFile = torch::RegisterOperators().op( // sox_effects.h //////////////////////////////////////////////////////////////////////////////// static auto registerSoxEffects = - torch::RegisterOperators( - "torchaudio::sox_effects_initialize_sox_effects", - &sox_effects::initialize_sox_effects) + torch::RegisterOperators() + .op("torchaudio::sox_effects_initialize_sox_effects", + &sox_effects::initialize_sox_effects) .op("torchaudio::sox_effects_shutdown_sox_effects", &sox_effects::shutdown_sox_effects) - .op("torchaudio::sox_effects_list_effects", &sox_effects::list_effects); + .op(torch::RegisterOperators::options() + .schema( + "torchaudio::sox_effects_apply_effects_tensor(__torch__.torch.classes.torchaudio.TensorSignal input_signal, str[][] effects) -> __torch__.torch.classes.torchaudio.TensorSignal output_signal") + .catchAllKernel< + decltype(sox_effects::apply_effects_tensor), + &sox_effects::apply_effects_tensor>()) + .op(torch::RegisterOperators::options() + .schema( + "torchaudio::sox_effects_apply_effects_file(str path, str[][] effects, bool normalize, bool channels_first) -> __torch__.torch.classes.torchaudio.TensorSignal output_signal") + .catchAllKernel< + decltype(sox_effects::apply_effects_file), + &sox_effects::apply_effects_file>()); } // namespace } // namespace torchaudio diff --git a/torchaudio/csrc/sox_effects.cpp b/torchaudio/csrc/sox_effects.cpp index 9a0c2ddc6f..8a7cc7c494 100644 --- a/torchaudio/csrc/sox_effects.cpp +++ b/torchaudio/csrc/sox_effects.cpp @@ -1,7 +1,9 @@ #include #include +#include +#include -using namespace torch::indexing; +using namespace torchaudio::sox_utils; namespace torchaudio { namespace sox_effects { @@ -10,44 +12,125 @@ namespace { enum SoxEffectsResourceState { NotInitialized, Initialized, ShutDown }; SoxEffectsResourceState SOX_RESOURCE_STATE = NotInitialized; +std::mutex SOX_RESOUCE_STATE_MUTEX; } // namespace void initialize_sox_effects() { - if (SOX_RESOURCE_STATE == ShutDown) { - throw std::runtime_error( - "SoX Effects has been shut down. Cannot initialize again."); - } - if (SOX_RESOURCE_STATE == NotInitialized) { - if (sox_init() != SOX_SUCCESS) { - throw std::runtime_error("Failed to initialize sox effects."); - }; - SOX_RESOURCE_STATE = Initialized; + const std::lock_guard lock(SOX_RESOUCE_STATE_MUTEX); + + switch (SOX_RESOURCE_STATE) { + case NotInitialized: + if (sox_init() != SOX_SUCCESS) { + throw std::runtime_error("Failed to initialize sox effects."); + }; + SOX_RESOURCE_STATE = Initialized; + case Initialized: + break; + case ShutDown: + throw std::runtime_error( + "SoX Effects has been shut down. Cannot initialize again."); } }; void shutdown_sox_effects() { - if (SOX_RESOURCE_STATE == NotInitialized) { - throw std::runtime_error( - "SoX Effects is not initialized. Cannot shutdown."); + const std::lock_guard lock(SOX_RESOUCE_STATE_MUTEX); + + switch (SOX_RESOURCE_STATE) { + case NotInitialized: + throw std::runtime_error( + "SoX Effects is not initialized. Cannot shutdown."); + case Initialized: + if (sox_quit() != SOX_SUCCESS) { + throw std::runtime_error("Failed to initialize sox effects."); + }; + SOX_RESOURCE_STATE = ShutDown; + case ShutDown: + break; } - if (SOX_RESOURCE_STATE == Initialized) { - if (sox_quit() != SOX_SUCCESS) { - throw std::runtime_error("Failed to initialize sox effects."); - }; - SOX_RESOURCE_STATE = ShutDown; +} + +c10::intrusive_ptr apply_effects_tensor( + const c10::intrusive_ptr& input_signal, + std::vector> effects) { + auto in_tensor = input_signal->getTensor(); + validate_input_tensor(in_tensor); + + // Create SoxEffectsChain + const auto dtype = in_tensor.dtype(); + torchaudio::sox_effects_chain::SoxEffectsChain chain( + /*input_encoding=*/get_encodinginfo("wav", dtype, 0.), + /*output_encoding=*/get_encodinginfo("wav", dtype, 0.)); + + // Prepare output buffer + std::vector out_buffer; + out_buffer.reserve(in_tensor.numel()); + + // Build and run effects chain + chain.addInputTensor(input_signal.get()); + for (const auto& effect : effects) { + chain.addEffect(effect); } + chain.addOutputBuffer(&out_buffer); + chain.run(); + + // Create tensor from buffer + const auto channels_first = input_signal->getChannelsFirst(); + auto out_tensor = convert_to_tensor( + /*buffer=*/out_buffer.data(), + /*num_samples=*/out_buffer.size(), + /*num_channels=*/chain.getOutputNumChannels(), + dtype, + /*noramlize=*/false, + channels_first); + + return c10::make_intrusive( + out_tensor, chain.getOutputSampleRate(), channels_first); } -std::vector list_effects() { - std::vector names; - const sox_effect_fn_t* fns = sox_get_effect_fns(); - for (int i = 0; fns[i]; ++i) { - const sox_effect_handler_t* handler = fns[i](); - if (handler && handler->name) - names.push_back(handler->name); +c10::intrusive_ptr apply_effects_file( + const std::string path, + std::vector> effects, + const bool normalize, + const bool channels_first) { + // Open input file + SoxFormat sf(sox_open_read( + path.c_str(), + /*signal=*/nullptr, + /*encoding=*/nullptr, + /*filetype=*/nullptr)); + + validate_input_file(sf); + + const auto dtype = get_dtype(sf->encoding.encoding, sf->signal.precision); + + // Prepare output + std::vector out_buffer; + out_buffer.reserve(sf->signal.length); + + // Create and run SoxEffectsChain + torchaudio::sox_effects_chain::SoxEffectsChain chain( + /*input_encoding=*/sf->encoding, + /*output_encoding=*/get_encodinginfo("wav", dtype, 0.)); + + chain.addInputFile(sf); + for (const auto& effect : effects) { + chain.addEffect(effect); } - return names; + chain.addOutputBuffer(&out_buffer); + chain.run(); + + // Create tensor from buffer + auto tensor = convert_to_tensor( + /*buffer=*/out_buffer.data(), + /*num_samples=*/out_buffer.size(), + /*num_channels=*/chain.getOutputNumChannels(), + dtype, + normalize, + channels_first); + + return c10::make_intrusive( + tensor, chain.getOutputSampleRate(), channels_first); } } // namespace sox_effects diff --git a/torchaudio/csrc/sox_effects.h b/torchaudio/csrc/sox_effects.h index 14bdbbfabc..7883a7beac 100644 --- a/torchaudio/csrc/sox_effects.h +++ b/torchaudio/csrc/sox_effects.h @@ -2,6 +2,7 @@ #define TORCHAUDIO_SOX_EFFECTS_H #include +#include namespace torchaudio { namespace sox_effects { @@ -10,7 +11,15 @@ void initialize_sox_effects(); void shutdown_sox_effects(); -std::vector list_effects(); +c10::intrusive_ptr apply_effects_tensor( + const c10::intrusive_ptr& input_signal, + std::vector> effects); + +c10::intrusive_ptr apply_effects_file( + const std::string path, + std::vector> effects, + const bool normalize = true, + const bool channels_first = true); } // namespace sox_effects } // namespace torchaudio diff --git a/torchaudio/csrc/sox_effects_chain.cpp b/torchaudio/csrc/sox_effects_chain.cpp new file mode 100644 index 0000000000..449e33be98 --- /dev/null +++ b/torchaudio/csrc/sox_effects_chain.cpp @@ -0,0 +1,287 @@ +#include +#include + +using namespace torch::indexing; +using namespace torchaudio::sox_utils; + +namespace torchaudio { +namespace sox_effects_chain { + +namespace { + +// Helper struct to safely close sox_effect_t* pointer returned by +// sox_create_effect +struct SoxEffect { + explicit SoxEffect(sox_effect_t* se) noexcept : se_(se){}; + SoxEffect(const SoxEffect& other) = delete; + SoxEffect(const SoxEffect&& other) = delete; + SoxEffect& operator=(const SoxEffect& other) = delete; + SoxEffect& operator=(SoxEffect&& other) = delete; + ~SoxEffect() { + if (se_ != nullptr) { + free(se_); + } + } + operator sox_effect_t*() const { + return se_; + }; + sox_effect_t* operator->() noexcept { + return se_; + } + + private: + sox_effect_t* se_; +}; + +/// helper classes for passing the location of input tensor and output buffer +/// +/// drain/flow callback functions require plaing C style function signature and +/// the way to pass extra data is to attach data to sox_fffect_t::priv pointer. +/// The following structs will be assigned to sox_fffect_t::priv pointer which +/// gives sox_effect_t an access to input Tensor and output buffer object. +struct TensorInputPriv { + size_t index; + TensorSignal* signal; +}; +struct TensorOutputPriv { + std::vector* buffer; +}; +struct FileOutputPriv { + sox_format_t* sf; +}; + +/// Callback function to feed Tensor data to SoxEffectChain. +int tensor_input_drain(sox_effect_t* effp, sox_sample_t* obuf, size_t* osamp) { + // Retrieve the input Tensor and current index + auto priv = static_cast(effp->priv); + auto index = priv->index; + auto signal = priv->signal; + auto tensor = signal->getTensor(); + auto num_channels = effp->out_signal.channels; + + // Adjust the number of samples to read + const size_t num_samples = tensor.numel(); + if (index + *osamp > num_samples) { + *osamp = num_samples - index; + } + // Ensure that it's a multiple of the number of channels + *osamp -= *osamp % num_channels; + + // Slice the input Tensor and unnormalize the values + const auto tensor_ = [&]() { + auto i_frame = index / num_channels; + auto num_frames = *osamp / num_channels; + auto t = (signal->getChannelsFirst()) + ? tensor.index({Slice(), Slice(i_frame, i_frame + num_frames)}).t() + : tensor.index({Slice(i_frame, i_frame + num_frames), Slice()}); + return unnormalize_wav(t.reshape({-1})).contiguous(); + }(); + priv->index += *osamp; + + // Write data to SoxEffectsChain buffer. + auto ptr = tensor_.data_ptr(); + std::copy(ptr, ptr + *osamp, obuf); + + return (priv->index == num_samples) ? SOX_EOF : SOX_SUCCESS; +} + +/// Callback function to fetch data from SoxEffectChain. +int tensor_output_flow( + sox_effect_t* effp, + sox_sample_t const* ibuf, + sox_sample_t* obuf LSX_UNUSED, + size_t* isamp, + size_t* osamp) { + *osamp = 0; + // Get output buffer + auto out_buffer = static_cast(effp->priv)->buffer; + // Append at the end + out_buffer->insert(out_buffer->end(), ibuf, ibuf + *isamp); + return SOX_SUCCESS; +} + +int file_output_flow( + sox_effect_t* effp, + sox_sample_t const* ibuf, + sox_sample_t* obuf LSX_UNUSED, + size_t* isamp, + size_t* osamp) { + *osamp = 0; + if (*isamp) { + auto sf = static_cast(effp->priv)->sf; + if (sox_write(sf, ibuf, *isamp) != *isamp) { + if (sf->sox_errno) { + std::ostringstream stream; + stream << sf->sox_errstr << " " << sox_strerror(sf->sox_errno) << " " + << sf->filename; + throw std::runtime_error(stream.str()); + } + return SOX_EOF; + } + } + return SOX_SUCCESS; +} + +sox_effect_handler_t* get_tensor_input_handler() { + static sox_effect_handler_t handler{/*name=*/"input_tensor", + /*usage=*/NULL, + /*flags=*/SOX_EFF_MCHAN, + /*getopts=*/NULL, + /*start=*/NULL, + /*flow=*/NULL, + /*drain=*/tensor_input_drain, + /*stop=*/NULL, + /*kill=*/NULL, + /*priv_size=*/sizeof(TensorInputPriv)}; + return &handler; +} + +sox_effect_handler_t* get_tensor_output_handler() { + static sox_effect_handler_t handler{/*name=*/"output_tensor", + /*usage=*/NULL, + /*flags=*/SOX_EFF_MCHAN, + /*getopts=*/NULL, + /*start=*/NULL, + /*flow=*/tensor_output_flow, + /*drain=*/NULL, + /*stop=*/NULL, + /*kill=*/NULL, + /*priv_size=*/sizeof(TensorOutputPriv)}; + return &handler; +} + +sox_effect_handler_t* get_file_output_handler() { + static sox_effect_handler_t handler{/*name=*/"output_file", + /*usage=*/NULL, + /*flags=*/SOX_EFF_MCHAN, + /*getopts=*/NULL, + /*start=*/NULL, + /*flow=*/file_output_flow, + /*drain=*/NULL, + /*stop=*/NULL, + /*kill=*/NULL, + /*priv_size=*/sizeof(FileOutputPriv)}; + return &handler; +} + +} // namespace + +SoxEffectsChain::SoxEffectsChain( + sox_encodinginfo_t input_encoding, + sox_encodinginfo_t output_encoding) + : in_enc_(input_encoding), + out_enc_(output_encoding), + in_sig_(), + interm_sig_(), + out_sig_(), + sec_(sox_create_effects_chain(&in_enc_, &out_enc_)) { + if (!sec_) { + throw std::runtime_error("Failed to create effect chain."); + } +} + +SoxEffectsChain::~SoxEffectsChain() { + if (sec_ != nullptr) { + sox_delete_effects_chain(sec_); + } +} + +void SoxEffectsChain::run() { + sox_flow_effects(sec_, NULL, NULL); +} + +void SoxEffectsChain::addInputTensor(TensorSignal* signal) { + in_sig_ = get_signalinfo(signal, "wav"); + interm_sig_ = in_sig_; + SoxEffect e(sox_create_effect(get_tensor_input_handler())); + auto priv = static_cast(e->priv); + priv->signal = signal; + priv->index = 0; + if (sox_add_effect(sec_, e, &interm_sig_, &in_sig_) != SOX_SUCCESS) { + throw std::runtime_error("Failed to add effect: input_tensor"); + } +} + +void SoxEffectsChain::addOutputBuffer( + std::vector* output_buffer) { + SoxEffect e(sox_create_effect(get_tensor_output_handler())); + static_cast(e->priv)->buffer = output_buffer; + if (sox_add_effect(sec_, e, &interm_sig_, &in_sig_) != SOX_SUCCESS) { + throw std::runtime_error("Failed to add effect: output_tensor"); + } +} + +void SoxEffectsChain::addInputFile(sox_format_t* sf) { + in_sig_ = sf->signal; + interm_sig_ = in_sig_; + SoxEffect e(sox_create_effect(sox_find_effect("input"))); + char* opts[] = {(char*)sf}; + sox_effect_options(e, 1, opts); + if (sox_add_effect(sec_, e, &interm_sig_, &in_sig_) != SOX_SUCCESS) { + std::ostringstream stream; + stream << "Failed to add effect: input " << sf->filename; + throw std::runtime_error(stream.str()); + } +} + +void SoxEffectsChain::addOutputFile(sox_format_t* sf) { + out_sig_ = sf->signal; + SoxEffect e(sox_create_effect(get_file_output_handler())); + static_cast(e->priv)->sf = sf; + if (sox_add_effect(sec_, e, &interm_sig_, &out_sig_) != SOX_SUCCESS) { + std::ostringstream stream; + stream << "Failed to add effect: output " << sf->filename; + throw std::runtime_error(stream.str()); + } +} + +void SoxEffectsChain::addEffect(const std::vector effect) { + const auto num_args = effect.size(); + if (num_args == 0) { + throw std::runtime_error("Invalid argument: empty effect."); + } + const auto name = effect[0]; + if (UNSUPPORTED_EFFECTS.find(name) != UNSUPPORTED_EFFECTS.end()) { + std::ostringstream stream; + stream << "Unsupported effect: " << name; + throw std::runtime_error(stream.str()); + } + + SoxEffect e(sox_create_effect(sox_find_effect(name.c_str()))); + const auto num_options = num_args - 1; + + std::vector opts; + for (size_t i = 1; i < num_args; ++i) { + opts.push_back((char*)effect[i].c_str()); + } + if (sox_effect_options(e, num_options, num_options ? opts.data() : nullptr) != + SOX_SUCCESS) { + std::ostringstream stream; + stream << "Invalid effect option:"; + for (const auto& v : effect) { + stream << " " << v; + } + throw std::runtime_error(stream.str()); + } + + if (sox_add_effect(sec_, e, &interm_sig_, &in_sig_) != SOX_SUCCESS) { + std::ostringstream stream; + stream << "Failed to add effect: \"" << name; + for (size_t i = 1; i < num_args; ++i) { + stream << " " << effect[i]; + } + stream << "\""; + throw std::runtime_error(stream.str()); + } +} + +int64_t SoxEffectsChain::getOutputNumChannels() { + return interm_sig_.channels; +} + +int64_t SoxEffectsChain::getOutputSampleRate() { + return interm_sig_.rate; +} + +} // namespace sox_effects_chain +} // namespace torchaudio diff --git a/torchaudio/csrc/sox_effects_chain.h b/torchaudio/csrc/sox_effects_chain.h new file mode 100644 index 0000000000..fa55182281 --- /dev/null +++ b/torchaudio/csrc/sox_effects_chain.h @@ -0,0 +1,42 @@ +#ifndef TORCHAUDIO_SOX_EFFECTS_CHAIN_H +#define TORCHAUDIO_SOX_EFFECTS_CHAIN_H + +#include +#include +#include + +namespace torchaudio { +namespace sox_effects_chain { + +// Helper struct to safely close sox_effects_chain_t with handy methods +class SoxEffectsChain { + const sox_encodinginfo_t in_enc_; + const sox_encodinginfo_t out_enc_; + sox_signalinfo_t in_sig_; + sox_signalinfo_t interm_sig_; + sox_signalinfo_t out_sig_; + sox_effects_chain_t* sec_; + + public: + explicit SoxEffectsChain( + sox_encodinginfo_t input_encoding, + sox_encodinginfo_t output_encoding); + SoxEffectsChain(const SoxEffectsChain& other) = delete; + SoxEffectsChain(const SoxEffectsChain&& other) = delete; + SoxEffectsChain& operator=(const SoxEffectsChain& other) = delete; + SoxEffectsChain& operator=(SoxEffectsChain&& other) = delete; + ~SoxEffectsChain(); + void run(); + void addInputTensor(torchaudio::sox_utils::TensorSignal* signal); + void addInputFile(sox_format_t* sf); + void addOutputBuffer(std::vector* output_buffer); + void addOutputFile(sox_format_t* sf); + void addEffect(const std::vector effect); + int64_t getOutputNumChannels(); + int64_t getOutputSampleRate(); +}; + +} // namespace sox_effects_chain +} // namespace torchaudio + +#endif diff --git a/torchaudio/csrc/sox_io.cpp b/torchaudio/csrc/sox_io.cpp index 5d308027bb..4092d215d0 100644 --- a/torchaudio/csrc/sox_io.cpp +++ b/torchaudio/csrc/sox_io.cpp @@ -1,4 +1,6 @@ #include +#include +#include #include #include @@ -60,64 +62,21 @@ c10::intrusive_ptr load_audio_file( "Invalid argument: num_frames must be -1 or greater than 0."); } - SoxFormat sf(sox_open_read( - path.c_str(), - /*signal=*/nullptr, - /*encoding=*/nullptr, - /*filetype=*/nullptr)); - - validate_input_file(sf); - - const int64_t num_channels = sf->signal.channels; - const int64_t num_total_samples = sf->signal.length; - const int64_t sample_start = sf->signal.channels * frame_offset; - - if (sox_seek(sf, sample_start, 0) == SOX_EOF) { - throw std::runtime_error("Error reading audio file: offset past EOF."); + std::vector> effects; + if (num_frames != -1) { + std::ostringstream offset, frames; + offset << frame_offset << "s"; + frames << "+" << num_frames << "s"; + effects.emplace_back( + std::vector{"trim", offset.str(), frames.str()}); + } else if (frame_offset != 0) { + std::ostringstream offset; + offset << frame_offset << "s"; + effects.emplace_back(std::vector{"trim", offset.str()}); } - const int64_t sample_end = [&]() { - if (num_frames == -1) - return num_total_samples; - const int64_t sample_end_ = num_channels * num_frames + sample_start; - if (num_total_samples < sample_end_) { - // For lossy encoding, it is difficult to predict exact size of buffer for - // reading the number of samples required. - // So we allocate buffer size of given `num_frames` and ask sox to read as - // much as possible. For lossless format, sox reads exact number of - // samples, but for lossy encoding, sox can end up reading less. (i.e. - // mp3) For the consistent behavior specification between lossy/lossless - // format, we allow users to provide `num_frames` value that exceeds #of - // available samples, and we adjust it here. - return num_total_samples; - } - return sample_end_; - }(); - - const int64_t max_samples = sample_end - sample_start; - - // Read samples into buffer - std::vector buffer; - buffer.reserve(max_samples); - const int64_t num_samples = sox_read(sf, buffer.data(), max_samples); - if (num_samples == 0) { - throw std::runtime_error( - "Error reading audio file: empty file or read operation failed."); - } - // NOTE: num_samples may be smaller than max_samples if the input - // format is compressed (i.e. mp3). - - // Convert to Tensor - auto tensor = convert_to_tensor( - buffer.data(), - num_samples, - num_channels, - get_dtype(sf->encoding.encoding, sf->signal.precision), - normalize, - channels_first); - - return c10::make_intrusive( - tensor, static_cast(sf->signal.rate), channels_first); + return torchaudio::sox_effects::apply_effects_file( + path, effects, normalize, channels_first); } void save_audio_file( @@ -125,14 +84,11 @@ void save_audio_file( const c10::intrusive_ptr& signal, const double compression) { const auto tensor = signal->getTensor(); - const auto sample_rate = signal->getSampleRate(); - const auto channels_first = signal->getChannelsFirst(); validate_input_tensor(tensor); const auto filetype = get_filetype(file_name); - const auto signal_info = - get_signalinfo(tensor, sample_rate, channels_first, filetype); + const auto signal_info = get_signalinfo(signal.get(), filetype); const auto encoding_info = get_encodinginfo(filetype, tensor.dtype(), compression); @@ -148,22 +104,12 @@ void save_audio_file( throw std::runtime_error("Error saving audio file: failed to open file."); } - auto tensor_ = tensor; - if (channels_first) { - tensor_ = tensor_.t(); - } - - const int64_t frames_per_chunk = 65536; - for (int64_t i = 0; i < tensor_.size(0); i += frames_per_chunk) { - auto chunk = tensor_.index({Slice(i, i + frames_per_chunk), Slice()}); - chunk = unnormalize_wav(chunk).contiguous(); - - const size_t numel = chunk.numel(); - if (sox_write(sf, chunk.data_ptr(), numel) != numel) { - throw std::runtime_error( - "Error saving audio file: failed to write the entier buffer."); - } - } + torchaudio::sox_effects_chain::SoxEffectsChain chain( + /*input_encoding=*/get_encodinginfo("wav", tensor.dtype(), 0.), + /*output_encoding=*/sf->encoding); + chain.addInputTensor(signal.get()); + chain.addOutputFile(sf); + chain.run(); } } // namespace sox_io diff --git a/torchaudio/csrc/sox_utils.cpp b/torchaudio/csrc/sox_utils.cpp index c1fd8383a8..c6b73c5795 100644 --- a/torchaudio/csrc/sox_utils.cpp +++ b/torchaudio/csrc/sox_utils.cpp @@ -5,6 +5,62 @@ namespace torchaudio { namespace sox_utils { +void set_seed(const int64_t seed) { + sox_get_globals()->ranqd1 = static_cast(seed); +} + +void set_verbosity(const int64_t verbosity) { + sox_get_globals()->verbosity = static_cast(verbosity); +} + +void set_use_threads(const bool use_threads) { + sox_get_globals()->use_threads = static_cast(use_threads); +} + +void set_buffer_size(const int64_t buffer_size) { + sox_get_globals()->bufsiz = static_cast(buffer_size); +} + +std::vector> list_effects() { + std::vector> effects; + for (const sox_effect_fn_t* fns = sox_get_effect_fns(); *fns; ++fns) { + const sox_effect_handler_t* handler = (*fns)(); + if (handler && handler->name) { + if (UNSUPPORTED_EFFECTS.find(handler->name) == + UNSUPPORTED_EFFECTS.end()) { + effects.emplace_back(std::vector{ + handler->name, + handler->usage ? std::string(handler->usage) : std::string("")}); + } + } + } + return effects; +} + +std::vector list_write_formats() { + std::vector formats; + for (const sox_format_tab_t* fns = sox_get_format_fns(); fns->fn; ++fns) { + const sox_format_handler_t* handler = fns->fn(); + for (const char* const* names = handler->names; *names; ++names) { + if (!strchr(*names, '/') && handler->write) + formats.emplace_back(*names); + } + } + return formats; +} + +std::vector list_read_formats() { + std::vector formats; + for (const sox_format_tab_t* fns = sox_get_format_fns(); fns->fn; ++fns) { + const sox_format_handler_t* handler = fns->fn(); + for (const char* const* names = handler->names; *names; ++names) { + if (!strchr(*names, '/') && handler->read) + formats.emplace_back(*names); + } + } + return formats; +} + TensorSignal::TensorSignal( torch::Tensor tensor_, int64_t sample_rate_, @@ -205,13 +261,13 @@ unsigned get_precision( } sox_signalinfo_t get_signalinfo( - const torch::Tensor& tensor, - const int64_t sample_rate, - const bool channels_first, + const TensorSignal* signal, const std::string filetype) { + auto tensor = signal->getTensor(); return sox_signalinfo_t{ - /*rate=*/static_cast(sample_rate), - /*channels=*/static_cast(tensor.size(channels_first ? 0 : 1)), + /*rate=*/static_cast(signal->getSampleRate()), + /*channels=*/ + static_cast(tensor.size(signal->getChannelsFirst() ? 0 : 1)), /*precision=*/get_precision(filetype, tensor.dtype()), /*length=*/static_cast(tensor.numel())}; } diff --git a/torchaudio/csrc/sox_utils.h b/torchaudio/csrc/sox_utils.h index 665187c840..c9037e9e2f 100644 --- a/torchaudio/csrc/sox_utils.h +++ b/torchaudio/csrc/sox_utils.h @@ -7,6 +7,27 @@ namespace torchaudio { namespace sox_utils { +//////////////////////////////////////////////////////////////////////////////// +// APIs for Python interaction +//////////////////////////////////////////////////////////////////////////////// + +/// Set sox global options +void set_seed(const int64_t seed); + +void set_verbosity(const int64_t verbosity); + +void set_use_threads(const bool use_threads); + +void set_buffer_size(const int64_t buffer_size); + +std::vector> list_effects(); + +std::vector list_read_formats(); + +std::vector list_write_formats(); + +/// Class for exchanging signal infomation (tensor + meta data) between +/// C++ and Python for read/write operation. struct TensorSignal : torch::CustomClassHolder { torch::Tensor tensor; int64_t sample_rate; @@ -22,6 +43,13 @@ struct TensorSignal : torch::CustomClassHolder { bool getChannelsFirst() const; }; +//////////////////////////////////////////////////////////////////////////////// +// Utilities for sox_io / sox_effects implementations +//////////////////////////////////////////////////////////////////////////////// + +const std::unordered_set UNSUPPORTED_EFFECTS = + {"input", "output", "spectrogram", "noiseprof", "noisered", "splice"}; + /// helper class to automatically close sox_format_t* struct SoxFormat { explicit SoxFormat(sox_format_t* fd) noexcept; @@ -84,9 +112,7 @@ const std::string get_filetype(const std::string path); /// Get sox_signalinfo_t for passing a torch::Tensor object. sox_signalinfo_t get_signalinfo( - const torch::Tensor& tensor, - const int64_t sample_rate, - const bool channels_first, + const TensorSignal* signal, const std::string filetype); /// Get sox_encofinginfo_t for saving audoi file diff --git a/torchaudio/datasets/__init__.py b/torchaudio/datasets/__init__.py index 942f2c83a1..187142db46 100644 --- a/torchaudio/datasets/__init__.py +++ b/torchaudio/datasets/__init__.py @@ -7,6 +7,7 @@ from .yesno import YESNO from .ljspeech import LJSPEECH from .cmuarctic import CMUARCTIC +from .libritts import LIBRITTS __all__ = ( "COMMONVOICE", @@ -17,6 +18,7 @@ "LJSPEECH", "GTZAN", "CMUARCTIC", + "LIBRITTS" "diskcache_iterator", "bg_iterator", ) diff --git a/torchaudio/datasets/gtzan.py b/torchaudio/datasets/gtzan.py index 13d7e8b68b..e031801bc1 100644 --- a/torchaudio/datasets/gtzan.py +++ b/torchaudio/datasets/gtzan.py @@ -8,7 +8,6 @@ from torchaudio.datasets.utils import ( download_url, extract_archive, - walk_files, ) # The following lists prefixed with `filtered_` provide a filtered split @@ -22,6 +21,19 @@ # Those are used when GTZAN is initialised with the `filtered` keyword. # The split was taken from (github) jordipons/sklearn-audio-transfer-learning. +gtzan_genres = [ + "blues", + "classical", + "country", + "disco", + "hiphop", + "jazz", + "metal", + "pop", + "reggae", + "rock", +] + filtered_test = [ "blues.00012", "blues.00013", @@ -964,7 +976,9 @@ URL = "http://opihi.cs.uvic.ca/sound/genres.tar.gz" FOLDER_IN_ARCHIVE = "genres" -_CHECKSUMS = {"http://opihi.cs.uvic.ca/sound/genres.tar.gz": "5b3d6dddb579ab49814ab86dba69e7c7"} +_CHECKSUMS = { + "http://opihi.cs.uvic.ca/sound/genres.tar.gz": "5b3d6dddb579ab49814ab86dba69e7c7" +} def load_gtzan_item(fileid: str, path: str, ext_audio: str) -> Tuple[Tensor, str]: @@ -1032,10 +1046,33 @@ def __init__( ) if self.subset is None: - walker = walk_files( - self._path, suffix=self._ext_audio, prefix=False, remove_suffix=True - ) - self._walker = list(walker) + # Check every subdirectory under dataset root + # which has the same name as the genres in + # GTZAN (e.g. `root_dir'/blues/, `root_dir'/rock, etc.) + # This lets users remove or move around song files, + # useful when e.g. they want to use only some of the files + # in a genre or want to label other files with a different + # genre. + self._walker = [] + + root = os.path.expanduser(self._path) + + for directory in gtzan_genres: + fulldir = os.path.join(root, directory) + + if not os.path.exists(fulldir): + continue + + songs_in_genre = os.listdir(fulldir) + songs_in_genre.sort() + for fname in songs_in_genre: + name, ext = os.path.splitext(fname) + if ext.lower() == ".wav" and "." in name: + # Check whether the file is of the form + # `gtzan_genre`.`5 digit number`.wav + genre, num = name.split(".") + if genre in gtzan_genres and len(num) == 5 and num.isdigit(): + self._walker.append(name) else: if self.subset == "training": self._walker = filtered_train diff --git a/torchaudio/datasets/libritts.py b/torchaudio/datasets/libritts.py new file mode 100644 index 0000000000..a37d5528fb --- /dev/null +++ b/torchaudio/datasets/libritts.py @@ -0,0 +1,131 @@ +import os +from typing import Tuple + +import torchaudio +from torch import Tensor +from torch.utils.data import Dataset +from torchaudio.datasets.utils import ( + download_url, + extract_archive, + walk_files, +) + +URL = "train-clean-100" +FOLDER_IN_ARCHIVE = "LibriTTS" +_CHECKSUMS = { + "http://www.openslr.org/60/dev-clean.tar.gz": "0c3076c1e5245bb3f0af7d82087ee207", + "http://www.openslr.org/60/dev-other.tar.gz": "815555d8d75995782ac3ccd7f047213d", + "http://www.openslr.org/60/test-clean.tar.gz": "7bed3bdb047c4c197f1ad3bc412db59f", + "http://www.openslr.org/60/test-other.tar.gz": "ae3258249472a13b5abef2a816f733e4", + "http://www.openslr.org/60/train-clean-100.tar.gz": "4a8c202b78fe1bc0c47916a98f3a2ea8", + "http://www.openslr.org/60/train-clean-360.tar.gz": "a84ef10ddade5fd25df69596a2767b2d", + "http://www.openslr.org/60/train-other-500.tar.gz": "7b181dd5ace343a5f38427999684aa6f", +} + + +def load_libritts_item( + fileid: str, + path: str, + ext_audio: str, + ext_original_txt: str, + ext_normalized_txt: str, +) -> Tuple[Tensor, int, str, str, int, int, str]: + speaker_id, chapter_id, segment_id, utterance_id = fileid.split("_") + utterance_id = fileid + + normalized_text = utterance_id + ext_normalized_txt + normalized_text = os.path.join(path, speaker_id, chapter_id, normalized_text) + + original_text = utterance_id + ext_original_txt + original_text = os.path.join(path, speaker_id, chapter_id, original_text) + + file_audio = utterance_id + ext_audio + file_audio = os.path.join(path, speaker_id, chapter_id, file_audio) + + # Load audio + waveform, sample_rate = torchaudio.load(file_audio) + + # Load original text + with open(original_text) as ft: + original_text = ft.readline() + + # Load normalized text + with open(normalized_text, "r") as ft: + normalized_text = ft.readline() + + return ( + waveform, + sample_rate, + original_text, + normalized_text, + int(speaker_id), + int(chapter_id), + utterance_id, + ) + + +class LIBRITTS(Dataset): + """ + Create a Dataset for LibriTTS. Each item is a tuple of the form: + waveform, sample_rate, original_text, normalized_text, speaker_id, chapter_id, utterance_id + """ + + _ext_original_txt = ".original.txt" + _ext_normalized_txt = ".normalized.txt" + _ext_audio = ".wav" + + def __init__( + self, + root: str, + url: str = URL, + folder_in_archive: str = FOLDER_IN_ARCHIVE, + download: bool = False, + ) -> None: + + if url in [ + "dev-clean", + "dev-other", + "test-clean", + "test-other", + "train-clean-100", + "train-clean-360", + "train-other-500", + ]: + + ext_archive = ".tar.gz" + base_url = "http://www.openslr.org/resources/60/" + + url = os.path.join(base_url, url + ext_archive) + + basename = os.path.basename(url) + archive = os.path.join(root, basename) + + basename = basename.split(".")[0] + folder_in_archive = os.path.join(folder_in_archive, basename) + + self._path = os.path.join(root, folder_in_archive) + + if download: + if not os.path.isdir(self._path): + if not os.path.isfile(archive): + checksum = _CHECKSUMS.get(url, None) + download_url(url, root, hash_value=checksum) + extract_archive(archive) + + walker = walk_files( + self._path, suffix=self._ext_audio, prefix=False, remove_suffix=True + ) + self._walker = list(walker) + + def __getitem__(self, n: int) -> Tuple[Tensor, int, str, str, int, int, str]: + fileid = self._walker[n] + return load_libritts_item( + fileid, + self._path, + self._ext_audio, + self._ext_original_txt, + self._ext_normalized_txt, + ) + + def __len__(self) -> int: + return len(self._walker) diff --git a/torchaudio/datasets/utils.py b/torchaudio/datasets/utils.py index 2840b43471..d00ffc143b 100644 --- a/torchaudio/datasets/utils.py +++ b/torchaudio/datasets/utils.py @@ -264,7 +264,13 @@ def walk_files(root: str, root = os.path.expanduser(root) - for dirpath, _, files in os.walk(root): + for dirpath, dirs, files in os.walk(root): + dirs.sort() + # `dirs` is the list used in os.walk function and by sorting it in-place here, we change the + # behavior of os.walk to traverse sub directory alphabetically + # see also + # https://stackoverflow.com/questions/6670029/can-i-force-python3s-os-walk-to-visit-directories-in-alphabetical-order-how#comment71993866_6670926 + files.sort() for f in files: if f.endswith(suffix): diff --git a/torchaudio/functional.py b/torchaudio/functional.py index 78c8c594c9..713544cc74 100644 --- a/torchaudio/functional.py +++ b/torchaudio/functional.py @@ -1646,11 +1646,11 @@ def compute_deltas( r"""Compute delta coefficients of a tensor, usually a spectrogram: .. math:: - d_t = \frac{\sum_{n=1}^{\text{N}} n (c_{t+n} - c_{t-n})}{2 \sum_{n=1}^{\text{N} n^2} + d_t = \frac{\sum_{n=1}^{\text{N}} n (c_{t+n} - c_{t-n})}{2 \sum_{n=1}^{\text{N}} n^2} where :math:`d_t` is the deltas at time :math:`t`, :math:`c_t` is the spectrogram coeffcients at time :math:`t`, - :math:`N` is (`win_length`-1)//2. + :math:`N` is ``(win_length-1)//2``. Args: specgram (Tensor): Tensor of audio of dimension (..., freq, time) diff --git a/torchaudio/models/_wavernn.py b/torchaudio/models/_wavernn.py index cd2e89a10c..37a06edfc3 100644 --- a/torchaudio/models/_wavernn.py +++ b/torchaudio/models/_wavernn.py @@ -1,4 +1,4 @@ -from typing import List +from typing import List, Tuple import torch from torch import Tensor @@ -13,7 +13,7 @@ class _ResBlock(nn.Module): The paper link is https://arxiv.org/pdf/1512.03385.pdf. Args: - n_freq: the number of bins in a spectrogram (default=128) + n_freq: the number of bins in a spectrogram. (Default: ``128``) Examples >>> resblock = _ResBlock() @@ -48,11 +48,11 @@ class _MelResNet(nn.Module): r"""MelResNet layer uses a stack of ResBlocks on spectrogram. Args: - n_res_block: the number of ResBlock in stack (default=10) - n_freq: the number of bins in a spectrogram (default=128) - n_hidden: the number of hidden dimensions (default=128) - n_output: the number of output dimensions (default=128) - kernel_size: the number of kernel size in the first Conv1d layer (default=5) + n_res_block: the number of ResBlock in stack. (Default: ``10``) + n_freq: the number of bins in a spectrogram. (Default: ``128``) + n_hidden: the number of hidden dimensions of resblock. (Default: ``128``) + n_output: the number of output dimensions of melresnet. (Default: ``128``) + kernel_size: the number of kernel size in the first Conv1d layer. (Default: ``5``) Examples >>> melresnet = _MelResNet() @@ -129,12 +129,12 @@ class _UpsampleNetwork(nn.Module): r"""Upscale the dimensions of a spectrogram. Args: - upsample_scales: the list of upsample scales - n_res_block: the number of ResBlock in stack (default=10) - n_freq: the number of bins in a spectrogram (default=128) - n_hidden: the number of hidden dimensions (default=128) - n_output: the number of output dimensions (default=128) - kernel_size: the number of kernel size in the first Conv1d layer (default=5) + upsample_scales: the list of upsample scales. + n_res_block: the number of ResBlock in stack. (Default: ``10``) + n_freq: the number of bins in a spectrogram. (Default: ``128``) + n_hidden: the number of hidden dimensions of resblock. (Default: ``128``) + n_output: the number of output dimensions of melresnet. (Default: ``128``) + kernel_size: the number of kernel size in the first Conv1d layer. (Default: ``5``) Examples >>> upsamplenetwork = _UpsampleNetwork(upsample_scales=[4, 4, 16]) @@ -172,7 +172,7 @@ def __init__(self, up_layers.append(conv) self.upsample_layers = nn.Sequential(*up_layers) - def forward(self, specgram: Tensor) -> Tensor: + def forward(self, specgram: Tensor) -> Tuple[Tensor, Tensor]: r"""Pass the input through the _UpsampleNetwork layer. Args: @@ -204,32 +204,29 @@ class _WaveRNN(nn.Module): `upsample_scales` must equal `hop_length`. Args: - upsample_scales: the list of upsample scales - n_bits: the bits of output waveform - sample_rate: the rate of audio dimensions (samples per second) - hop_length: the number of samples between the starts of consecutive frames - n_res_block: the number of ResBlock in stack (default=10) - n_rnn: the dimension of RNN layer (default=512) - n_fc: the dimension of fully connected layer (default=512) - kernel_size: the number of kernel size in the first Conv1d layer (default=5) - n_freq: the number of bins in a spectrogram (default=128) - n_hidden: the number of hidden dimensions (default=128) - n_output: the number of output dimensions (default=128) - mode: the mode of waveform in ['waveform', 'mol'] (default='waveform') + upsample_scales: the list of upsample scales. + n_classes: the number of output classes. + hop_length: the number of samples between the starts of consecutive frames. + n_res_block: the number of ResBlock in stack. (Default: ``10``) + n_rnn: the dimension of RNN layer. (Default: ``512``) + n_fc: the dimension of fully connected layer. (Default: ``512``) + kernel_size: the number of kernel size in the first Conv1d layer. (Default: ``5``) + n_freq: the number of bins in a spectrogram. (Default: ``128``) + n_hidden: the number of hidden dimensions of resblock. (Default: ``128``) + n_output: the number of output dimensions of melresnet. (Default: ``128``) Example - >>> wavernn = _waveRNN(upsample_scales=[5,5,8], n_bits=9, sample_rate=24000, hop_length=200) + >>> wavernn = _waveRNN(upsample_scales=[5,5,8], n_classes=512, hop_length=200) >>> waveform, sample_rate = torchaudio.load(file) >>> # waveform shape: (n_batch, n_channel, (n_time - kernel_size + 1) * hop_length) >>> specgram = MelSpectrogram(sample_rate)(waveform) # shape: (n_batch, n_channel, n_freq, n_time) >>> output = wavernn(waveform, specgram) - >>> # output shape: (n_batch, n_channel, (n_time - kernel_size + 1) * hop_length, 2 ** n_bits) + >>> # output shape: (n_batch, n_channel, (n_time - kernel_size + 1) * hop_length, n_classes) """ def __init__(self, upsample_scales: List[int], - n_bits: int, - sample_rate: int, + n_classes: int, hop_length: int, n_res_block: int = 10, n_rnn: int = 512, @@ -237,24 +234,14 @@ def __init__(self, kernel_size: int = 5, n_freq: int = 128, n_hidden: int = 128, - n_output: int = 128, - mode: str = 'waveform') -> None: + n_output: int = 128) -> None: super().__init__() - self.mode = mode self.kernel_size = kernel_size - - if self.mode == 'waveform': - self.n_classes = 2 ** n_bits - elif self.mode == 'mol': - self.n_classes = 30 - else: - raise ValueError(f"Expected mode: `waveform` or `mol`, but found {self.mode}") - self.n_rnn = n_rnn self.n_aux = n_output // 4 self.hop_length = hop_length - self.sample_rate = sample_rate + self.n_classes = n_classes total_scale = 1 for upsample_scale in upsample_scales: @@ -262,7 +249,12 @@ def __init__(self, if total_scale != self.hop_length: raise ValueError(f"Expected: total_scale == hop_length, but found {total_scale} != {hop_length}") - self.upsample = _UpsampleNetwork(upsample_scales, n_res_block, n_freq, n_hidden, n_output, kernel_size) + self.upsample = _UpsampleNetwork(upsample_scales, + n_res_block, + n_freq, + n_hidden, + n_output, + kernel_size) self.fc = nn.Linear(n_freq + self.n_aux + 1, n_rnn) self.rnn1 = nn.GRU(n_rnn, n_rnn, batch_first=True) @@ -283,7 +275,7 @@ def forward(self, waveform: Tensor, specgram: Tensor) -> Tensor: specgram: the input spectrogram to the _WaveRNN layer (n_batch, 1, n_freq, n_time) Return: - Tensor shape: (n_batch, 1, (n_time - kernel_size + 1) * hop_length, 2 ** n_bits) + Tensor shape: (n_batch, 1, (n_time - kernel_size + 1) * hop_length, n_classes) """ assert waveform.size(1) == 1, 'Require the input channel of waveform is 1' diff --git a/torchaudio/models/wav2letter.py b/torchaudio/models/wav2letter.py index 3466e42dd2..acd4dfe4b3 100644 --- a/torchaudio/models/wav2letter.py +++ b/torchaudio/models/wav2letter.py @@ -1,5 +1,3 @@ -from typing import Optional - from torch import Tensor from torch import nn @@ -7,8 +5,9 @@ class Wav2Letter(nn.Module): - r"""Wav2Letter model architecture from the `"Wav2Letter: an End-to-End ConvNet-based Speech Recognition System" - `_ paper. + r"""Wav2Letter model architecture from the `Wav2Letter an End-to-End ConvNet-based Speech Recognition System`_. + + .. _Wav2Letter an End-to-End ConvNet-based Speech Recognition System: https://arxiv.org/abs/1609.03193 :math:`\text{padding} = \frac{\text{ceil}(\text{kernel} - \text{stride})}{2}` @@ -63,7 +62,7 @@ def __init__(self, num_classes: int = 40, def forward(self, x: Tensor) -> Tensor: r""" Args: - x (Tensor): Tensor of dimension (batch_size, num_features, input_length). + x (torch.Tensor): Tensor of dimension (batch_size, num_features, input_length). Returns: Tensor: Predictor tensor of dimension (batch_size, number_of_classes, input_length). diff --git a/torchaudio/sox_effects/__init__.py b/torchaudio/sox_effects/__init__.py index 507dc5c3af..d9650173c5 100644 --- a/torchaudio/sox_effects/__init__.py +++ b/torchaudio/sox_effects/__init__.py @@ -3,6 +3,8 @@ init_sox_effects, shutdown_sox_effects, effect_names, + apply_effects_tensor, + apply_effects_file, SoxEffect, SoxEffectsChain, ) diff --git a/torchaudio/sox_effects/sox_effects.py b/torchaudio/sox_effects/sox_effects.py index 0aee312126..9262786541 100644 --- a/torchaudio/sox_effects/sox_effects.py +++ b/torchaudio/sox_effects/sox_effects.py @@ -7,37 +7,37 @@ module_utils as _mod_utils, misc_ops as _misc_ops, ) +from torchaudio.utils.sox_utils import list_effects + if _mod_utils.is_module_available('torchaudio._torchaudio'): from torchaudio import _torchaudio @_mod_utils.requires_module('torchaudio._torchaudio') -def init_sox_effects() -> None: - """Initialize resources required to use ``SoxEffectsChain`` - - You do not need to call this function manually. It is called automatically. - - Once initialized, you do not need to call this function again across the multiple call of - ``SoxEffectsChain.sox_build_flow_effects``, though it is safe to do so as long as - ``shutdown_sox_effects`` is not called yet. - Once ``shutdown_sox_effects`` is called, you can no longer use SoX effects and - initializing again will result in error. +def init_sox_effects(): + """Initialize resources required to use sox effects. Note: - This function is not required for simple loading. + You do not need to call this function manually. It is called automatically. + + Once initialized, you do not need to call this function again across the multiple uses of + sox effects though it is safe to do so as long as :func:`shutdown_sox_effects` is not called yet. + Once :func:`shutdown_sox_effects` is called, you can no longer use SoX effects and initializing + again will result in error. """ torch.ops.torchaudio.sox_effects_initialize_sox_effects() @_mod_utils.requires_module("torchaudio._torchaudio") -def shutdown_sox_effects() -> None: - """Clean up resources required to use ``SoxEffectsChain`` +def shutdown_sox_effects(): + """Clean up resources required to use sox effects. - You do not need to call this function manually. It is called automatically. + Note: + You do not need to call this function manually. It is called automatically. It is safe to call this function multiple times. - Once ``shutdown_sox_effects`` is called, you can no longer use SoX effects and + Once :py:func:`shutdown_sox_effects` is called, you can no longer use SoX effects and initializing again will result in error. """ torch.ops.torchaudio.sox_effects_shutdown_sox_effects() @@ -47,18 +47,227 @@ def shutdown_sox_effects() -> None: def effect_names() -> List[str]: """Gets list of valid sox effect names - Returns: list[str] + Returns: + List[str]: list of available effect names. Example - >>> EFFECT_NAMES = torchaudio.sox_effects.effect_names() + >>> torchaudio.sox_effects.effect_names() + ['allpass', 'band', 'bandpass', ... ] """ - return torch.ops.torchaudio.sox_effects_list_effects() + return list(list_effects().keys()) @_mod_utils.requires_module('torchaudio._torchaudio') +def apply_effects_tensor( + tensor: torch.Tensor, + sample_rate: int, + effects: List[List[str]], + channels_first: bool = True, +) -> Tuple[torch.Tensor, int]: + """Apply sox effects to given Tensor + + Note: + This function works in the way very similar to ``sox`` command, however there are slight + differences. For example, ``sox`` commnad adds certain effects automatically (such as + ``rate`` effect after ``speed`` and ``pitch`` and other effects), but this function does + only applies the given effects. (Therefore, to actually apply ``speed`` effect, you also + need to give ``rate`` effect with desired sampling rate.) + + Args: + tensor (torch.Tensor): Input 2D Tensor. + sample_rate (int): Sample rate + effects (List[List[str]]): List of effects. + channels_first (bool): Indicates if the input Tensor's dimension is + ``[channels, time]`` or ``[time, channels]`` + + Returns: + Tuple[torch.Tensor, int]: Resulting Tensor and sample rate. + The resulting Tensor has the same ``dtype`` as the input Tensor, and + the same channels order. The shape of the Tensor can be different based on the + effects applied. Sample rate can also be different based on the effects applied. + + Example - Basic usage + >>> + >>> # Defines the effects to apply + >>> effects = [ + ... ['gain', '-n'], # normalises to 0dB + ... ['pitch', '5'], # 5 cent pitch shift + ... ['rate', '8000'], # resample to 8000 Hz + ... ] + >>> + >>> # Generate pseudo wave: + >>> # normalized, channels first, 2ch, sampling rate 16000, 1 second + >>> sample_rate = 16000 + >>> waveform = 2 * torch.rand([2, sample_rate * 1]) - 1 + >>> waveform.shape + torch.Size([2, 16000]) + >>> waveform + tensor([[ 0.3138, 0.7620, -0.9019, ..., -0.7495, -0.4935, 0.5442], + [-0.0832, 0.0061, 0.8233, ..., -0.5176, -0.9140, -0.2434]]) + >>> + >>> # Apply effects + >>> waveform, sample_rate = apply_effects_tensor( + ... wave_form, sample_rate, effects, channels_first=True) + >>> + >>> # Check the result + >>> # The new waveform is sampling rate 8000, 1 second. + >>> # normalization and channel order are preserved + >>> waveform.shape + torch.Size([2, 8000]) + >>> waveform + tensor([[ 0.5054, -0.5518, -0.4800, ..., -0.0076, 0.0096, -0.0110], + [ 0.1331, 0.0436, -0.3783, ..., -0.0035, 0.0012, 0.0008]]) + >>> sample_rate + 8000 + + Example - Torchscript-able transform + >>> + >>> # Use `apply_effects_tensor` in `torch.nn.Module` and dump it to file, + >>> # then run sox effect via Torchscript runtime. + >>> + >>> class SoxEffectTransform(torch.nn.Module): + ... effects: List[List[str]] + ... + ... def __init__(self, effects: List[List[str]]): + ... super().__init__() + ... self.effects = effects + ... + ... def forward(self, tensor: torch.Tensor, sample_rate: int): + ... return sox_effects.apply_effects_tensor( + ... tensor, sample_rate, self.effects) + ... + ... + >>> # Create transform object + >>> effects = [ + ... ["lowpass", "-1", "300"], # apply single-pole lowpass filter + ... ["rate", "8000"], # change sample rate to 8000 + ... ] + >>> transform = SoxEffectTensorTransform(effects, input_sample_rate) + >>> + >>> # Dump it to file and load + >>> path = 'sox_effect.zip' + >>> torch.jit.script(trans).save(path) + >>> transform = torch.jit.load(path) + >>> + >>>> # Run transform + >>> waveform, input_sample_rate = torchaudio.load("input.wav") + >>> waveform, sample_rate = transform(waveform, input_sample_rate) + >>> assert sample_rate == 8000 + """ + in_signal = torch.classes.torchaudio.TensorSignal(tensor, sample_rate, channels_first) + out_signal = torch.ops.torchaudio.sox_effects_apply_effects_tensor(in_signal, effects) + return out_signal.get_tensor(), out_signal.get_sample_rate() + + +@_mod_utils.requires_module('torchaudio._torchaudio') +def apply_effects_file( + path: str, + effects: List[List[str]], + normalize: bool = True, + channels_first: bool = True, +) -> Tuple[torch.Tensor, int]: + """Apply sox effects to the audio file and load the resulting data as Tensor + + Note: + This function works in the way very similar to ``sox`` command, however there are slight + differences. For example, ``sox`` commnad adds certain effects automatically (such as + ``rate`` effect after ``speed``, ``pitch`` etc), but this function only applies the given + effects. Therefore, to actually apply ``speed`` effect, you also need to give ``rate`` + effect with desired sampling rate, because internally, ``speed`` effects only alter sampling + rate and leave samples untouched. + + Args: + path (str): Path to the audio file. + effects (List[List[str]]): List of effects. + normalize (bool): + When ``True``, this function always return ``float32``, and sample values are + normalized to ``[-1.0, 1.0]``. + If input file is integer WAV, giving ``False`` will change the resulting Tensor type to + integer type. This argument has no effect for formats other + than integer WAV type. + channels_first (bool): When True, the returned Tensor has dimension ``[channel, time]``. + Otherwise, the returned Tensor's dimension is ``[time, channel]``. + + Returns: + Tuple[torch.Tensor, int]: Resulting Tensor and sample rate. + If ``normalize=True``, the resulting Tensor is always ``float32`` type. + If ``normalize=False`` and the input audio file is of integer WAV file, then the + resulting Tensor has corresponding integer type. (Note 24 bit integer type is not supported) + If ``channels_first=True``, the resulting Tensor has dimension ``[channel, time]``, + otherwise ``[time, channel]``. + + Example - Basic usage + >>> + >>> # Defines the effects to apply + >>> effects = [ + ... ['gain', '-n'], # normalises to 0dB + ... ['pitch', '5'], # 5 cent pitch shift + ... ['rate', '8000'], # resample to 8000 Hz + ... ] + >>> + >>> # Apply effects and load data with channels_first=True + >>> waveform, sample_rate = apply_effects_file("data.wav", effects, channels_first=True) + >>> + >>> # Check the result + >>> waveform.shape + torch.Size([2, 8000]) + >>> waveform + tensor([[ 5.1151e-03, 1.8073e-02, 2.2188e-02, ..., 1.0431e-07, + -1.4761e-07, 1.8114e-07], + [-2.6924e-03, 2.1860e-03, 1.0650e-02, ..., 6.4122e-07, + -5.6159e-07, 4.8103e-07]]) + >>> sample_rate + 8000 + + Example - Apply random speed perturbation to dataset + >>> + >>> # Load data from file, apply random speed perturbation + >>> class RandomPerturbationFile(torch.utils.data.Dataset): + ... \"\"\"Given flist, apply random speed perturbation + ... + ... Suppose all the input files are at least one second long. + ... \"\"\" + ... def __init__(self, flist: List[str], sample_rate: int): + ... super().__init__() + ... self.flist = flist + ... self.sample_rate = sample_rate + ... self.rng = None + ... + ... def __getitem__(self, index): + ... speed = self.rng.uniform(0.5, 2.0) + ... effects = [ + ... ['gain', '-n', '-10'], # apply 10 db attenuation + ... ['remix', '-'], # merge all the channels + ... ['speed', f'{speed:.5f}'], # duration is now 0.5 ~ 2.0 seconds. + ... ['rate', f'{self.sample_rate}'], + ... ['pad', '0', '1.5'], # add 1.5 seconds silence at the end + ... ['trim', '0', '2'], # get the first 2 seconds + ... ] + ... waveform, _ = torchaudio.sox_effects.apply_effects_file( + ... self.flist[index], effects) + ... return waveform + ... + ... def __len__(self): + ... return len(self.flist) + ... + >>> dataset = RandomPerturbationFile(file_list, sample_rate=8000) + >>> loader = torch.utils.data.DataLoader(dataset, batch_size=32) + >>> for batch in loader: + >>> pass + """ + signal = torch.ops.torchaudio.sox_effects_apply_effects_file(path, effects, normalize, channels_first) + return signal.get_tensor(), signal.get_sample_rate() + + +@_mod_utils.requires_module('torchaudio._torchaudio') +@_mod_utils.deprecated('Please migrate to `apply_effects_file` or `apply_effects_tensor`.') def SoxEffect(): r"""Create an object for passing sox effect information between python and c++ + Warning: + This function is deprecated. + Please migrate to :func:`apply_effects_file` or :func:`apply_effects_tensor`. + Returns: SoxEffect: An object with the following attributes: ename (str) which is the name of effect, and eopts (List[str]) which is a list of effect options. @@ -66,49 +275,60 @@ def SoxEffect(): return _torchaudio.SoxEffect() +@_mod_utils.deprecated('Please migrate to `apply_effects_file` or `apply_effects_tensor`.') class SoxEffectsChain(object): r"""SoX effects chain class. + Warning: + This class is deprecated. + Please migrate to :func:`apply_effects_file` or :func:`apply_effects_tensor`. + Args: - normalization (bool, number, or callable, optional): If boolean `True`, then output is divided by `1 << 31` - (assumes signed 32-bit audio), and normalizes to `[-1, 1]`. If `number`, then output is divided by that - number. If `callable`, then the output is passed as a parameter to the given function, then the - output is divided by the result. (Default: ``True``) - channels_first (bool, optional): Set channels first or length first in result. (Default: ``True``) - out_siginfo (sox_signalinfo_t, optional): a sox_signalinfo_t type, which could be helpful if the - audio type cannot be automatically determined. (Default: ``None``) - out_encinfo (sox_encodinginfo_t, optional): a sox_encodinginfo_t type, which could be set if the - audio type cannot be automatically determined. (Default: ``None``) - filetype (str, optional): a filetype or extension to be set if sox cannot determine it - automatically. . (Default: ``'raw'``) + normalization (bool, number, or callable, optional): + If boolean ``True``, then output is divided by ``1 << 31`` + (assumes signed 32-bit audio), and normalizes to ``[-1, 1]``. + If ``number``, then output is divided by that number. + If ``callable``, then the output is passed as a parameter to the given function, then + the output is divided by the result. (Default: ``True``) + channels_first (bool, optional): + Set channels first or length first in result. (Default: ``True``) + out_siginfo (sox_signalinfo_t, optional): + a sox_signalinfo_t type, which could be helpful if the audio type cannot be + automatically determined. (Default: ``None``) + out_encinfo (sox_encodinginfo_t, optional): + a sox_encodinginfo_t type, which could be set if the audio type cannot be + automatically determined. (Default: ``None``) + filetype (str, optional): + a filetype or extension to be set if sox cannot determine it automatically. + (Default: ``'raw'``) Returns: - Tuple[Tensor, int]: An output Tensor of size `[C x L]` or `[L x C]` where L is the number + Tuple[Tensor, int]: + An output Tensor of size ``[C x L]`` or ``[L x C]`` where L is the number of audio frames and C is the number of channels. An integer which is the sample rate of the audio (as listed in the metadata of the file) Example >>> class MyDataset(Dataset): - >>> def __init__(self, audiodir_path): - >>> self.data = [os.path.join(audiodir_path, fn) for fn in os.listdir(audiodir_path)] - >>> self.E = torchaudio.sox_effects.SoxEffectsChain() - >>> self.E.append_effect_to_chain("rate", [16000]) # resample to 16000hz - >>> self.E.append_effect_to_chain("channels", ["1"]) # mono signal - >>> def __getitem__(self, index): - >>> fn = self.data[index] - >>> self.E.set_input_file(fn) - >>> x, sr = self.E.sox_build_flow_effects() - >>> return x, sr - >>> - >>> def __len__(self): - >>> return len(self.data) - >>> - >>> torchaudio.initialize_sox() + ... def __init__(self, audiodir_path): + ... self.data = [ + ... os.path.join(audiodir_path, fn) + ... for fn in os.listdir(audiodir_path)] + ... self.E = torchaudio.sox_effects.SoxEffectsChain() + ... self.E.append_effect_to_chain("rate", [16000]) # resample to 16000hz + ... self.E.append_effect_to_chain("channels", ["1"]) # mono signal + ... def __getitem__(self, index): + ... fn = self.data[index] + ... self.E.set_input_file(fn) + ... x, sr = self.E.sox_build_flow_effects() + ... return x, sr + ... + ... def __len__(self): + ... return len(self.data) + ... >>> ds = MyDataset(path_to_audio_files) >>> for sig, sr in ds: - >>> [do something here] - >>> torchaudio.shutdown_sox() - + ... pass """ EFFECTS_UNIMPLEMENTED = {"spectrogram", "splice", "noiseprof", "fir"} @@ -165,9 +385,9 @@ def sox_build_flow_effects(self, out (Tensor, optional): Where the output will be written to. (Default: ``None``) Returns: - Tuple[Tensor, int]: An output Tensor of size `[C x L]` or `[L x C]` where L is the number - of audio frames and C is the number of channels. An integer which is the sample rate of the - audio (as listed in the metadata of the file) + Tuple[Tensor, int]: An output Tensor of size `[C x L]` or `[L x C]` where + L is the number of audio frames and C is the number of channels. + An integer which is the sample rate of the audio (as listed in the metadata of the file) """ # initialize output tensor if out is not None: diff --git a/torchaudio/transforms.py b/torchaudio/transforms.py index f34f5c468e..72e55c94c8 100644 --- a/torchaudio/transforms.py +++ b/torchaudio/transforms.py @@ -86,20 +86,8 @@ def forward(self, waveform: Tensor) -> Tensor: class GriffinLim(torch.nn.Module): r"""Compute waveform from a linear scale magnitude spectrogram using the Griffin-Lim transformation. - Implementation ported from `librosa`. - .. [1] McFee, Brian, Colin Raffel, Dawen Liang, Daniel PW Ellis, Matt McVicar, Eric Battenberg, and Oriol Nieto. - "librosa: Audio and music signal analysis in python." - In Proceedings of the 14th python in science conference, pp. 18-25. 2015. - - .. [2] Perraudin, N., Balazs, P., & Sรธndergaard, P. L. - "A fast Griffin-Lim algorithm," - IEEE Workshop on Applications of Signal Processing to Audio and Acoustics (pp. 1-4), - Oct. 2013. - - .. [3] D. W. Griffin and J. S. Lim, - "Signal estimation from modified short-time Fourier transform," - IEEE Trans. ASSP, vol.32, no.2, pp.236โ€“243, Apr. 1984. + Implementation ported from ``librosa`` [1]_, [2]_, [3]_. Args: n_fft (int, optional): Size of FFT, creates ``n_fft // 2 + 1`` bins. (Default: ``400``) @@ -117,6 +105,24 @@ class GriffinLim(torch.nn.Module): Values near 1 can lead to faster convergence, but above 1 may not converge. (Default: ``0.99``) length (int, optional): Array length of the expected output. (Default: ``None``) rand_init (bool, optional): Initializes phase randomly if True and to zero otherwise. (Default: ``True``) + + References: + .. [1] + | McFee, Brian, Colin Raffel, Dawen Liang, Daniel PW Ellis, Matt McVicar, Eric Battenberg, + and Oriol Nieto. + | "librosa: Audio and music signal analysis in python." + | In Proceedings of the 14th python in science conference, pp. 18-25. 2015. + + .. [2] + | Perraudin, N., Balazs, P., & Sรธndergaard, P. L. + | "A fast Griffin-Lim algorithm," + | IEEE Workshop on Applications of Signal Processing to Audio and Acoustics (pp. 1-4), + | Oct. 2013. + + .. [3] + | D. W. Griffin and J. S. Lim, + | "Signal estimation from modified short-time Fourier transform," + | IEEE Trans. ASSP, vol.32, no.2, pp.236โ€“243, Apr. 1984. """ __constants__ = ['n_fft', 'n_iter', 'win_length', 'hop_length', 'power', 'normalized', 'length', 'momentum', 'rand_init'] @@ -153,8 +159,9 @@ def __init__(self, def forward(self, specgram: Tensor) -> Tensor: r""" Args: - specgram (Tensor): A magnitude-only STFT spectrogram of dimension (..., freq, frames) - where freq is ``n_fft // 2 + 1``. + specgram (Tensor): + A magnitude-only STFT spectrogram of dimension (..., freq, frames) + where freq is ``n_fft // 2 + 1``. Returns: Tensor: waveform of (..., time), where time equals the ``length`` parameter if given. diff --git a/torchaudio/utils/__init__.py b/torchaudio/utils/__init__.py new file mode 100644 index 0000000000..bc11f86893 --- /dev/null +++ b/torchaudio/utils/__init__.py @@ -0,0 +1,9 @@ +from . import ( + sox_utils, +) + +from torchaudio._internal import module_utils as _mod_utils + + +if _mod_utils.is_module_available('torchaudio._torchaudio'): + sox_utils.set_verbosity(1) diff --git a/torchaudio/utils/sox_utils.py b/torchaudio/utils/sox_utils.py new file mode 100644 index 0000000000..59090e4b88 --- /dev/null +++ b/torchaudio/utils/sox_utils.py @@ -0,0 +1,94 @@ +from typing import List, Dict + +import torch + +from torchaudio._internal import ( + module_utils as _mod_utils, +) + + +@_mod_utils.requires_module('torchaudio._torchaudio') +def set_seed(seed: int): + """Set libsox's PRNG + + Args: + seed (int): seed value. valid range is int32. + + See Also: + http://sox.sourceforge.net/sox.html + """ + torch.ops.torchaudio.sox_utils_set_seed(seed) + + +@_mod_utils.requires_module('torchaudio._torchaudio') +def set_verbosity(verbosity: int): + """Set libsox's verbosity + + Args: + verbosity (int): Set verbosity level of libsox. + 1: failure messages + 2: warnings + 3: details of processing + 4-6: increasing levels of debug messages + + See Also: + http://sox.sourceforge.net/sox.html + """ + torch.ops.torchaudio.sox_utils_set_verbosity(verbosity) + + +@_mod_utils.requires_module('torchaudio._torchaudio') +def set_buffer_size(buffer_size: int): + """Set buffer size for sox effect chain + + Args: + buffer_size (int): Set the size in bytes of the buffers used for processing audio. + + See Also: + http://sox.sourceforge.net/sox.html + """ + torch.ops.torchaudio.sox_utils_set_buffer_size(buffer_size) + + +@_mod_utils.requires_module('torchaudio._torchaudio') +def set_use_threads(use_threads: bool): + """Set multithread option for sox effect chain + + Args: + use_threads (bool): When ``True``, enables ``libsox``'s parallel effects channels processing. + To use mutlithread, the underlying ``libsox`` has to be compiled with OpenMP support. + + See Also: + http://sox.sourceforge.net/sox.html + """ + torch.ops.torchaudio.sox_utils_set_use_threads(use_threads) + + +@_mod_utils.requires_module('torchaudio._torchaudio') +def list_effects() -> Dict[str, str]: + """List the available sox effect names + + Returns: + Dict[str, str]: Mapping from ``effect name`` to ``usage`` + """ + return dict(torch.ops.torchaudio.sox_utils_list_effects()) + + +@_mod_utils.requires_module('torchaudio._torchaudio') +def list_read_formats() -> List[str]: + """List the supported audio formats for read + + Returns: + List[str]: List of supported audio formats + """ + return torch.ops.torchaudio.sox_utils_list_read_formats() + + +@_mod_utils.requires_module('torchaudio._torchaudio') +def list_write_formats() -> List[str]: + """List the supported audio formats for write + + Returns: + List[str]: List of supported audio formats + """ + return torch.ops.torchaudio.sox_utils_list_write_formats() From 18be43cd7248272d5096c3695f34ebae26449193 Mon Sep 17 00:00:00 2001 From: Yanan Cao Date: Sat, 1 Aug 2020 13:02:20 -0700 Subject: [PATCH 14/73] Support custom exception message (#41907) Summary: Raise and assert used to have a hard-coded error message "Exception". User provided error message was ignored. This PR adds support to represent user's error message in TorchScript. This breaks backward compatibility because now we actually need to script the user's error message, which can potentially contain unscriptable expressions. Such programs can break when scripting, but saved models can still continue to work. Increased an op count in test_mobile_optimizer.py because now we need aten::format to form the actual exception message. This is built upon an WIP PR: https://github.com/pytorch/pytorch/pull/34112 by driazati Pull Request resolved: https://github.com/pytorch/pytorch/pull/41907 Reviewed By: ngimel Differential Revision: D22778301 Pulled By: gmagogsfm fbshipit-source-id: 2b94f0db4ae9fe70c4cd03f4048e519ea96323ad --- torchaudio/functional.py | 4 ++-- torchaudio/transforms.py | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/torchaudio/functional.py b/torchaudio/functional.py index 713544cc74..53795fef1a 100644 --- a/torchaudio/functional.py +++ b/torchaudio/functional.py @@ -223,8 +223,8 @@ def griffinlim( Returns: torch.Tensor: waveform of (..., time), where time equals the ``length`` parameter if given. """ - assert momentum < 1, 'momentum=%s > 1 can be unstable' % momentum - assert momentum >= 0, 'momentum=%s < 0' % momentum + assert momentum < 1, 'momentum={} > 1 can be unstable'.format(momentum) + assert momentum >= 0, 'momentum={} < 0'.format(momentum) # pack batch shape = specgram.size() diff --git a/torchaudio/transforms.py b/torchaudio/transforms.py index 72e55c94c8..ea0d6db492 100644 --- a/torchaudio/transforms.py +++ b/torchaudio/transforms.py @@ -607,7 +607,7 @@ def forward(self, waveform: Tensor) -> Tensor: return waveform - raise ValueError('Invalid resampling method: %s' % (self.resampling_method)) + raise ValueError('Invalid resampling method: ' + str(self.resampling_method)) class ComplexNorm(torch.nn.Module): From 355c1fdbda46a9fffc74ca1bbc061eccc62cc2c1 Mon Sep 17 00:00:00 2001 From: Moto Hira Date: Wed, 5 Aug 2020 11:03:05 -0700 Subject: [PATCH 15/73] Import torchaudio 20200804 Summary: Up to #804 Reviewed By: vincentqb Differential Revision: D22947671 fbshipit-source-id: d1a005cec2f1a00913c41eda380b9f4b993ef779 --- .../unittest/linux/scripts/environment.yml | 1 + .circleci/unittest/linux/scripts/install.sh | 2 +- .circleci/unittest/linux/scripts/run_test.sh | 21 +- .circleci/unittest/windows/scripts/install.sh | 2 +- .../unittest/windows/scripts/run_test.sh | 4 +- README.md | 1 + docs/source/functional.rst | 5 - docs/source/models.rst | 8 + examples/pipeline_wavernn/datasets.py | 20 +- examples/pipeline_wavernn/main.py | 15 +- setup.py | 5 +- test/README.md | 62 ++- .../cmu_us_aew_arctic/etc/txt.done.data | 1 - .../cmu_us_aew_arctic/wav/arctic_a0024.wav | Bin 441078 -> 0 bytes test/assets/LJSpeech-1.1/metadata.csv | 1 - test/assets/LJSpeech-1.1/wavs/LJ001-0001.wav | Bin 425830 -> 0 bytes .../1272/128104/1272-128104-0000.flac | Bin 120041 -> 0 bytes .../1272/128104/1272-128104.trans.txt | 1 - .../go/0a9f9af7_nohash_0.wav | Bin 27352 -> 0 bytes test/common_utils/backend_utils.py | 41 -- test/datasets/datasets_test.py | 60 --- test/functional_cpu_test.py | 407 ------------------ test/{ => torchaudio_unittest}/__init__.py | 0 .../tt/clips/common_voice_tt_00000000.wav | Bin .../cv-corpus-4-2019-12-10/tt/train.tsv | 0 .../assets/VCTK-Corpus/txt/p224/p224_002.txt | 0 .../VCTK-Corpus/wav48/p224/p224_002.wav | Bin .../assets/io/96k_0_1ch.opus | Bin .../assets/io/96k_0_2ch.opus | Bin .../assets/io/96k_10_1ch.opus | Bin .../assets/io/96k_10_2ch.opus | Bin .../assets/io/96k_5_1ch.opus | Bin .../assets/io/96k_5_2ch.opus | Bin .../assets/io/generate_opus.py | 0 .../assets/kaldi/resample-16000-1000.ark | Bin .../assets/kaldi/resample-16000-10000.ark | Bin .../assets/kaldi/resample-16000-11000.ark | Bin .../assets/kaldi/resample-16000-12000.ark | Bin .../assets/kaldi/resample-16000-13000.ark | Bin .../assets/kaldi/resample-16000-14000.ark | Bin .../assets/kaldi/resample-16000-15000.ark | Bin .../assets/kaldi/resample-16000-16000.ark | Bin .../assets/kaldi/resample-16000-17000.ark | Bin .../assets/kaldi/resample-16000-18000.ark | Bin .../assets/kaldi/resample-16000-19000.ark | Bin .../assets/kaldi/resample-16000-2000.ark | Bin .../assets/kaldi/resample-16000-20000.ark | Bin .../assets/kaldi/resample-16000-21000.ark | Bin .../assets/kaldi/resample-16000-22000.ark | Bin .../assets/kaldi/resample-16000-23000.ark | Bin .../assets/kaldi/resample-16000-24000.ark | Bin .../assets/kaldi/resample-16000-25000.ark | Bin .../assets/kaldi/resample-16000-26000.ark | Bin .../assets/kaldi/resample-16000-27000.ark | Bin .../assets/kaldi/resample-16000-28000.ark | Bin .../assets/kaldi/resample-16000-29000.ark | Bin .../assets/kaldi/resample-16000-3000.ark | Bin .../assets/kaldi/resample-16000-30000.ark | Bin .../assets/kaldi/resample-16000-31000.ark | Bin .../assets/kaldi/resample-16000-32000.ark | Bin .../assets/kaldi/resample-16000-4000.ark | Bin .../assets/kaldi/resample-16000-5000.ark | Bin .../assets/kaldi/resample-16000-6000.ark | Bin .../assets/kaldi/resample-16000-7000.ark | Bin .../assets/kaldi/resample-16000-8000.ark | Bin .../assets/kaldi/resample-16000-9000.ark | Bin .../assets/kaldi_file.wav | Bin .../assets/kaldi_file_8000.wav | Bin .../assets/kaldi_test_fbank_args.json | 0 .../assets/kaldi_test_mfcc_args.json | 0 .../assets/kaldi_test_spectrogram_args.json | 0 test/{ => torchaudio_unittest}/assets/mat.ark | Bin .../assets/sinewave.wav | Bin .../assets/sox_effect_test_args.json | 0 .../assets/sox_effect_test_fir_coeffs.txt | 0 .../steam-train-whistle-daniel_simon.mp3 | Bin .../steam-train-whistle-daniel_simon.wav | Bin .../assets/vad-go-mono-32000.wav | Bin .../assets/vad-go-stereo-44100.wav | Bin .../assets/vec_flt.ark | Bin .../assets/vec_int.ark | Bin .../backend_test.py} | 2 +- .../batch_consistency_test.py} | 10 +- .../common_utils/__init__.py | 2 - .../common_utils/backend_utils.py | 19 + .../common_utils/case_utils.py | 9 +- .../common_utils/data_utils.py | 0 .../common_utils/parameterized_utils.py | 0 .../common_utils/sox_utils.py | 0 .../common_utils/wav_utils.py | 0 .../compliance/__init__.py | 0 .../compliance/generate_fbank_data.py | 2 +- .../compliance/generate_test_stft_data.py | 0 .../compliance/utils.py | 0 .../compliance_kaldi_test.py} | 6 +- .../dataloader_test.py} | 2 +- .../datasets/__init__.py | 0 .../datasets/cmuarctic_test.py | 67 +++ .../datasets/commonvoice_test.py | 72 ++++ .../datasets/datasets_test.py | 17 + .../datasets/gtzan_test.py | 2 +- .../datasets/librispeech_test.py | 112 +++++ .../datasets/libritts_test.py | 8 +- .../datasets/ljspeech_test.py | 74 ++++ .../datasets/speechcommands_test.py | 109 +++++ .../datasets/utils_test.py | 23 +- .../datasets/yesno_test.py | 6 +- .../functional}/__init__.py | 0 .../functional/functional_cpu_test.py | 146 +++++++ .../functional}/functional_cuda_test.py | 2 +- .../functional}/functional_impl.py | 2 +- .../io_test.py} | 33 +- .../kaldi_compatibility_cpu_test.py | 2 +- .../kaldi_compatibility_cuda_test.py | 2 +- .../kaldi_compatibility_impl.py | 2 +- .../kaldi_io_test.py} | 2 +- .../librosa_compatibility_test.py} | 2 +- .../models_test.py} | 28 +- .../sox_compatibility_test.py} | 2 +- .../sox_effect}/__init__.py | 0 .../sox_effect/common.py | 2 +- .../sox_effect/dataset_test.py} | 2 +- .../sox_effect/smoke_test.py | 2 +- .../sox_effect/sox_effect_test.py} | 2 +- .../sox_effect/sox_effects_chain_test.py | 0 .../sox_effect/torchscript_test.py} | 2 +- .../sox_io_backend}/__init__.py | 0 .../sox_io_backend/common.py | 0 .../sox_io_backend/info_test.py} | 2 +- .../sox_io_backend/load_test.py} | 2 +- .../sox_io_backend/roundtrip_test.py} | 2 +- .../sox_io_backend/save_test.py} | 2 +- .../sox_io_backend/smoke_test.py | 2 +- .../sox_io_backend/torchscript_test.py} | 2 +- .../torchscript_consistency_cpu_test.py | 2 +- .../torchscript_consistency_cuda_test.py | 2 +- .../torchscript_consistency_impl.py | 2 +- .../transforms_test.py} | 2 +- test/torchaudio_unittest/utils/__init__.py | 0 .../utils/sox_utils_test.py} | 2 +- torchaudio/compliance/kaldi.py | 12 +- torchaudio/datasets/ljspeech.py | 2 +- torchaudio/functional.py | 98 +---- torchaudio/models/__init__.py | 2 +- torchaudio/models/{_wavernn.py => wavernn.py} | 64 +-- torchaudio/transforms.py | 10 +- 146 files changed, 878 insertions(+), 764 deletions(-) delete mode 100644 test/assets/ARCTIC/cmu_us_aew_arctic/etc/txt.done.data delete mode 100644 test/assets/ARCTIC/cmu_us_aew_arctic/wav/arctic_a0024.wav delete mode 100644 test/assets/LJSpeech-1.1/metadata.csv delete mode 100644 test/assets/LJSpeech-1.1/wavs/LJ001-0001.wav delete mode 100644 test/assets/LibriSpeech/dev-clean/1272/128104/1272-128104-0000.flac delete mode 100644 test/assets/LibriSpeech/dev-clean/1272/128104/1272-128104.trans.txt delete mode 100644 test/assets/SpeechCommands/speech_commands_v0.02/go/0a9f9af7_nohash_0.wav delete mode 100644 test/common_utils/backend_utils.py delete mode 100644 test/datasets/datasets_test.py delete mode 100644 test/functional_cpu_test.py rename test/{ => torchaudio_unittest}/__init__.py (100%) rename test/{ => torchaudio_unittest}/assets/CommonVoice/cv-corpus-4-2019-12-10/tt/clips/common_voice_tt_00000000.wav (100%) rename test/{ => torchaudio_unittest}/assets/CommonVoice/cv-corpus-4-2019-12-10/tt/train.tsv (100%) rename test/{ => torchaudio_unittest}/assets/VCTK-Corpus/txt/p224/p224_002.txt (100%) rename test/{ => torchaudio_unittest}/assets/VCTK-Corpus/wav48/p224/p224_002.wav (100%) rename test/{ => torchaudio_unittest}/assets/io/96k_0_1ch.opus (100%) rename test/{ => torchaudio_unittest}/assets/io/96k_0_2ch.opus (100%) rename test/{ => torchaudio_unittest}/assets/io/96k_10_1ch.opus (100%) rename test/{ => torchaudio_unittest}/assets/io/96k_10_2ch.opus (100%) rename test/{ => torchaudio_unittest}/assets/io/96k_5_1ch.opus (100%) rename test/{ => torchaudio_unittest}/assets/io/96k_5_2ch.opus (100%) rename test/{ => torchaudio_unittest}/assets/io/generate_opus.py (100%) rename test/{ => torchaudio_unittest}/assets/kaldi/resample-16000-1000.ark (100%) rename test/{ => torchaudio_unittest}/assets/kaldi/resample-16000-10000.ark (100%) rename test/{ => torchaudio_unittest}/assets/kaldi/resample-16000-11000.ark (100%) rename test/{ => torchaudio_unittest}/assets/kaldi/resample-16000-12000.ark (100%) rename test/{ => torchaudio_unittest}/assets/kaldi/resample-16000-13000.ark (100%) rename test/{ => torchaudio_unittest}/assets/kaldi/resample-16000-14000.ark (100%) rename test/{ => torchaudio_unittest}/assets/kaldi/resample-16000-15000.ark (100%) rename test/{ => torchaudio_unittest}/assets/kaldi/resample-16000-16000.ark (100%) rename test/{ => torchaudio_unittest}/assets/kaldi/resample-16000-17000.ark (100%) rename test/{ => torchaudio_unittest}/assets/kaldi/resample-16000-18000.ark (100%) rename test/{ => torchaudio_unittest}/assets/kaldi/resample-16000-19000.ark (100%) rename test/{ => torchaudio_unittest}/assets/kaldi/resample-16000-2000.ark (100%) rename test/{ => torchaudio_unittest}/assets/kaldi/resample-16000-20000.ark (100%) rename test/{ => torchaudio_unittest}/assets/kaldi/resample-16000-21000.ark (100%) rename test/{ => torchaudio_unittest}/assets/kaldi/resample-16000-22000.ark (100%) rename test/{ => torchaudio_unittest}/assets/kaldi/resample-16000-23000.ark (100%) rename test/{ => torchaudio_unittest}/assets/kaldi/resample-16000-24000.ark (100%) rename test/{ => torchaudio_unittest}/assets/kaldi/resample-16000-25000.ark (100%) rename test/{ => torchaudio_unittest}/assets/kaldi/resample-16000-26000.ark (100%) rename test/{ => torchaudio_unittest}/assets/kaldi/resample-16000-27000.ark (100%) rename test/{ => torchaudio_unittest}/assets/kaldi/resample-16000-28000.ark (100%) rename test/{ => torchaudio_unittest}/assets/kaldi/resample-16000-29000.ark (100%) rename test/{ => torchaudio_unittest}/assets/kaldi/resample-16000-3000.ark (100%) rename test/{ => torchaudio_unittest}/assets/kaldi/resample-16000-30000.ark (100%) rename test/{ => torchaudio_unittest}/assets/kaldi/resample-16000-31000.ark (100%) rename test/{ => torchaudio_unittest}/assets/kaldi/resample-16000-32000.ark (100%) rename test/{ => torchaudio_unittest}/assets/kaldi/resample-16000-4000.ark (100%) rename test/{ => torchaudio_unittest}/assets/kaldi/resample-16000-5000.ark (100%) rename test/{ => torchaudio_unittest}/assets/kaldi/resample-16000-6000.ark (100%) rename test/{ => torchaudio_unittest}/assets/kaldi/resample-16000-7000.ark (100%) rename test/{ => torchaudio_unittest}/assets/kaldi/resample-16000-8000.ark (100%) rename test/{ => torchaudio_unittest}/assets/kaldi/resample-16000-9000.ark (100%) rename test/{ => torchaudio_unittest}/assets/kaldi_file.wav (100%) rename test/{ => torchaudio_unittest}/assets/kaldi_file_8000.wav (100%) rename test/{ => torchaudio_unittest}/assets/kaldi_test_fbank_args.json (100%) rename test/{ => torchaudio_unittest}/assets/kaldi_test_mfcc_args.json (100%) rename test/{ => torchaudio_unittest}/assets/kaldi_test_spectrogram_args.json (100%) rename test/{ => torchaudio_unittest}/assets/mat.ark (100%) rename test/{ => torchaudio_unittest}/assets/sinewave.wav (100%) rename test/{ => torchaudio_unittest}/assets/sox_effect_test_args.json (100%) rename test/{ => torchaudio_unittest}/assets/sox_effect_test_fir_coeffs.txt (100%) rename test/{ => torchaudio_unittest}/assets/steam-train-whistle-daniel_simon.mp3 (100%) rename test/{ => torchaudio_unittest}/assets/steam-train-whistle-daniel_simon.wav (100%) rename test/{ => torchaudio_unittest}/assets/vad-go-mono-32000.wav (100%) rename test/{ => torchaudio_unittest}/assets/vad-go-stereo-44100.wav (100%) rename test/{ => torchaudio_unittest}/assets/vec_flt.ark (100%) rename test/{ => torchaudio_unittest}/assets/vec_int.ark (100%) rename test/{test_backend.py => torchaudio_unittest/backend_test.py} (96%) rename test/{test_batch_consistency.py => torchaudio_unittest/batch_consistency_test.py} (96%) rename test/{ => torchaudio_unittest}/common_utils/__init__.py (94%) create mode 100644 test/torchaudio_unittest/common_utils/backend_utils.py rename test/{ => torchaudio_unittest}/common_utils/case_utils.py (85%) rename test/{ => torchaudio_unittest}/common_utils/data_utils.py (100%) rename test/{ => torchaudio_unittest}/common_utils/parameterized_utils.py (100%) rename test/{ => torchaudio_unittest}/common_utils/sox_utils.py (100%) rename test/{ => torchaudio_unittest}/common_utils/wav_utils.py (100%) rename test/{ => torchaudio_unittest}/compliance/__init__.py (100%) rename test/{ => torchaudio_unittest}/compliance/generate_fbank_data.py (98%) rename test/{ => torchaudio_unittest}/compliance/generate_test_stft_data.py (100%) rename test/{ => torchaudio_unittest}/compliance/utils.py (100%) rename test/{test_compliance_kaldi.py => torchaudio_unittest/compliance_kaldi_test.py} (98%) rename test/{test_dataloader.py => torchaudio_unittest/dataloader_test.py} (96%) rename test/{ => torchaudio_unittest}/datasets/__init__.py (100%) create mode 100644 test/torchaudio_unittest/datasets/cmuarctic_test.py create mode 100644 test/torchaudio_unittest/datasets/commonvoice_test.py create mode 100644 test/torchaudio_unittest/datasets/datasets_test.py rename test/{ => torchaudio_unittest}/datasets/gtzan_test.py (98%) create mode 100644 test/torchaudio_unittest/datasets/librispeech_test.py rename test/{ => torchaudio_unittest}/datasets/libritts_test.py (91%) create mode 100644 test/torchaudio_unittest/datasets/ljspeech_test.py create mode 100644 test/torchaudio_unittest/datasets/speechcommands_test.py rename test/{ => torchaudio_unittest}/datasets/utils_test.py (68%) rename test/{ => torchaudio_unittest}/datasets/yesno_test.py (91%) rename test/{sox_effect => torchaudio_unittest/functional}/__init__.py (100%) create mode 100644 test/torchaudio_unittest/functional/functional_cpu_test.py rename test/{ => torchaudio_unittest/functional}/functional_cuda_test.py (88%) rename test/{ => torchaudio_unittest/functional}/functional_impl.py (96%) rename test/{test_io.py => torchaudio_unittest/io_test.py} (95%) rename test/{ => torchaudio_unittest}/kaldi_compatibility_cpu_test.py (87%) rename test/{ => torchaudio_unittest}/kaldi_compatibility_cuda_test.py (88%) rename test/{ => torchaudio_unittest}/kaldi_compatibility_impl.py (98%) rename test/{test_kaldi_io.py => torchaudio_unittest/kaldi_io_test.py} (96%) rename test/{test_librosa_compatibility.py => torchaudio_unittest/librosa_compatibility_test.py} (99%) rename test/{test_models.py => torchaudio_unittest/models_test.py} (75%) rename test/{test_sox_compatibility.py => torchaudio_unittest/sox_compatibility_test.py} (99%) rename test/{sox_io_backend => torchaudio_unittest/sox_effect}/__init__.py (100%) rename test/{ => torchaudio_unittest}/sox_effect/common.py (92%) rename test/{sox_effect/test_dataset.py => torchaudio_unittest/sox_effect/dataset_test.py} (98%) rename test/{ => torchaudio_unittest}/sox_effect/smoke_test.py (97%) rename test/{sox_effect/test_sox_effect.py => torchaudio_unittest/sox_effect/sox_effect_test.py} (99%) rename test/{ => torchaudio_unittest}/sox_effect/sox_effects_chain_test.py (100%) rename test/{sox_effect/test_torchscript.py => torchaudio_unittest/sox_effect/torchscript_test.py} (98%) rename test/{utils => torchaudio_unittest/sox_io_backend}/__init__.py (100%) rename test/{ => torchaudio_unittest}/sox_io_backend/common.py (100%) rename test/{sox_io_backend/test_info.py => torchaudio_unittest/sox_io_backend/info_test.py} (98%) rename test/{sox_io_backend/test_load.py => torchaudio_unittest/sox_io_backend/load_test.py} (99%) rename test/{sox_io_backend/test_roundtrip.py => torchaudio_unittest/sox_io_backend/roundtrip_test.py} (97%) rename test/{sox_io_backend/test_save.py => torchaudio_unittest/sox_io_backend/save_test.py} (99%) rename test/{ => torchaudio_unittest}/sox_io_backend/smoke_test.py (98%) rename test/{sox_io_backend/test_torchscript.py => torchaudio_unittest/sox_io_backend/torchscript_test.py} (99%) rename test/{ => torchaudio_unittest}/torchscript_consistency_cpu_test.py (93%) rename test/{ => torchaudio_unittest}/torchscript_consistency_cuda_test.py (94%) rename test/{ => torchaudio_unittest}/torchscript_consistency_impl.py (99%) rename test/{test_transforms.py => torchaudio_unittest/transforms_test.py} (99%) create mode 100644 test/torchaudio_unittest/utils/__init__.py rename test/{utils/test_sox_utils.py => torchaudio_unittest/utils/sox_utils_test.py} (97%) rename torchaudio/models/{_wavernn.py => wavernn.py} (83%) diff --git a/.circleci/unittest/linux/scripts/environment.yml b/.circleci/unittest/linux/scripts/environment.yml index 108d97d193..121478165e 100644 --- a/.circleci/unittest/linux/scripts/environment.yml +++ b/.circleci/unittest/linux/scripts/environment.yml @@ -6,6 +6,7 @@ dependencies: - numpy - pytest - pytest-cov + - pytest-xdist - codecov - librosa - llvmlite==0.31 # See https://github.com/pytorch/audio/pull/766 diff --git a/.circleci/unittest/linux/scripts/install.sh b/.circleci/unittest/linux/scripts/install.sh index 131c9e43bf..8346e6c825 100755 --- a/.circleci/unittest/linux/scripts/install.sh +++ b/.circleci/unittest/linux/scripts/install.sh @@ -20,4 +20,4 @@ printf "Installing PyTorch with %s\n" "${cudatoolkit}" conda install -y -c pytorch-nightly pytorch "${cudatoolkit}" printf "* Installing torchaudio\n" -BUILD_SOX=1 python setup.py develop +BUILD_SOX=1 python setup.py install diff --git a/.circleci/unittest/linux/scripts/run_test.sh b/.circleci/unittest/linux/scripts/run_test.sh index 9ea942851e..50bcf711d6 100755 --- a/.circleci/unittest/linux/scripts/run_test.sh +++ b/.circleci/unittest/linux/scripts/run_test.sh @@ -2,9 +2,28 @@ set -e +case "$(uname -s)" in + Darwin*) os=MacOSX;; + *) os=Linux +esac + + eval "$(./conda/bin/conda shell.bash hook)" conda activate ./env python -m torch.utils.collect_env +export TORCHAUDIO_TEST_FAIL_IF_NO_EXTENSION=1 export PATH="${PWD}/third_party/install/bin/:${PATH}" -pytest --cov=torchaudio --junitxml=test-results/junit.xml -v --durations 20 test + +declare -a common_args=( + '--cov=torchaudio' + "--junitxml=${PWD}/test-results/junit.xml" + '--durations' '20' +) +if [ "${os}" == MacOSX ] ; then + declare -a args=('-q' '-n' 'auto' '--dist=loadscope') +else + declare -a args=('-v') +fi +cd test +pytest "${args[@]}" "${common_args[@]}" torchaudio_unittest diff --git a/.circleci/unittest/windows/scripts/install.sh b/.circleci/unittest/windows/scripts/install.sh index acbd79ae50..2b9c88b4af 100644 --- a/.circleci/unittest/windows/scripts/install.sh +++ b/.circleci/unittest/windows/scripts/install.sh @@ -20,4 +20,4 @@ printf "Installing PyTorch with %s\n" "${cudatoolkit}" conda install -y -c pytorch-nightly pytorch "${cudatoolkit}" printf "* Installing torchaudio\n" -python setup.py develop +python setup.py install diff --git a/.circleci/unittest/windows/scripts/run_test.sh b/.circleci/unittest/windows/scripts/run_test.sh index 252c1e9f46..7fdd1d4c6d 100644 --- a/.circleci/unittest/windows/scripts/run_test.sh +++ b/.circleci/unittest/windows/scripts/run_test.sh @@ -6,5 +6,5 @@ eval "$(./conda/Scripts/conda.exe 'shell.bash' 'hook')" conda activate ./env python -m torch.utils.collect_env -pytest --cov=torchaudio --junitxml=test-results/junit.xml -v --durations 20 test -flake8 torchaudio test +cd test +pytest --cov=torchaudio --junitxml=../test-results/junit.xml -v --durations 20 torchaudio_unittest diff --git a/README.md b/README.md index 290bb73543..70f30be243 100644 --- a/README.md +++ b/README.md @@ -37,6 +37,7 @@ The following is the corresponding ``torchaudio`` versions and supported Python | ``torch`` | ``torchaudio`` | ``python`` | | ------------------------ | ------------------------ | ------------------------------- | | ``master`` / ``nightly`` | ``master`` / ``nightly`` | ``>=3.6`` | +| ``1.6.0`` | ``0.6.0`` | ``>=3.6`` | | ``1.5.0`` | ``0.5.0`` | ``>=3.5`` | | ``1.4.0`` | ``0.4.0`` | ``==2.7``, ``>=3.5``, ``<=3.8`` | diff --git a/docs/source/functional.rst b/docs/source/functional.rst index 12ee165060..89e992bb89 100644 --- a/docs/source/functional.rst +++ b/docs/source/functional.rst @@ -8,11 +8,6 @@ torchaudio.functional Functions to perform common audio operations. -:hidden:`istft` -~~~~~~~~~~~~~~~ - -.. autofunction:: istft - :hidden:`spectrogram` ~~~~~~~~~~~~~~~~~~~~~ diff --git a/docs/source/models.rst b/docs/source/models.rst index 5b40482976..44eb74444a 100644 --- a/docs/source/models.rst +++ b/docs/source/models.rst @@ -15,3 +15,11 @@ The models subpackage contains definitions of models for addressing common audio .. autoclass:: Wav2Letter .. automethod:: forward + + +:hidden:`WaveRNN` +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +.. autoclass:: WaveRNN + + .. automethod:: forward diff --git a/examples/pipeline_wavernn/datasets.py b/examples/pipeline_wavernn/datasets.py index 8d3068a229..58c2853f3d 100644 --- a/examples/pipeline_wavernn/datasets.py +++ b/examples/pipeline_wavernn/datasets.py @@ -4,7 +4,7 @@ import torch import torchaudio from torch.utils.data.dataset import random_split -from torchaudio.datasets import LJSPEECH +from torchaudio.datasets import LJSPEECH, LIBRITTS from torchaudio.transforms import MuLawEncoding from processing import bits_to_normalized_waveform, normalized_waveform_to_bits @@ -48,12 +48,20 @@ def process_datapoint(self, item): return item[0].squeeze(0), specgram -def split_process_ljspeech(args, transforms): - data = LJSPEECH(root=args.file_path, download=False) +def split_process_dataset(args, transforms): + if args.dataset == 'ljspeech': + data = LJSPEECH(root=args.file_path, download=False) - val_length = int(len(data) * args.val_ratio) - lengths = [len(data) - val_length, val_length] - train_dataset, val_dataset = random_split(data, lengths) + val_length = int(len(data) * args.val_ratio) + lengths = [len(data) - val_length, val_length] + train_dataset, val_dataset = random_split(data, lengths) + + elif args.dataset == 'libritts': + train_dataset = LIBRITTS(root=args.file_path, url='train-clean-100', download=False) + val_dataset = LIBRITTS(root=args.file_path, url='dev-clean', download=False) + + else: + raise ValueError(f"Expected dataset: `ljspeech` or `libritts`, but found {args.dataset}") train_dataset = Processed(train_dataset, transforms) val_dataset = Processed(val_dataset, transforms) diff --git a/examples/pipeline_wavernn/main.py b/examples/pipeline_wavernn/main.py index 032e9fc70e..9620dd5d45 100644 --- a/examples/pipeline_wavernn/main.py +++ b/examples/pipeline_wavernn/main.py @@ -13,9 +13,9 @@ from torch.optim import Adam from torch.utils.data import DataLoader from torchaudio.datasets.utils import bg_iterator -from torchaudio.models._wavernn import _WaveRNN +from torchaudio.models.wavernn import WaveRNN -from datasets import collate_factory, split_process_ljspeech +from datasets import collate_factory, split_process_dataset from losses import LongCrossEntropyLoss, MoLLoss from processing import LinearToMel, NormalizeDB from utils import MetricLogger, count_parameters, save_checkpoint @@ -55,6 +55,13 @@ def parse_args(): metavar="N", help="print frequency in epochs", ) + parser.add_argument( + "--dataset", + default="ljspeech", + choices=["ljspeech", "libritts"], + type=str, + help="select dataset to train with", + ) parser.add_argument( "--batch-size", default=256, type=int, metavar="N", help="mini-batch size" ) @@ -269,7 +276,7 @@ def main(args): NormalizeDB(min_level_db=args.min_level_db), ) - train_dataset, val_dataset = split_process_ljspeech(args, transforms) + train_dataset, val_dataset = split_process_dataset(args, transforms) loader_training_params = { "num_workers": args.workers, @@ -297,7 +304,7 @@ def main(args): n_classes = 2 ** args.n_bits if args.loss == "crossentropy" else 30 - model = _WaveRNN( + model = WaveRNN( upsample_scales=args.upsample_scales, n_classes=n_classes, hop_length=args.hop_length, diff --git a/setup.py b/setup.py index aab59b4d8a..0773b23107 100644 --- a/setup.py +++ b/setup.py @@ -3,8 +3,8 @@ import shutil import subprocess from pathlib import Path -import distutils.command.clean from setuptools import setup, find_packages +import distutils.command.clean from build_tools import setup_helpers @@ -85,5 +85,6 @@ def run(self): cmdclass={ 'build_ext': setup_helpers.BuildExtension.with_options(no_python_abi_suffix=True) }, - install_requires=[pytorch_package_dep] + install_requires=[pytorch_package_dep], + zip_safe=False, ) diff --git a/test/README.md b/test/README.md index c0a4b2a21d..629e5b54be 100644 --- a/test/README.md +++ b/test/README.md @@ -1,5 +1,27 @@ # Torchaudio Test Suite +## How to run test + +You can use `pytest` to run `torchaudio`'s test suites. See https://docs.pytest.org/ for the detail of how to use `pytest` command. + +``` +# List up all the tests +pytest test --collect-only +# Run all the test suites +pytest test +# Run tests on sox_effects module +pytest test/sox_effect +# use -k to apply filter +pytest test/sox_io_backend -k load # only runs tests where their names contain load +# Some other useful options; +# Stop on the first failure -x +# Run failure fast --ff +# Only rerun the failure --lf +``` + +**Note** +We use PyTorch's test utilities instead of `pytest` frameworks when writing tests to avoid reinventing the wheel for Tensor comparison. + ## Structure of tests The following is an overview of the tests and related modules for `torchaudio`. @@ -7,39 +29,39 @@ The following is an overview of the tests and related modules for `torchaudio`. ### Purpose specific test suites #### Numerical compatibility agains existing software -- [Librosa compatibility test](./test_librosa_compatibility.py) +- [Librosa compatibility test](./torchaudio_unittest/librosa_compatibility_test.py) Test suite for numerical compatibility against librosa. -- [SoX compatibility test](./test_sox_compatibility.py) +- [SoX compatibility test](./torchaudio_unittest/sox_compatibility_test.py) Test suite for numerical compatibility against SoX. -- [Kaldi compatibility test](./test_kaldi_compatibility.py) +- [Kaldi compatibility test](./torchaudio_unittest/kaldi_compatibility_test.py) Test suite for numerical compatibility against Kaldi. #### Result consistency with PyTorch framework -- [TorchScript consistency test](./test_torchscript_consistency.py) +- [TorchScript consistency test](./torchaudio_unittest/torchscript_consistency_impl.py) Test suite to check 1. if an API is TorchScript-able, and 2. the results from Python and Torchscript match. -- [Batch consistency test](./test_batch_consistency.py) +- [Batch consistency test](./torchaudio_unittest/batch_consistency_test.py) Test suite to check if functionals/Transforms handle single sample input and batch input and return the same result. ### Module specific test suites The following test modules are defined for corresponding `torchaudio` module/functions. -- [`torchaudio.datasets`](./test_datasets.py) -- [`torchaudio.functional`](./test_functional.py) -- [`torchaudio.transforms`](./test_transforms.py) -- [`torchaudio.compliance.kaldi`](./test_compliance_kaldi.py) -- [`torchaudio.kaldi_io`](./test_kaldi_io.py) +- [`torchaudio.datasets`](./torchaudio_unittest/datasets) +- [`torchaudio.functional`](./torchaudio_unittest/functional) +- [`torchaudio.transforms`](./torchaudio_unittest/transforms_test.py) +- [`torchaudio.compliance.kaldi`](./torchaudio_unittest/compliance_kaldi_test.py) +- [`torchaudio.kaldi_io`](./torchaudio_unittest/kaldi_io_test.py) - [`torchaudio.sox_effects`](test/sox_effects) -- [`torchaudio.save`, `torchaudio.load`, `torchaudio.info`](test/test_io.py) +- [`torchaudio.save`, `torchaudio.load`, `torchaudio.info`](./torchaudio_unittest/io_test.py) ### Test modules that do not fall into the above categories -- [test_dataloader.py](./test_dataloader.py) +- [test_dataloader.py](./torchaudio_unittest/dataloader_test.py) Simple test for loading data and applying preprocessing. ### Support files -- [assets](./assets): Contain sample audio files. -- [assets/kaldi](./assets/kaldi): Contains Kaldi format matrix files used in [./test_compliance_kaldi.py](./test_compliance_kaldi.py). -- [compliance](./compliance): Scripts used to generate above Kaldi matrix files. +- [assets](./torchaudio_unittest/assets): Contain sample audio files. +- [assets/kaldi](./torchaudio_unittest/assets/kaldi): Contains Kaldi format matrix files used in [./torchaudio_unittest/test_compliance_kaldi.py](./torchaudio_unittest/test_compliance_kaldi.py). +- [compliance](./torchaudio_unittest/compliance): Scripts used to generate above Kaldi matrix files. ### Waveforms for Testing Purposes @@ -86,11 +108,7 @@ Files: Files: * `CommonVoice/cv-corpus-4-2019-12-10/tt/clips/common_voice_tt_00000000.wav` -* `LibriSpeech/dev-clean/1272/128104/1272-128104-0000.flac` -* `LJSpeech-1.1/wavs/LJ001-0001.wav` -* `SpeechCommands/speech_commands_v0.02/go/0a9f9af7_nohash_0.wav` * `VCTK-Corpus/wav48/p224/p224_002.wav` -* `waves_yesno/0_1_0_1_0_1_1_0.wav` * `vad-go-stereo-44100.wav` * `vad-go-mono-32000.wav` @@ -98,13 +116,13 @@ Files: The following is the current practice of torchaudio test suite. -1. Unless the tests are related to I/O, use synthetic data. [`common_utils`](./common_utils.py) has some data generator functions. +1. Unless the tests are related to I/O, use synthetic data. [`common_utils`](./torchaudio_unittest/common_utils) has some data generator functions. 1. When you add a new test case, use `common_utils.TorchaudioTestCase` as base class unless you are writing tests that are common to CPU / CUDA. - Set class memeber `dtype`, `device` and `backend` for the desired behavior. - If you do not set `backend` value in your test suite, then I/O functions will be unassigned and attempt to load/save file will fail. - For `backend` value, in addition to available backends, you can also provide the value "default" and backend will be picked automatically based on availability. -1. If you are writing tests that should pass on diffrent dtype/devices, write a common class inheriting `common_utils.TestBaseMixin`, then inherit `common_utils.PytorchTestCase` and define class attributes (`dtype` / `device` / `backend`) there. See [Torchscript consistency test implementation](./torchscript_consistency_impl.py) and test definitions for [CPU](./torchscript_consistency_cpu_test.py) and [CUDA](./torchscript_consistency_cuda_test.py) devices. -1. For numerically comparing Tensors, use `assertEqual` method from `common_utils.PytorchTestCase` class. This method has a better support for a wide variety of Tensor types. +1. If you are writing tests that should pass on diffrent dtype/devices, write a common class inheriting `common_utils.TestBaseMixin`, then inherit `common_utils.PytorchTestCase` and define class attributes (`dtype` / `device` / `backend`) there. See [Torchscript consistency test implementation](./torchaudio_unittest/torchscript_consistency_impl.py) and test definitions for [CPU](./torchaudio_unittest/torchscript_consistency_cpu_test.py) and [CUDA](./torchaudio_unittest/torchscript_consistency_cuda_test.py) devices. +1. For numerically comparing Tensors, use `assertEqual` method from torchaudio_unittest.common_utils.PytorchTestCase` class. This method has a better support for a wide variety of Tensor types. When you add a new feature(functional/transform), consider the following diff --git a/test/assets/ARCTIC/cmu_us_aew_arctic/etc/txt.done.data b/test/assets/ARCTIC/cmu_us_aew_arctic/etc/txt.done.data deleted file mode 100644 index b6a7aa90ba..0000000000 --- a/test/assets/ARCTIC/cmu_us_aew_arctic/etc/txt.done.data +++ /dev/null @@ -1 +0,0 @@ -( arctic_a0024 "This is the test text." ) diff --git a/test/assets/ARCTIC/cmu_us_aew_arctic/wav/arctic_a0024.wav b/test/assets/ARCTIC/cmu_us_aew_arctic/wav/arctic_a0024.wav deleted file mode 100644 index b95ce95776fafd3e3cbaf670153f8d73167dfab3..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 441078 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

CSAV+5*9;R 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

Cz3T@ze3!6w*(fHW_fV9=% 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

=l)=@v0H>7mWgJuOT2YmGi<=T(XdH(r)*H! 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 X!?&c0&tuxMijB9q4^us!wT# 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�LI#YTvzcVN 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�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ƅF&C=B=rs{zF#5!EC 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 diff --git a/test/assets/LibriSpeech/dev-clean/1272/128104/1272-128104-0000.flac b/test/assets/LibriSpeech/dev-clean/1272/128104/1272-128104-0000.flac deleted file mode 100644 index 3b0c844f12abe55b7988eeb62f8553384b0d764f..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 120041 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

H(JwXuG5sxGPCe?AL|gMk1TijE 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 diff --git a/test/assets/LibriSpeech/dev-clean/1272/128104/1272-128104.trans.txt b/test/assets/LibriSpeech/dev-clean/1272/128104/1272-128104.trans.txt deleted file mode 100644 index 57bf5c5086..0000000000 --- a/test/assets/LibriSpeech/dev-clean/1272/128104/1272-128104.trans.txt +++ /dev/null @@ -1 +0,0 @@ -1272-128104-0000 MISTER QUILTER diff --git a/test/assets/SpeechCommands/speech_commands_v0.02/go/0a9f9af7_nohash_0.wav b/test/assets/SpeechCommands/speech_commands_v0.02/go/0a9f9af7_nohash_0.wav deleted file mode 100644 index 5ca06c9282ddd884af34e319d50561f1c46688b7..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 27352 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 P-k4=vBg5&3AZY#vXap6N diff --git a/test/common_utils/backend_utils.py b/test/common_utils/backend_utils.py deleted file mode 100644 index beceb6cafb..0000000000 --- a/test/common_utils/backend_utils.py +++ /dev/null @@ -1,41 +0,0 @@ -import unittest - -import torchaudio - -from .import data_utils - - -BACKENDS = torchaudio.list_audio_backends() - - -def _filter_backends_with_mp3(backends): - # Filter out backends that do not support mp3 - test_filepath = data_utils.get_asset_path('steam-train-whistle-daniel_simon.mp3') - - def supports_mp3(backend): - torchaudio.set_audio_backend(backend) - try: - torchaudio.load(test_filepath) - return True - except (RuntimeError, ImportError): - return False - - return [backend for backend in backends if supports_mp3(backend)] - - -BACKENDS_MP3 = _filter_backends_with_mp3(BACKENDS) - - -def set_audio_backend(backend): - """Allow additional backend value, 'default'""" - if backend == 'default': - if 'sox_io' in BACKENDS: - be = 'sox_io' - elif 'soundfile' in BACKENDS: - be = 'soundfile' - else: - raise unittest.SkipTest('No default backend available') - else: - be = backend - - torchaudio.set_audio_backend(be) diff --git a/test/datasets/datasets_test.py b/test/datasets/datasets_test.py deleted file mode 100644 index b8a980f346..0000000000 --- a/test/datasets/datasets_test.py +++ /dev/null @@ -1,60 +0,0 @@ -from torchaudio.datasets.commonvoice import COMMONVOICE -from torchaudio.datasets.librispeech import LIBRISPEECH -from torchaudio.datasets.speechcommands import SPEECHCOMMANDS -from torchaudio.datasets.utils import diskcache_iterator, bg_iterator -from torchaudio.datasets.vctk import VCTK -from torchaudio.datasets.ljspeech import LJSPEECH -from torchaudio.datasets.cmuarctic import CMUARCTIC - -from ..common_utils import ( - TorchaudioTestCase, - get_asset_path, -) - - -class TestDatasets(TorchaudioTestCase): - backend = 'default' - path = get_asset_path() - - def test_vctk(self): - data = VCTK(self.path) - data[0] - - def test_librispeech(self): - data = LIBRISPEECH(self.path, "dev-clean") - data[0] - - def test_ljspeech(self): - data = LJSPEECH(self.path) - data[0] - - def test_speechcommands(self): - data = SPEECHCOMMANDS(self.path) - data[0] - - def test_cmuarctic(self): - data = CMUARCTIC(self.path) - data[0] - - -class TestCommonVoice(TorchaudioTestCase): - backend = 'default' - path = get_asset_path() - - def test_commonvoice(self): - data = COMMONVOICE(self.path, url="tatar") - data[0] - - def test_commonvoice_diskcache(self): - data = COMMONVOICE(self.path, url="tatar") - data = diskcache_iterator(data) - # Save - data[0] - # Load - data[0] - - def test_commonvoice_bg(self): - data = COMMONVOICE(self.path, url="tatar") - data = bg_iterator(data, 5) - for _ in data: - pass diff --git a/test/functional_cpu_test.py b/test/functional_cpu_test.py deleted file mode 100644 index b162df2ebc..0000000000 --- a/test/functional_cpu_test.py +++ /dev/null @@ -1,407 +0,0 @@ -import math -import unittest - -import torch -import torchaudio -import torchaudio.functional as F -from parameterized import parameterized -import pytest - -from . import common_utils -from .functional_impl import Lfilter - - -def random_float_tensor(seed, size, a=22695477, c=1, m=2 ** 32): - """ Generates random tensors given a seed and size - https://en.wikipedia.org/wiki/Linear_congruential_generator - X_{n + 1} = (a * X_n + c) % m - Using Borland C/C++ values - - The tensor will have values between [0,1) - Inputs: - seed (int): an int - size (Tuple[int]): the size of the output tensor - a (int): the multiplier constant to the generator - c (int): the additive constant to the generator - m (int): the modulus constant to the generator - """ - num_elements = 1 - for s in size: - num_elements *= s - - arr = [(a * seed + c) % m] - for i in range(num_elements - 1): - arr.append((a * arr[i] + c) % m) - - return torch.tensor(arr).float().view(size) / m - - -class TestLFilterFloat32(Lfilter, common_utils.PytorchTestCase): - dtype = torch.float32 - device = torch.device('cpu') - - -class TestLFilterFloat64(Lfilter, common_utils.PytorchTestCase): - dtype = torch.float64 - device = torch.device('cpu') - - -class TestComputeDeltas(common_utils.TorchaudioTestCase): - """Test suite for correctness of compute_deltas""" - def test_one_channel(self): - specgram = torch.tensor([[[1.0, 2.0, 3.0, 4.0]]]) - expected = torch.tensor([[[0.5, 1.0, 1.0, 0.5]]]) - computed = F.compute_deltas(specgram, win_length=3) - torch.testing.assert_allclose(computed, expected) - - def test_two_channels(self): - specgram = torch.tensor([[[1.0, 2.0, 3.0, 4.0], - [1.0, 2.0, 3.0, 4.0]]]) - expected = torch.tensor([[[0.5, 1.0, 1.0, 0.5], - [0.5, 1.0, 1.0, 0.5]]]) - computed = F.compute_deltas(specgram, win_length=3) - torch.testing.assert_allclose(computed, expected) - - -def _compare_estimate(sound, estimate, atol=1e-6, rtol=1e-8): - # trim sound for case when constructed signal is shorter than original - sound = sound[..., :estimate.size(-1)] - torch.testing.assert_allclose(estimate, sound, atol=atol, rtol=rtol) - - -def _test_istft_is_inverse_of_stft(kwargs): - # generates a random sound signal for each tril and then does the stft/istft - # operation to check whether we can reconstruct signal - for data_size in [(2, 20), (3, 15), (4, 10)]: - for i in range(100): - - sound = random_float_tensor(i, data_size) - - stft = torch.stft(sound, **kwargs) - estimate = torchaudio.functional.istft(stft, length=sound.size(1), **kwargs) - - _compare_estimate(sound, estimate) - - -class TestIstft(common_utils.TorchaudioTestCase): - """Test suite for correctness of istft with various input""" - number_of_trials = 100 - - def test_istft_is_inverse_of_stft1(self): - # hann_window, centered, normalized, onesided - kwargs1 = { - 'n_fft': 12, - 'hop_length': 4, - 'win_length': 12, - 'window': torch.hann_window(12), - 'center': True, - 'pad_mode': 'reflect', - 'normalized': True, - 'onesided': True, - } - _test_istft_is_inverse_of_stft(kwargs1) - - def test_istft_is_inverse_of_stft2(self): - # hann_window, centered, not normalized, not onesided - kwargs2 = { - 'n_fft': 12, - 'hop_length': 2, - 'win_length': 8, - 'window': torch.hann_window(8), - 'center': True, - 'pad_mode': 'reflect', - 'normalized': False, - 'onesided': False, - } - _test_istft_is_inverse_of_stft(kwargs2) - - def test_istft_is_inverse_of_stft3(self): - # hamming_window, centered, normalized, not onesided - kwargs3 = { - 'n_fft': 15, - 'hop_length': 3, - 'win_length': 11, - 'window': torch.hamming_window(11), - 'center': True, - 'pad_mode': 'constant', - 'normalized': True, - 'onesided': False, - } - _test_istft_is_inverse_of_stft(kwargs3) - - def test_istft_is_inverse_of_stft4(self): - # hamming_window, not centered, not normalized, onesided - # window same size as n_fft - kwargs4 = { - 'n_fft': 5, - 'hop_length': 2, - 'win_length': 5, - 'window': torch.hamming_window(5), - 'center': False, - 'pad_mode': 'constant', - 'normalized': False, - 'onesided': True, - } - _test_istft_is_inverse_of_stft(kwargs4) - - def test_istft_is_inverse_of_stft5(self): - # hamming_window, not centered, not normalized, not onesided - # window same size as n_fft - kwargs5 = { - 'n_fft': 3, - 'hop_length': 2, - 'win_length': 3, - 'window': torch.hamming_window(3), - 'center': False, - 'pad_mode': 'reflect', - 'normalized': False, - 'onesided': False, - } - _test_istft_is_inverse_of_stft(kwargs5) - - def test_istft_of_ones(self): - # stft = torch.stft(torch.ones(4), 4) - stft = torch.tensor([ - [[4., 0.], [4., 0.], [4., 0.], [4., 0.], [4., 0.]], - [[0., 0.], [0., 0.], [0., 0.], [0., 0.], [0., 0.]], - [[0., 0.], [0., 0.], [0., 0.], [0., 0.], [0., 0.]] - ]) - - estimate = torchaudio.functional.istft(stft, n_fft=4, length=4) - _compare_estimate(torch.ones(4), estimate) - - def test_istft_of_zeros(self): - # stft = torch.stft(torch.zeros(4), 4) - stft = torch.zeros((3, 5, 2)) - - estimate = torchaudio.functional.istft(stft, n_fft=4, length=4) - _compare_estimate(torch.zeros(4), estimate) - - def test_istft_requires_overlap_windows(self): - # the window is size 1 but it hops 20 so there is a gap which throw an error - stft = torch.zeros((3, 5, 2)) - self.assertRaises(RuntimeError, torchaudio.functional.istft, stft, n_fft=4, - hop_length=20, win_length=1, window=torch.ones(1)) - - def test_istft_requires_nola(self): - stft = torch.zeros((3, 5, 2)) - kwargs_ok = { - 'n_fft': 4, - 'win_length': 4, - 'window': torch.ones(4), - } - - kwargs_not_ok = { - 'n_fft': 4, - 'win_length': 4, - 'window': torch.zeros(4), - } - - # A window of ones meets NOLA but a window of zeros does not. This should - # throw an error. - torchaudio.functional.istft(stft, **kwargs_ok) - self.assertRaises(RuntimeError, torchaudio.functional.istft, stft, **kwargs_not_ok) - - def test_istft_requires_non_empty(self): - self.assertRaises(RuntimeError, torchaudio.functional.istft, torch.zeros((3, 0, 2)), 2) - self.assertRaises(RuntimeError, torchaudio.functional.istft, torch.zeros((0, 3, 2)), 2) - - def _test_istft_of_sine(self, amplitude, L, n): - # stft of amplitude*sin(2*pi/L*n*x) with the hop length and window size equaling L - x = torch.arange(2 * L + 1, dtype=torch.get_default_dtype()) - sound = amplitude * torch.sin(2 * math.pi / L * x * n) - # stft = torch.stft(sound, L, hop_length=L, win_length=L, - # window=torch.ones(L), center=False, normalized=False) - stft = torch.zeros((L // 2 + 1, 2, 2)) - stft_largest_val = (amplitude * L) / 2.0 - if n < stft.size(0): - stft[n, :, 1] = -stft_largest_val - - if 0 <= L - n < stft.size(0): - # symmetric about L // 2 - stft[L - n, :, 1] = stft_largest_val - - estimate = torchaudio.functional.istft(stft, L, hop_length=L, win_length=L, - window=torch.ones(L), center=False, normalized=False) - # There is a larger error due to the scaling of amplitude - _compare_estimate(sound, estimate, atol=1e-3) - - def test_istft_of_sine(self): - self._test_istft_of_sine(amplitude=123, L=5, n=1) - self._test_istft_of_sine(amplitude=150, L=5, n=2) - self._test_istft_of_sine(amplitude=111, L=5, n=3) - self._test_istft_of_sine(amplitude=160, L=7, n=4) - self._test_istft_of_sine(amplitude=145, L=8, n=5) - self._test_istft_of_sine(amplitude=80, L=9, n=6) - self._test_istft_of_sine(amplitude=99, L=10, n=7) - - def _test_linearity_of_istft(self, data_size, kwargs, atol=1e-6, rtol=1e-8): - for i in range(self.number_of_trials): - tensor1 = random_float_tensor(i, data_size) - tensor2 = random_float_tensor(i * 2, data_size) - a, b = torch.rand(2) - istft1 = torchaudio.functional.istft(tensor1, **kwargs) - istft2 = torchaudio.functional.istft(tensor2, **kwargs) - istft = a * istft1 + b * istft2 - estimate = torchaudio.functional.istft(a * tensor1 + b * tensor2, **kwargs) - _compare_estimate(istft, estimate, atol, rtol) - - def test_linearity_of_istft1(self): - # hann_window, centered, normalized, onesided - kwargs1 = { - 'n_fft': 12, - 'window': torch.hann_window(12), - 'center': True, - 'pad_mode': 'reflect', - 'normalized': True, - 'onesided': True, - } - data_size = (2, 7, 7, 2) - self._test_linearity_of_istft(data_size, kwargs1) - - def test_linearity_of_istft2(self): - # hann_window, centered, not normalized, not onesided - kwargs2 = { - 'n_fft': 12, - 'window': torch.hann_window(12), - 'center': True, - 'pad_mode': 'reflect', - 'normalized': False, - 'onesided': False, - } - data_size = (2, 12, 7, 2) - self._test_linearity_of_istft(data_size, kwargs2) - - def test_linearity_of_istft3(self): - # hamming_window, centered, normalized, not onesided - kwargs3 = { - 'n_fft': 12, - 'window': torch.hamming_window(12), - 'center': True, - 'pad_mode': 'constant', - 'normalized': True, - 'onesided': False, - } - data_size = (2, 12, 7, 2) - self._test_linearity_of_istft(data_size, kwargs3) - - def test_linearity_of_istft4(self): - # hamming_window, not centered, not normalized, onesided - kwargs4 = { - 'n_fft': 12, - 'window': torch.hamming_window(12), - 'center': False, - 'pad_mode': 'constant', - 'normalized': False, - 'onesided': True, - } - data_size = (2, 7, 3, 2) - self._test_linearity_of_istft(data_size, kwargs4, atol=1e-5, rtol=1e-8) - - -class TestDetectPitchFrequency(common_utils.TorchaudioTestCase): - @parameterized.expand([(100,), (440,)]) - def test_pitch(self, frequency): - sample_rate = 44100 - test_sine_waveform = common_utils.get_sinusoid( - frequency=frequency, sample_rate=sample_rate, duration=5, - ) - - freq = torchaudio.functional.detect_pitch_frequency(test_sine_waveform, sample_rate) - - threshold = 1 - s = ((freq - frequency).abs() > threshold).sum() - self.assertFalse(s) - - -class TestDB_to_amplitude(common_utils.TorchaudioTestCase): - def test_DB_to_amplitude(self): - # Make some noise - x = torch.rand(1000) - spectrogram = torchaudio.transforms.Spectrogram() - spec = spectrogram(x) - - amin = 1e-10 - ref = 1.0 - db_multiplier = math.log10(max(amin, ref)) - - # Waveform amplitude -> DB -> amplitude - multiplier = 20. - power = 0.5 - - db = F.amplitude_to_DB(torch.abs(x), multiplier, amin, db_multiplier, top_db=None) - x2 = F.DB_to_amplitude(db, ref, power) - - torch.testing.assert_allclose(x2, torch.abs(x), atol=5e-5, rtol=1e-5) - - # Spectrogram amplitude -> DB -> amplitude - db = F.amplitude_to_DB(spec, multiplier, amin, db_multiplier, top_db=None) - x2 = F.DB_to_amplitude(db, ref, power) - - torch.testing.assert_allclose(x2, spec, atol=5e-5, rtol=1e-5) - - # Waveform power -> DB -> power - multiplier = 10. - power = 1. - - db = F.amplitude_to_DB(x, multiplier, amin, db_multiplier, top_db=None) - x2 = F.DB_to_amplitude(db, ref, power) - - torch.testing.assert_allclose(x2, torch.abs(x), atol=5e-5, rtol=1e-5) - - # Spectrogram power -> DB -> power - db = F.amplitude_to_DB(spec, multiplier, amin, db_multiplier, top_db=None) - x2 = F.DB_to_amplitude(db, ref, power) - - torch.testing.assert_allclose(x2, spec, atol=5e-5, rtol=1e-5) - - -@pytest.mark.parametrize('complex_tensor', [ - torch.randn(1, 2, 1025, 400, 2), - torch.randn(1025, 400, 2) -]) -@pytest.mark.parametrize('power', [1, 2, 0.7]) -def test_complex_norm(complex_tensor, power): - expected_norm_tensor = complex_tensor.pow(2).sum(-1).pow(power / 2) - norm_tensor = F.complex_norm(complex_tensor, power) - - torch.testing.assert_allclose(norm_tensor, expected_norm_tensor, atol=1e-5, rtol=1e-5) - - -@pytest.mark.parametrize('specgram', [ - torch.randn(2, 1025, 400), - torch.randn(1, 201, 100) -]) -@pytest.mark.parametrize('mask_param', [100]) -@pytest.mark.parametrize('mask_value', [0., 30.]) -@pytest.mark.parametrize('axis', [1, 2]) -def test_mask_along_axis(specgram, mask_param, mask_value, axis): - - mask_specgram = F.mask_along_axis(specgram, mask_param, mask_value, axis) - - other_axis = 1 if axis == 2 else 2 - - masked_columns = (mask_specgram == mask_value).sum(other_axis) - num_masked_columns = (masked_columns == mask_specgram.size(other_axis)).sum() - num_masked_columns //= mask_specgram.size(0) - - assert mask_specgram.size() == specgram.size() - assert num_masked_columns < mask_param - - -@pytest.mark.parametrize('mask_param', [100]) -@pytest.mark.parametrize('mask_value', [0., 30.]) -@pytest.mark.parametrize('axis', [2, 3]) -def test_mask_along_axis_iid(mask_param, mask_value, axis): - torch.random.manual_seed(42) - specgrams = torch.randn(4, 2, 1025, 400) - - mask_specgrams = F.mask_along_axis_iid(specgrams, mask_param, mask_value, axis) - - other_axis = 2 if axis == 3 else 3 - - masked_columns = (mask_specgrams == mask_value).sum(other_axis) - num_masked_columns = (masked_columns == mask_specgrams.size(other_axis)).sum(-1) - - assert mask_specgrams.size() == specgrams.size() - assert (num_masked_columns < mask_param).sum() == num_masked_columns.numel() diff --git a/test/__init__.py b/test/torchaudio_unittest/__init__.py similarity index 100% rename from test/__init__.py rename to test/torchaudio_unittest/__init__.py diff --git a/test/assets/CommonVoice/cv-corpus-4-2019-12-10/tt/clips/common_voice_tt_00000000.wav b/test/torchaudio_unittest/assets/CommonVoice/cv-corpus-4-2019-12-10/tt/clips/common_voice_tt_00000000.wav similarity index 100% rename from test/assets/CommonVoice/cv-corpus-4-2019-12-10/tt/clips/common_voice_tt_00000000.wav rename to test/torchaudio_unittest/assets/CommonVoice/cv-corpus-4-2019-12-10/tt/clips/common_voice_tt_00000000.wav diff --git a/test/assets/CommonVoice/cv-corpus-4-2019-12-10/tt/train.tsv b/test/torchaudio_unittest/assets/CommonVoice/cv-corpus-4-2019-12-10/tt/train.tsv similarity index 100% rename from test/assets/CommonVoice/cv-corpus-4-2019-12-10/tt/train.tsv rename to test/torchaudio_unittest/assets/CommonVoice/cv-corpus-4-2019-12-10/tt/train.tsv diff --git a/test/assets/VCTK-Corpus/txt/p224/p224_002.txt b/test/torchaudio_unittest/assets/VCTK-Corpus/txt/p224/p224_002.txt similarity index 100% rename from test/assets/VCTK-Corpus/txt/p224/p224_002.txt rename to test/torchaudio_unittest/assets/VCTK-Corpus/txt/p224/p224_002.txt diff --git a/test/assets/VCTK-Corpus/wav48/p224/p224_002.wav b/test/torchaudio_unittest/assets/VCTK-Corpus/wav48/p224/p224_002.wav similarity index 100% rename from test/assets/VCTK-Corpus/wav48/p224/p224_002.wav rename to test/torchaudio_unittest/assets/VCTK-Corpus/wav48/p224/p224_002.wav diff --git a/test/assets/io/96k_0_1ch.opus b/test/torchaudio_unittest/assets/io/96k_0_1ch.opus similarity index 100% rename from test/assets/io/96k_0_1ch.opus rename to test/torchaudio_unittest/assets/io/96k_0_1ch.opus diff --git a/test/assets/io/96k_0_2ch.opus b/test/torchaudio_unittest/assets/io/96k_0_2ch.opus similarity index 100% rename from test/assets/io/96k_0_2ch.opus rename to test/torchaudio_unittest/assets/io/96k_0_2ch.opus diff --git a/test/assets/io/96k_10_1ch.opus b/test/torchaudio_unittest/assets/io/96k_10_1ch.opus similarity index 100% rename from test/assets/io/96k_10_1ch.opus rename to test/torchaudio_unittest/assets/io/96k_10_1ch.opus diff --git a/test/assets/io/96k_10_2ch.opus b/test/torchaudio_unittest/assets/io/96k_10_2ch.opus similarity index 100% rename from test/assets/io/96k_10_2ch.opus rename to test/torchaudio_unittest/assets/io/96k_10_2ch.opus diff --git a/test/assets/io/96k_5_1ch.opus b/test/torchaudio_unittest/assets/io/96k_5_1ch.opus similarity index 100% rename from test/assets/io/96k_5_1ch.opus rename to test/torchaudio_unittest/assets/io/96k_5_1ch.opus diff --git a/test/assets/io/96k_5_2ch.opus b/test/torchaudio_unittest/assets/io/96k_5_2ch.opus similarity index 100% rename from test/assets/io/96k_5_2ch.opus rename to test/torchaudio_unittest/assets/io/96k_5_2ch.opus diff --git a/test/assets/io/generate_opus.py b/test/torchaudio_unittest/assets/io/generate_opus.py similarity index 100% rename from test/assets/io/generate_opus.py rename to test/torchaudio_unittest/assets/io/generate_opus.py diff --git a/test/assets/kaldi/resample-16000-1000.ark b/test/torchaudio_unittest/assets/kaldi/resample-16000-1000.ark similarity index 100% rename from test/assets/kaldi/resample-16000-1000.ark rename to test/torchaudio_unittest/assets/kaldi/resample-16000-1000.ark diff --git a/test/assets/kaldi/resample-16000-10000.ark b/test/torchaudio_unittest/assets/kaldi/resample-16000-10000.ark similarity index 100% rename from test/assets/kaldi/resample-16000-10000.ark rename to test/torchaudio_unittest/assets/kaldi/resample-16000-10000.ark diff --git a/test/assets/kaldi/resample-16000-11000.ark b/test/torchaudio_unittest/assets/kaldi/resample-16000-11000.ark similarity index 100% rename from test/assets/kaldi/resample-16000-11000.ark rename to test/torchaudio_unittest/assets/kaldi/resample-16000-11000.ark diff --git a/test/assets/kaldi/resample-16000-12000.ark b/test/torchaudio_unittest/assets/kaldi/resample-16000-12000.ark similarity index 100% rename from test/assets/kaldi/resample-16000-12000.ark rename to test/torchaudio_unittest/assets/kaldi/resample-16000-12000.ark diff --git a/test/assets/kaldi/resample-16000-13000.ark b/test/torchaudio_unittest/assets/kaldi/resample-16000-13000.ark similarity index 100% rename from test/assets/kaldi/resample-16000-13000.ark rename to test/torchaudio_unittest/assets/kaldi/resample-16000-13000.ark diff --git a/test/assets/kaldi/resample-16000-14000.ark b/test/torchaudio_unittest/assets/kaldi/resample-16000-14000.ark similarity index 100% rename from test/assets/kaldi/resample-16000-14000.ark rename to test/torchaudio_unittest/assets/kaldi/resample-16000-14000.ark diff --git a/test/assets/kaldi/resample-16000-15000.ark b/test/torchaudio_unittest/assets/kaldi/resample-16000-15000.ark similarity index 100% rename from test/assets/kaldi/resample-16000-15000.ark rename to test/torchaudio_unittest/assets/kaldi/resample-16000-15000.ark diff --git a/test/assets/kaldi/resample-16000-16000.ark b/test/torchaudio_unittest/assets/kaldi/resample-16000-16000.ark similarity index 100% rename from test/assets/kaldi/resample-16000-16000.ark rename to test/torchaudio_unittest/assets/kaldi/resample-16000-16000.ark diff --git a/test/assets/kaldi/resample-16000-17000.ark b/test/torchaudio_unittest/assets/kaldi/resample-16000-17000.ark similarity index 100% rename from test/assets/kaldi/resample-16000-17000.ark rename to test/torchaudio_unittest/assets/kaldi/resample-16000-17000.ark diff --git a/test/assets/kaldi/resample-16000-18000.ark b/test/torchaudio_unittest/assets/kaldi/resample-16000-18000.ark similarity index 100% rename from test/assets/kaldi/resample-16000-18000.ark rename to test/torchaudio_unittest/assets/kaldi/resample-16000-18000.ark diff --git a/test/assets/kaldi/resample-16000-19000.ark b/test/torchaudio_unittest/assets/kaldi/resample-16000-19000.ark similarity index 100% rename from test/assets/kaldi/resample-16000-19000.ark rename to test/torchaudio_unittest/assets/kaldi/resample-16000-19000.ark diff --git a/test/assets/kaldi/resample-16000-2000.ark b/test/torchaudio_unittest/assets/kaldi/resample-16000-2000.ark similarity index 100% rename from test/assets/kaldi/resample-16000-2000.ark rename to test/torchaudio_unittest/assets/kaldi/resample-16000-2000.ark diff --git a/test/assets/kaldi/resample-16000-20000.ark b/test/torchaudio_unittest/assets/kaldi/resample-16000-20000.ark similarity index 100% rename from test/assets/kaldi/resample-16000-20000.ark rename to test/torchaudio_unittest/assets/kaldi/resample-16000-20000.ark diff --git a/test/assets/kaldi/resample-16000-21000.ark b/test/torchaudio_unittest/assets/kaldi/resample-16000-21000.ark similarity index 100% rename from test/assets/kaldi/resample-16000-21000.ark rename to test/torchaudio_unittest/assets/kaldi/resample-16000-21000.ark diff --git a/test/assets/kaldi/resample-16000-22000.ark b/test/torchaudio_unittest/assets/kaldi/resample-16000-22000.ark similarity index 100% rename from test/assets/kaldi/resample-16000-22000.ark rename to test/torchaudio_unittest/assets/kaldi/resample-16000-22000.ark diff --git a/test/assets/kaldi/resample-16000-23000.ark b/test/torchaudio_unittest/assets/kaldi/resample-16000-23000.ark similarity index 100% rename from test/assets/kaldi/resample-16000-23000.ark rename to test/torchaudio_unittest/assets/kaldi/resample-16000-23000.ark diff --git a/test/assets/kaldi/resample-16000-24000.ark b/test/torchaudio_unittest/assets/kaldi/resample-16000-24000.ark similarity index 100% rename from test/assets/kaldi/resample-16000-24000.ark rename to test/torchaudio_unittest/assets/kaldi/resample-16000-24000.ark diff --git a/test/assets/kaldi/resample-16000-25000.ark b/test/torchaudio_unittest/assets/kaldi/resample-16000-25000.ark similarity index 100% rename from test/assets/kaldi/resample-16000-25000.ark rename to test/torchaudio_unittest/assets/kaldi/resample-16000-25000.ark diff --git a/test/assets/kaldi/resample-16000-26000.ark b/test/torchaudio_unittest/assets/kaldi/resample-16000-26000.ark similarity index 100% rename from test/assets/kaldi/resample-16000-26000.ark rename to test/torchaudio_unittest/assets/kaldi/resample-16000-26000.ark diff --git a/test/assets/kaldi/resample-16000-27000.ark b/test/torchaudio_unittest/assets/kaldi/resample-16000-27000.ark similarity index 100% rename from test/assets/kaldi/resample-16000-27000.ark rename to test/torchaudio_unittest/assets/kaldi/resample-16000-27000.ark diff --git a/test/assets/kaldi/resample-16000-28000.ark b/test/torchaudio_unittest/assets/kaldi/resample-16000-28000.ark similarity index 100% rename from test/assets/kaldi/resample-16000-28000.ark rename to test/torchaudio_unittest/assets/kaldi/resample-16000-28000.ark diff --git a/test/assets/kaldi/resample-16000-29000.ark b/test/torchaudio_unittest/assets/kaldi/resample-16000-29000.ark similarity index 100% rename from test/assets/kaldi/resample-16000-29000.ark rename to test/torchaudio_unittest/assets/kaldi/resample-16000-29000.ark diff --git a/test/assets/kaldi/resample-16000-3000.ark b/test/torchaudio_unittest/assets/kaldi/resample-16000-3000.ark similarity index 100% rename from test/assets/kaldi/resample-16000-3000.ark rename to test/torchaudio_unittest/assets/kaldi/resample-16000-3000.ark diff --git a/test/assets/kaldi/resample-16000-30000.ark b/test/torchaudio_unittest/assets/kaldi/resample-16000-30000.ark similarity index 100% rename from test/assets/kaldi/resample-16000-30000.ark rename to test/torchaudio_unittest/assets/kaldi/resample-16000-30000.ark diff --git a/test/assets/kaldi/resample-16000-31000.ark b/test/torchaudio_unittest/assets/kaldi/resample-16000-31000.ark similarity index 100% rename from test/assets/kaldi/resample-16000-31000.ark rename to test/torchaudio_unittest/assets/kaldi/resample-16000-31000.ark diff --git a/test/assets/kaldi/resample-16000-32000.ark b/test/torchaudio_unittest/assets/kaldi/resample-16000-32000.ark similarity index 100% rename from test/assets/kaldi/resample-16000-32000.ark rename to test/torchaudio_unittest/assets/kaldi/resample-16000-32000.ark diff --git a/test/assets/kaldi/resample-16000-4000.ark b/test/torchaudio_unittest/assets/kaldi/resample-16000-4000.ark similarity index 100% rename from test/assets/kaldi/resample-16000-4000.ark rename to test/torchaudio_unittest/assets/kaldi/resample-16000-4000.ark diff --git a/test/assets/kaldi/resample-16000-5000.ark b/test/torchaudio_unittest/assets/kaldi/resample-16000-5000.ark similarity index 100% rename from test/assets/kaldi/resample-16000-5000.ark rename to test/torchaudio_unittest/assets/kaldi/resample-16000-5000.ark diff --git a/test/assets/kaldi/resample-16000-6000.ark b/test/torchaudio_unittest/assets/kaldi/resample-16000-6000.ark similarity index 100% rename from test/assets/kaldi/resample-16000-6000.ark rename to test/torchaudio_unittest/assets/kaldi/resample-16000-6000.ark diff --git a/test/assets/kaldi/resample-16000-7000.ark b/test/torchaudio_unittest/assets/kaldi/resample-16000-7000.ark similarity index 100% rename from test/assets/kaldi/resample-16000-7000.ark rename to test/torchaudio_unittest/assets/kaldi/resample-16000-7000.ark diff --git a/test/assets/kaldi/resample-16000-8000.ark b/test/torchaudio_unittest/assets/kaldi/resample-16000-8000.ark similarity index 100% rename from test/assets/kaldi/resample-16000-8000.ark rename to test/torchaudio_unittest/assets/kaldi/resample-16000-8000.ark diff --git a/test/assets/kaldi/resample-16000-9000.ark b/test/torchaudio_unittest/assets/kaldi/resample-16000-9000.ark similarity index 100% rename from test/assets/kaldi/resample-16000-9000.ark rename to test/torchaudio_unittest/assets/kaldi/resample-16000-9000.ark diff --git a/test/assets/kaldi_file.wav b/test/torchaudio_unittest/assets/kaldi_file.wav similarity index 100% rename from test/assets/kaldi_file.wav rename to test/torchaudio_unittest/assets/kaldi_file.wav diff --git a/test/assets/kaldi_file_8000.wav b/test/torchaudio_unittest/assets/kaldi_file_8000.wav similarity index 100% rename from test/assets/kaldi_file_8000.wav rename to test/torchaudio_unittest/assets/kaldi_file_8000.wav diff --git a/test/assets/kaldi_test_fbank_args.json b/test/torchaudio_unittest/assets/kaldi_test_fbank_args.json similarity index 100% rename from test/assets/kaldi_test_fbank_args.json rename to test/torchaudio_unittest/assets/kaldi_test_fbank_args.json diff --git a/test/assets/kaldi_test_mfcc_args.json b/test/torchaudio_unittest/assets/kaldi_test_mfcc_args.json similarity index 100% rename from test/assets/kaldi_test_mfcc_args.json rename to test/torchaudio_unittest/assets/kaldi_test_mfcc_args.json diff --git a/test/assets/kaldi_test_spectrogram_args.json b/test/torchaudio_unittest/assets/kaldi_test_spectrogram_args.json similarity index 100% rename from test/assets/kaldi_test_spectrogram_args.json rename to test/torchaudio_unittest/assets/kaldi_test_spectrogram_args.json diff --git a/test/assets/mat.ark b/test/torchaudio_unittest/assets/mat.ark similarity index 100% rename from test/assets/mat.ark rename to test/torchaudio_unittest/assets/mat.ark diff --git a/test/assets/sinewave.wav b/test/torchaudio_unittest/assets/sinewave.wav similarity index 100% rename from test/assets/sinewave.wav rename to test/torchaudio_unittest/assets/sinewave.wav diff --git a/test/assets/sox_effect_test_args.json b/test/torchaudio_unittest/assets/sox_effect_test_args.json similarity index 100% rename from test/assets/sox_effect_test_args.json rename to test/torchaudio_unittest/assets/sox_effect_test_args.json diff --git a/test/assets/sox_effect_test_fir_coeffs.txt b/test/torchaudio_unittest/assets/sox_effect_test_fir_coeffs.txt similarity index 100% rename from test/assets/sox_effect_test_fir_coeffs.txt rename to test/torchaudio_unittest/assets/sox_effect_test_fir_coeffs.txt diff --git a/test/assets/steam-train-whistle-daniel_simon.mp3 b/test/torchaudio_unittest/assets/steam-train-whistle-daniel_simon.mp3 similarity index 100% rename from test/assets/steam-train-whistle-daniel_simon.mp3 rename to test/torchaudio_unittest/assets/steam-train-whistle-daniel_simon.mp3 diff --git a/test/assets/steam-train-whistle-daniel_simon.wav b/test/torchaudio_unittest/assets/steam-train-whistle-daniel_simon.wav similarity index 100% rename from test/assets/steam-train-whistle-daniel_simon.wav rename to test/torchaudio_unittest/assets/steam-train-whistle-daniel_simon.wav diff --git a/test/assets/vad-go-mono-32000.wav b/test/torchaudio_unittest/assets/vad-go-mono-32000.wav similarity index 100% rename from test/assets/vad-go-mono-32000.wav rename to test/torchaudio_unittest/assets/vad-go-mono-32000.wav diff --git a/test/assets/vad-go-stereo-44100.wav b/test/torchaudio_unittest/assets/vad-go-stereo-44100.wav similarity index 100% rename from test/assets/vad-go-stereo-44100.wav rename to test/torchaudio_unittest/assets/vad-go-stereo-44100.wav diff --git a/test/assets/vec_flt.ark b/test/torchaudio_unittest/assets/vec_flt.ark similarity index 100% rename from test/assets/vec_flt.ark rename to test/torchaudio_unittest/assets/vec_flt.ark diff --git a/test/assets/vec_int.ark b/test/torchaudio_unittest/assets/vec_int.ark similarity index 100% rename from test/assets/vec_int.ark rename to test/torchaudio_unittest/assets/vec_int.ark diff --git a/test/test_backend.py b/test/torchaudio_unittest/backend_test.py similarity index 96% rename from test/test_backend.py rename to test/torchaudio_unittest/backend_test.py index 6b67cb2898..d7a2078a31 100644 --- a/test/test_backend.py +++ b/test/torchaudio_unittest/backend_test.py @@ -1,6 +1,6 @@ import torchaudio -from . import common_utils +from torchaudio_unittest import common_utils class BackendSwitchMixin: diff --git a/test/test_batch_consistency.py b/test/torchaudio_unittest/batch_consistency_test.py similarity index 96% rename from test/test_batch_consistency.py rename to test/torchaudio_unittest/batch_consistency_test.py index e7040fdc0b..696b714df1 100644 --- a/test/test_batch_consistency.py +++ b/test/torchaudio_unittest/batch_consistency_test.py @@ -7,7 +7,7 @@ import torchaudio import torchaudio.functional as F -from . import common_utils +from torchaudio_unittest import common_utils class TestFunctional(common_utils.TorchaudioTestCase): @@ -59,14 +59,6 @@ def test_detect_pitch_frequency(self, frequency, sample_rate, n_channels): n_channels=n_channels, duration=5) self.assert_batch_consistencies(F.detect_pitch_frequency, waveform, sample_rate) - def test_istft(self): - stft = torch.tensor([ - [[4., 0.], [4., 0.], [4., 0.], [4., 0.], [4., 0.]], - [[0., 0.], [0., 0.], [0., 0.], [0., 0.], [0., 0.]], - [[0., 0.], [0., 0.], [0., 0.], [0., 0.], [0., 0.]] - ]) - self.assert_batch_consistencies(F.istft, stft, n_fft=4, length=4) - def test_contrast(self): waveform = torch.rand(2, 100) - 0.5 self.assert_batch_consistencies(F.contrast, waveform, enhancement_amount=80.) diff --git a/test/common_utils/__init__.py b/test/torchaudio_unittest/common_utils/__init__.py similarity index 94% rename from test/common_utils/__init__.py rename to test/torchaudio_unittest/common_utils/__init__.py index 841cd26713..105a054864 100644 --- a/test/common_utils/__init__.py +++ b/test/torchaudio_unittest/common_utils/__init__.py @@ -5,8 +5,6 @@ ) from .backend_utils import ( set_audio_backend, - BACKENDS, - BACKENDS_MP3, ) from .case_utils import ( TempDirMixin, diff --git a/test/torchaudio_unittest/common_utils/backend_utils.py b/test/torchaudio_unittest/common_utils/backend_utils.py new file mode 100644 index 0000000000..7702a3d6f3 --- /dev/null +++ b/test/torchaudio_unittest/common_utils/backend_utils.py @@ -0,0 +1,19 @@ +import unittest + +import torchaudio + + +def set_audio_backend(backend): + """Allow additional backend value, 'default'""" + backends = torchaudio.list_audio_backends() + if backend == 'default': + if 'sox_io' in backends: + be = 'sox_io' + elif 'soundfile' in backends: + be = 'soundfile' + else: + raise unittest.SkipTest('No default backend available') + else: + be = backend + + torchaudio.set_audio_backend(be) diff --git a/test/common_utils/case_utils.py b/test/torchaudio_unittest/common_utils/case_utils.py similarity index 85% rename from test/common_utils/case_utils.py rename to test/torchaudio_unittest/common_utils/case_utils.py index 9c89ef6891..2e0a17b5da 100644 --- a/test/common_utils/case_utils.py +++ b/test/torchaudio_unittest/common_utils/case_utils.py @@ -67,4 +67,11 @@ def skipIfNoModule(module, display_name=None): skipIfNoSoxBackend = unittest.skipIf( 'sox' not in torchaudio.list_audio_backends(), 'Sox backend not available') skipIfNoCuda = unittest.skipIf(not torch.cuda.is_available(), reason='CUDA not available') -skipIfNoExtension = skipIfNoModule('torchaudio._torchaudio', 'torchaudio C++ extension') + + +def skipIfNoExtension(test_item): + if is_module_available('torchaudio._torchaudio'): + return test_item + if 'TORCHAUDIO_TEST_FAIL_IF_NO_EXTENSION' in os.environ: + raise RuntimeError('torchaudio C++ extension is not available.') + return unittest.skip('torchaudio C++ extension is not available')(test_item) diff --git a/test/common_utils/data_utils.py b/test/torchaudio_unittest/common_utils/data_utils.py similarity index 100% rename from test/common_utils/data_utils.py rename to test/torchaudio_unittest/common_utils/data_utils.py diff --git a/test/common_utils/parameterized_utils.py b/test/torchaudio_unittest/common_utils/parameterized_utils.py similarity index 100% rename from test/common_utils/parameterized_utils.py rename to test/torchaudio_unittest/common_utils/parameterized_utils.py diff --git a/test/common_utils/sox_utils.py b/test/torchaudio_unittest/common_utils/sox_utils.py similarity index 100% rename from test/common_utils/sox_utils.py rename to test/torchaudio_unittest/common_utils/sox_utils.py diff --git a/test/common_utils/wav_utils.py b/test/torchaudio_unittest/common_utils/wav_utils.py similarity index 100% rename from test/common_utils/wav_utils.py rename to test/torchaudio_unittest/common_utils/wav_utils.py diff --git a/test/compliance/__init__.py b/test/torchaudio_unittest/compliance/__init__.py similarity index 100% rename from test/compliance/__init__.py rename to test/torchaudio_unittest/compliance/__init__.py diff --git a/test/compliance/generate_fbank_data.py b/test/torchaudio_unittest/compliance/generate_fbank_data.py similarity index 98% rename from test/compliance/generate_fbank_data.py rename to test/torchaudio_unittest/compliance/generate_fbank_data.py index 446ebea284..96a935d116 100644 --- a/test/compliance/generate_fbank_data.py +++ b/test/torchaudio_unittest/compliance/generate_fbank_data.py @@ -92,7 +92,7 @@ def decode(fn, sound_path, exe_path, scp_path, out_dir): 'round_to_power_of_two', 'snip_edges', 'subtract_mean', 'use_energy', 'use_log_fbank', 'use_power', 'vtln_high', 'vtln_low', 'vtln_warp', 'window_type'] fn_split = fn.split('-') - assert len(fn_split) == len(arr), ('Len mismatch: %d and %d' % (len(fn_split), len(arr))) + assert len(fn_split) == len(arr), ('Len mismatch: {} and {}'.format(len(fn_split), len(arr))) inputs = {arr[i]: utils.parse(fn_split[i]) for i in range(len(arr))} # print flags for C++ diff --git a/test/compliance/generate_test_stft_data.py b/test/torchaudio_unittest/compliance/generate_test_stft_data.py similarity index 100% rename from test/compliance/generate_test_stft_data.py rename to test/torchaudio_unittest/compliance/generate_test_stft_data.py diff --git a/test/compliance/utils.py b/test/torchaudio_unittest/compliance/utils.py similarity index 100% rename from test/compliance/utils.py rename to test/torchaudio_unittest/compliance/utils.py diff --git a/test/test_compliance_kaldi.py b/test/torchaudio_unittest/compliance_kaldi_test.py similarity index 98% rename from test/test_compliance_kaldi.py rename to test/torchaudio_unittest/compliance_kaldi_test.py index 450183d6b3..43e9865e2f 100644 --- a/test/test_compliance_kaldi.py +++ b/test/torchaudio_unittest/compliance_kaldi_test.py @@ -6,7 +6,7 @@ import torchaudio import torchaudio.compliance.kaldi as kaldi -from . import common_utils +from torchaudio_unittest import common_utils from .compliance import utils as compliance_utils @@ -148,7 +148,9 @@ def _compliance_test_helper(self, sound_filepath, filepath_key, expected_num_fil sound, sr = torchaudio.load_wav(sound_filepath) files = self.test_filepaths[filepath_key] - assert len(files) == expected_num_files, ('number of kaldi %s file changed to %d' % (filepath_key, len(files))) + assert len(files) == expected_num_files, \ + ('number of kaldi {} file changed to {}'.format( + filepath_key, len(files))) for f in files: print(f) diff --git a/test/test_dataloader.py b/test/torchaudio_unittest/dataloader_test.py similarity index 96% rename from test/test_dataloader.py rename to test/torchaudio_unittest/dataloader_test.py index 6d1518b70c..8f1d7e6fb3 100644 --- a/test/test_dataloader.py +++ b/test/torchaudio_unittest/dataloader_test.py @@ -3,7 +3,7 @@ import torchaudio from torch.utils.data import Dataset, DataLoader -from . import common_utils +from torchaudio_unittest import common_utils class TORCHAUDIODS(Dataset): diff --git a/test/datasets/__init__.py b/test/torchaudio_unittest/datasets/__init__.py similarity index 100% rename from test/datasets/__init__.py rename to test/torchaudio_unittest/datasets/__init__.py diff --git a/test/torchaudio_unittest/datasets/cmuarctic_test.py b/test/torchaudio_unittest/datasets/cmuarctic_test.py new file mode 100644 index 0000000000..578b0ec385 --- /dev/null +++ b/test/torchaudio_unittest/datasets/cmuarctic_test.py @@ -0,0 +1,67 @@ +import os + +from torchaudio.datasets import cmuarctic + +from torchaudio_unittest.common_utils import ( + TempDirMixin, + TorchaudioTestCase, + get_whitenoise, + save_wav, + normalize_wav, +) + + +class TestCMUARCTIC(TempDirMixin, TorchaudioTestCase): + backend = "default" + + root_dir = None + samples = [] + + @classmethod + def setUpClass(cls): + cls.root_dir = cls.get_base_temp_dir() + sample_rate = 16000 + utterance = "This is a test utterance." + + base_dir = os.path.join(cls.root_dir, "ARCTIC", "cmu_us_aew_arctic") + txt_dir = os.path.join(base_dir, "etc") + os.makedirs(txt_dir, exist_ok=True) + txt_file = os.path.join(txt_dir, "txt.done.data") + audio_dir = os.path.join(base_dir, "wav") + os.makedirs(audio_dir, exist_ok=True) + + seed = 42 + with open(txt_file, "w") as txt: + for c in ["a", "b"]: + for i in range(5): + utterance_id = f"arctic_{c}{i:04d}" + path = os.path.join(audio_dir, f"{utterance_id}.wav") + data = get_whitenoise( + sample_rate=sample_rate, + duration=3, + n_channels=1, + dtype="int16", + seed=seed, + ) + save_wav(path, data, sample_rate) + sample = ( + normalize_wav(data), + sample_rate, + utterance, + utterance_id.split("_")[1], + ) + cls.samples.append(sample) + txt.write(f'( {utterance_id} "{utterance}" )\n') + seed += 1 + + def test_cmuarctic(self): + dataset = cmuarctic.CMUARCTIC(self.root_dir) + n_ite = 0 + for i, (waveform, sample_rate, utterance, utterance_id) in enumerate(dataset): + expected_sample = self.samples[i] + assert sample_rate == expected_sample[1] + assert utterance == expected_sample[2] + assert utterance_id == expected_sample[3] + self.assertEqual(expected_sample[0], waveform, atol=5e-5, rtol=1e-8) + n_ite += 1 + assert n_ite == len(self.samples) diff --git a/test/torchaudio_unittest/datasets/commonvoice_test.py b/test/torchaudio_unittest/datasets/commonvoice_test.py new file mode 100644 index 0000000000..3eedebec70 --- /dev/null +++ b/test/torchaudio_unittest/datasets/commonvoice_test.py @@ -0,0 +1,72 @@ +import os +import csv +import random + +from torchaudio.datasets import commonvoice +from torchaudio_unittest.common_utils import ( + TempDirMixin, + TorchaudioTestCase, + get_whitenoise, + save_wav, + normalize_wav, +) + + +class TestCommonVoice(TempDirMixin, TorchaudioTestCase): + backend = 'default' + + root_dir = None + data = [] + _headers = [u"client_ids", u"path", u"sentence", u"up_votes", u"down_votes", u"age", u"gender", u"accent"] + # Note: extension is changed to wav for the sake of test + # Note: the first content is missing values for `age`, `gender` and `accent` as in the original data. + _train_csv_contents = [ + ["9d16c5d980247861130e0480e2719f448be73d86a496c36d01a477cbdecd8cfd1399403d7a77bf458d211a70711b2da0845c", + "common_voice_en_18885784.wav", + "He was accorded a State funeral, and was buried in Drayton and Toowoomba Cemetery.", "2", "0", "", "", ""], + ["c82eb9291328620f06025a1f8112b909099e447e485e99236cb87df008650250e79fea5ca772061fb6a370830847b9c44d20", + "common_voice_en_556542.wav", "Once more into the breach", "2", "0", "thirties", "male", "us"], + ["f74d880c5ad4c5917f314a604d3fc4805159d255796fb9f8defca35333ecc002bdf53dc463503c12674ea840b21b4a507b7c", + "common_voice_en_18607573.wav", + "Caddy, show Miss Clare and Miss Summerson their rooms.", "2", "0", "twenties", "male", "canada"], + ] + _folder_audio = "clips" + sample_rate = 48000 + + @classmethod + def setUpClass(cls): + cls.root_dir = cls.get_base_temp_dir() + # The path convention commonvoice uses + base_dir = os.path.join(cls.root_dir, commonvoice.FOLDER_IN_ARCHIVE, commonvoice.VERSION, "en") + os.makedirs(base_dir, exist_ok=True) + + # Tsv file name difference does not mean different subset, testing as a whole dataset here + tsv_filename = os.path.join(base_dir, commonvoice.TSV) + with open(tsv_filename, "w", newline='') as tsv: + writer = csv.writer(tsv, delimiter='\t') + writer.writerow(cls._headers) + for i, content in enumerate(cls._train_csv_contents): + audio_filename = audio_filename = content[1] + writer.writerow(content) + + # Generate and store audio + audio_base_path = os.path.join(base_dir, cls._folder_audio) + os.makedirs(audio_base_path, exist_ok=True) + audio_path = os.path.join(audio_base_path, audio_filename) + data = get_whitenoise(sample_rate=cls.sample_rate, duration=1, n_channels=1, seed=i, dtype='float32') + save_wav(audio_path, data, cls.sample_rate) + + # Append data entry + cls.data.append((normalize_wav(data), cls.sample_rate, dict(zip(cls._headers, content)))) + + def test_commonvoice(self): + dataset = commonvoice.COMMONVOICE(self.root_dir) + n_ite = 0 + for i, (waveform, sample_rate, dictionary) in enumerate(dataset): + expected_dictionary = self.data[i][2] + expected_data = self.data[i][0] + self.assertEqual(expected_data, waveform, atol=5e-5, rtol=1e-8) + assert sample_rate == TestCommonVoice.sample_rate + assert dictionary == expected_dictionary + n_ite += 1 + assert n_ite == len(self.data) diff --git a/test/torchaudio_unittest/datasets/datasets_test.py b/test/torchaudio_unittest/datasets/datasets_test.py new file mode 100644 index 0000000000..cd04c4d447 --- /dev/null +++ b/test/torchaudio_unittest/datasets/datasets_test.py @@ -0,0 +1,17 @@ +from torchaudio.datasets.librispeech import LIBRISPEECH +from torchaudio.datasets.speechcommands import SPEECHCOMMANDS +from torchaudio.datasets.vctk import VCTK + +from torchaudio_unittest.common_utils import ( + TorchaudioTestCase, + get_asset_path, +) + + +class TestDatasets(TorchaudioTestCase): + backend = 'default' + path = get_asset_path() + + def test_vctk(self): + data = VCTK(self.path) + data[0] diff --git a/test/datasets/gtzan_test.py b/test/torchaudio_unittest/datasets/gtzan_test.py similarity index 98% rename from test/datasets/gtzan_test.py rename to test/torchaudio_unittest/datasets/gtzan_test.py index 14c82a512a..3236535fad 100644 --- a/test/datasets/gtzan_test.py +++ b/test/torchaudio_unittest/datasets/gtzan_test.py @@ -2,7 +2,7 @@ from torchaudio.datasets import gtzan -from ..common_utils import ( +from torchaudio_unittest.common_utils import ( TempDirMixin, TorchaudioTestCase, get_whitenoise, diff --git a/test/torchaudio_unittest/datasets/librispeech_test.py b/test/torchaudio_unittest/datasets/librispeech_test.py new file mode 100644 index 0000000000..669b428876 --- /dev/null +++ b/test/torchaudio_unittest/datasets/librispeech_test.py @@ -0,0 +1,112 @@ +import os + +from torchaudio.datasets import librispeech + +from torchaudio_unittest.common_utils import ( + TempDirMixin, + TorchaudioTestCase, + get_whitenoise, + save_wav, + normalize_wav, +) + +# Used to generate a unique utterance for each dummy audio file +NUMBERS = [ + 'ZERO', + 'ONE', + 'TWO', + 'THREE', + 'FOUR', + 'FIVE', + 'SIX', + 'SEVEN', + 'EIGHT', + 'NINE' +] + + +class TestLibriSpeech(TempDirMixin, TorchaudioTestCase): + backend = 'default' + + root_dir = None + samples = [] + + @classmethod + def setUpClass(cls): + cls.root_dir = cls.get_base_temp_dir() + dataset_dir = os.path.join( + cls.root_dir, librispeech.FOLDER_IN_ARCHIVE, librispeech.URL + ) + os.makedirs(dataset_dir, exist_ok=True) + sample_rate = 16000 # 16kHz + seed = 0 + + for speaker_id in range(5): + speaker_path = os.path.join(dataset_dir, str(speaker_id)) + os.makedirs(speaker_path, exist_ok=True) + + for chapter_id in range(3): + chapter_path = os.path.join(speaker_path, str(chapter_id)) + os.makedirs(chapter_path, exist_ok=True) + trans_content = [] + + for utterance_id in range(10): + filename = f'{speaker_id}-{chapter_id}-{utterance_id:04d}.wav' + path = os.path.join(chapter_path, filename) + + utterance = ' '.join( + [NUMBERS[x] for x in [speaker_id, chapter_id, utterance_id]] + ) + trans_content.append( + f'{speaker_id}-{chapter_id}-{utterance_id:04d} {utterance}' + ) + + data = get_whitenoise( + sample_rate=sample_rate, + duration=0.01, + n_channels=1, + dtype='float32', + seed=seed + ) + save_wav(path, data, sample_rate) + sample = ( + normalize_wav(data), + sample_rate, + utterance, + speaker_id, + chapter_id, + utterance_id + ) + cls.samples.append(sample) + + seed += 1 + + trans_filename = f'{speaker_id}-{chapter_id}.trans.txt' + trans_path = os.path.join(chapter_path, trans_filename) + with open(trans_path, 'w') as f: + f.write('\n'.join(trans_content)) + + @classmethod + def tearDownClass(cls): + # In case of test failure + librispeech.LIBRISPEECH._ext_audio = '.flac' + + def test_librispeech(self): + librispeech.LIBRISPEECH._ext_audio = '.wav' + dataset = librispeech.LIBRISPEECH(self.root_dir) + print(dataset._path) + + num_samples = 0 + for i, ( + data, sample_rate, utterance, speaker_id, chapter_id, utterance_id + ) in enumerate(dataset): + self.assertEqual(data, self.samples[i][0], atol=5e-5, rtol=1e-8) + assert sample_rate == self.samples[i][1] + assert utterance == self.samples[i][2] + assert speaker_id == self.samples[i][3] + assert chapter_id == self.samples[i][4] + assert utterance_id == self.samples[i][5] + num_samples += 1 + + assert num_samples == len(self.samples) + librispeech.LIBRISPEECH._ext_audio = '.flac' diff --git a/test/datasets/libritts_test.py b/test/torchaudio_unittest/datasets/libritts_test.py similarity index 91% rename from test/datasets/libritts_test.py rename to test/torchaudio_unittest/datasets/libritts_test.py index f31561d211..639098446b 100644 --- a/test/datasets/libritts_test.py +++ b/test/torchaudio_unittest/datasets/libritts_test.py @@ -2,7 +2,7 @@ from torchaudio.datasets.libritts import LIBRITTS -from ..common_utils import ( +from torchaudio_unittest.common_utils import ( TempDirMixin, TorchaudioTestCase, get_whitenoise, @@ -33,8 +33,8 @@ def setUpClass(cls): os.makedirs(file_dir, exist_ok=True) path = os.path.join(file_dir, filename) - data = get_whitenoise(sample_rate=8000, duration=6, n_channels=1, dtype='int16', seed=i) - save_wav(path, data, 8000) + data = get_whitenoise(sample_rate=24000, duration=2, n_channels=1, dtype='int16', seed=i) + save_wav(path, data, 24000) cls.data.append(normalize_wav(data)) original_text_filename = f'{"_".join(str(u) for u in utterance_id)}.original.txt' @@ -61,7 +61,7 @@ def test_libritts(self): expected_ids = self.utterance_ids[i] expected_data = self.data[i] self.assertEqual(expected_data, waveform, atol=5e-5, rtol=1e-8) - assert sample_rate == 8000 + assert sample_rate == 24000 assert speaker_id == expected_ids[0] assert chapter_id == expected_ids[1] assert original_text == self.original_text diff --git a/test/torchaudio_unittest/datasets/ljspeech_test.py b/test/torchaudio_unittest/datasets/ljspeech_test.py new file mode 100644 index 0000000000..7c1128c31b --- /dev/null +++ b/test/torchaudio_unittest/datasets/ljspeech_test.py @@ -0,0 +1,74 @@ +import csv +import os + +from torchaudio.datasets import ljspeech + +from torchaudio_unittest.common_utils import ( + TempDirMixin, + TorchaudioTestCase, + get_whitenoise, + normalize_wav, + save_wav, +) + + +class TestLJSpeech(TempDirMixin, TorchaudioTestCase): + backend = "default" + + root_dir = None + data = [] + transcripts = [ + "Test transcript 1", + "Test transcript 2", + "Test transcript 3", + "In 1465 Sweynheim and Pannartz began printing in the monastery of Subiaco near Rome," + ] + + normalized_transcripts = [ + "Test transcript one", + "Test transcript two", + "Test transcript three", + "In fourteen sixty-five Sweynheim and Pannartz began printing in the monastery of Subiaco near Rome," + ] + + @classmethod + def setUpClass(cls): + cls.root_dir = cls.get_base_temp_dir() + base_dir = os.path.join(cls.root_dir, "LJSpeech-1.1") + archive_dir = os.path.join(base_dir, "wavs") + os.makedirs(archive_dir, exist_ok=True) + metadata_path = os.path.join(base_dir, "metadata.csv") + sample_rate = 22050 + + with open(metadata_path, mode="w", newline='') as metadata_file: + metadata_writer = csv.writer( + metadata_file, delimiter="|", quoting=csv.QUOTE_NONE + ) + for i, (transcript, normalized_transcript) in enumerate( + zip(cls.transcripts, cls.normalized_transcripts) + ): + fileid = f'LJ001-{i:04d}' + metadata_writer.writerow([fileid, transcript, normalized_transcript]) + filename = fileid + ".wav" + path = os.path.join(archive_dir, filename) + data = get_whitenoise( + sample_rate=sample_rate, duration=1, n_channels=1, dtype="int16", seed=i + ) + save_wav(path, data, sample_rate) + cls.data.append(normalize_wav(data)) + + def test_ljspeech(self): + dataset = ljspeech.LJSPEECH(self.root_dir) + n_ite = 0 + for i, (waveform, sample_rate, transcript, normalized_transcript) in enumerate( + dataset + ): + expected_transcript = self.transcripts[i] + expected_normalized_transcript = self.normalized_transcripts[i] + expected_data = self.data[i] + self.assertEqual(expected_data, waveform, atol=5e-5, rtol=1e-8) + assert sample_rate == sample_rate + assert transcript == expected_transcript + assert normalized_transcript == expected_normalized_transcript + n_ite += 1 + assert n_ite == len(self.data) diff --git a/test/torchaudio_unittest/datasets/speechcommands_test.py b/test/torchaudio_unittest/datasets/speechcommands_test.py new file mode 100644 index 0000000000..7df1ea2007 --- /dev/null +++ b/test/torchaudio_unittest/datasets/speechcommands_test.py @@ -0,0 +1,109 @@ +import os + +from torchaudio.datasets import speechcommands + +from torchaudio_unittest.common_utils import ( + TempDirMixin, + TorchaudioTestCase, + get_whitenoise, + normalize_wav, + save_wav, +) + +LABELS = [ + "bed", + "bird", + "cat", + "dog", + "down", + "eight", + "five", + "follow", + "forward", + "four", + "go", + "happy", + "house", + "learn", + "left", + "marvin", + "nine", + "no", + "off", + "on", + "one", + "right", + "seven", + "sheila", + "six", + "stop", + "three", + "tree", + "two", + "up", + "visual", + "wow", + "yes", + "zero", +] + + +class TestSpeechCommands(TempDirMixin, TorchaudioTestCase): + backend = "default" + + root_dir = None + samples = [] + + @classmethod + def setUp(cls): + cls.root_dir = cls.get_base_temp_dir() + dataset_dir = os.path.join( + cls.root_dir, speechcommands.FOLDER_IN_ARCHIVE, speechcommands.URL + ) + os.makedirs(dataset_dir, exist_ok=True) + sample_rate = 16000 # 16kHz sample rate + seed = 0 + for label in LABELS: + path = os.path.join(dataset_dir, label) + os.makedirs(path, exist_ok=True) + for j in range(2): + # generate hash ID for speaker + speaker = "{:08x}".format(j) + + for utterance in range(3): + filename = f"{speaker}{speechcommands.HASH_DIVIDER}{utterance}.wav" + file_path = os.path.join(path, filename) + seed += 1 + data = get_whitenoise( + sample_rate=sample_rate, + duration=0.01, + n_channels=1, + dtype="int16", + seed=seed, + ) + save_wav(file_path, data, sample_rate) + sample = ( + normalize_wav(data), + sample_rate, + label, + speaker, + utterance, + ) + cls.samples.append(sample) + + def testSpeechCommands(self): + dataset = speechcommands.SPEECHCOMMANDS(self.root_dir) + print(dataset._path) + + num_samples = 0 + for i, (data, sample_rate, label, speaker_id, utterance_number) in enumerate( + dataset + ): + self.assertEqual(data, self.samples[i][0], atol=5e-5, rtol=1e-8) + assert sample_rate == self.samples[i][1] + assert label == self.samples[i][2] + assert speaker_id == self.samples[i][3] + assert utterance_number == self.samples[i][4] + num_samples += 1 + + assert num_samples == len(self.samples) diff --git a/test/datasets/utils_test.py b/test/torchaudio_unittest/datasets/utils_test.py similarity index 68% rename from test/datasets/utils_test.py rename to test/torchaudio_unittest/datasets/utils_test.py index e77df09f4c..f75ae2319c 100644 --- a/test/datasets/utils_test.py +++ b/test/torchaudio_unittest/datasets/utils_test.py @@ -2,10 +2,12 @@ from pathlib import Path from torchaudio.datasets import utils as dataset_utils +from torchaudio.datasets.commonvoice import COMMONVOICE -from ..common_utils import ( +from torchaudio_unittest.common_utils import ( TempDirMixin, TorchaudioTestCase, + get_asset_path, ) @@ -45,3 +47,22 @@ def test_walk_files(self): assert found == self.expected[i] n_ites += 1 assert n_ites == len(self.expected) + + +class TestIterator(TorchaudioTestCase): + backend = 'default' + path = get_asset_path() + + def test_disckcache_iterator(self): + data = COMMONVOICE(self.path, url="tatar") + data = dataset_utils.diskcache_iterator(data) + # Save + data[0] + # Load + data[0] + + def test_bg_iterator(self): + data = COMMONVOICE(self.path, url="tatar") + data = dataset_utils.bg_iterator(data, 5) + for _ in data: + pass diff --git a/test/datasets/yesno_test.py b/test/torchaudio_unittest/datasets/yesno_test.py similarity index 91% rename from test/datasets/yesno_test.py rename to test/torchaudio_unittest/datasets/yesno_test.py index f9c4d0b051..a8a8a04276 100644 --- a/test/datasets/yesno_test.py +++ b/test/torchaudio_unittest/datasets/yesno_test.py @@ -2,7 +2,7 @@ from torchaudio.datasets import yesno -from ..common_utils import ( +from torchaudio_unittest.common_utils import ( TempDirMixin, TorchaudioTestCase, get_whitenoise, @@ -29,10 +29,10 @@ def setUpClass(cls): cls.root_dir = cls.get_base_temp_dir() base_dir = os.path.join(cls.root_dir, 'waves_yesno') os.makedirs(base_dir, exist_ok=True) - for label in cls.labels: + for i, label in enumerate(cls.labels): filename = f'{"_".join(str(l) for l in label)}.wav' path = os.path.join(base_dir, filename) - data = get_whitenoise(sample_rate=8000, duration=6, n_channels=1, dtype='int16') + data = get_whitenoise(sample_rate=8000, duration=6, n_channels=1, dtype='int16', seed=i) save_wav(path, data, 8000) cls.data.append(normalize_wav(data)) diff --git a/test/sox_effect/__init__.py b/test/torchaudio_unittest/functional/__init__.py similarity index 100% rename from test/sox_effect/__init__.py rename to test/torchaudio_unittest/functional/__init__.py diff --git a/test/torchaudio_unittest/functional/functional_cpu_test.py b/test/torchaudio_unittest/functional/functional_cpu_test.py new file mode 100644 index 0000000000..96aac4e770 --- /dev/null +++ b/test/torchaudio_unittest/functional/functional_cpu_test.py @@ -0,0 +1,146 @@ +import math +import unittest + +import torch +import torchaudio +import torchaudio.functional as F +from parameterized import parameterized +import pytest + +from torchaudio_unittest import common_utils +from .functional_impl import Lfilter + + +class TestLFilterFloat32(Lfilter, common_utils.PytorchTestCase): + dtype = torch.float32 + device = torch.device('cpu') + + +class TestLFilterFloat64(Lfilter, common_utils.PytorchTestCase): + dtype = torch.float64 + device = torch.device('cpu') + + +class TestComputeDeltas(common_utils.TorchaudioTestCase): + """Test suite for correctness of compute_deltas""" + def test_one_channel(self): + specgram = torch.tensor([[[1.0, 2.0, 3.0, 4.0]]]) + expected = torch.tensor([[[0.5, 1.0, 1.0, 0.5]]]) + computed = F.compute_deltas(specgram, win_length=3) + torch.testing.assert_allclose(computed, expected) + + def test_two_channels(self): + specgram = torch.tensor([[[1.0, 2.0, 3.0, 4.0], + [1.0, 2.0, 3.0, 4.0]]]) + expected = torch.tensor([[[0.5, 1.0, 1.0, 0.5], + [0.5, 1.0, 1.0, 0.5]]]) + computed = F.compute_deltas(specgram, win_length=3) + torch.testing.assert_allclose(computed, expected) + + +class TestDetectPitchFrequency(common_utils.TorchaudioTestCase): + @parameterized.expand([(100,), (440,)]) + def test_pitch(self, frequency): + sample_rate = 44100 + test_sine_waveform = common_utils.get_sinusoid( + frequency=frequency, sample_rate=sample_rate, duration=5, + ) + + freq = torchaudio.functional.detect_pitch_frequency(test_sine_waveform, sample_rate) + + threshold = 1 + s = ((freq - frequency).abs() > threshold).sum() + self.assertFalse(s) + + +class TestDB_to_amplitude(common_utils.TorchaudioTestCase): + def test_DB_to_amplitude(self): + # Make some noise + x = torch.rand(1000) + spectrogram = torchaudio.transforms.Spectrogram() + spec = spectrogram(x) + + amin = 1e-10 + ref = 1.0 + db_multiplier = math.log10(max(amin, ref)) + + # Waveform amplitude -> DB -> amplitude + multiplier = 20. + power = 0.5 + + db = F.amplitude_to_DB(torch.abs(x), multiplier, amin, db_multiplier, top_db=None) + x2 = F.DB_to_amplitude(db, ref, power) + + torch.testing.assert_allclose(x2, torch.abs(x), atol=5e-5, rtol=1e-5) + + # Spectrogram amplitude -> DB -> amplitude + db = F.amplitude_to_DB(spec, multiplier, amin, db_multiplier, top_db=None) + x2 = F.DB_to_amplitude(db, ref, power) + + torch.testing.assert_allclose(x2, spec, atol=5e-5, rtol=1e-5) + + # Waveform power -> DB -> power + multiplier = 10. + power = 1. + + db = F.amplitude_to_DB(x, multiplier, amin, db_multiplier, top_db=None) + x2 = F.DB_to_amplitude(db, ref, power) + + torch.testing.assert_allclose(x2, torch.abs(x), atol=5e-5, rtol=1e-5) + + # Spectrogram power -> DB -> power + db = F.amplitude_to_DB(spec, multiplier, amin, db_multiplier, top_db=None) + x2 = F.DB_to_amplitude(db, ref, power) + + torch.testing.assert_allclose(x2, spec, atol=5e-5, rtol=1e-5) + + +@pytest.mark.parametrize('complex_tensor', [ + torch.randn(1, 2, 1025, 400, 2), + torch.randn(1025, 400, 2) +]) +@pytest.mark.parametrize('power', [1, 2, 0.7]) +def test_complex_norm(complex_tensor, power): + expected_norm_tensor = complex_tensor.pow(2).sum(-1).pow(power / 2) + norm_tensor = F.complex_norm(complex_tensor, power) + + torch.testing.assert_allclose(norm_tensor, expected_norm_tensor, atol=1e-5, rtol=1e-5) + + +@pytest.mark.parametrize('specgram', [ + torch.randn(2, 1025, 400), + torch.randn(1, 201, 100) +]) +@pytest.mark.parametrize('mask_param', [100]) +@pytest.mark.parametrize('mask_value', [0., 30.]) +@pytest.mark.parametrize('axis', [1, 2]) +def test_mask_along_axis(specgram, mask_param, mask_value, axis): + + mask_specgram = F.mask_along_axis(specgram, mask_param, mask_value, axis) + + other_axis = 1 if axis == 2 else 2 + + masked_columns = (mask_specgram == mask_value).sum(other_axis) + num_masked_columns = (masked_columns == mask_specgram.size(other_axis)).sum() + num_masked_columns //= mask_specgram.size(0) + + assert mask_specgram.size() == specgram.size() + assert num_masked_columns < mask_param + + +@pytest.mark.parametrize('mask_param', [100]) +@pytest.mark.parametrize('mask_value', [0., 30.]) +@pytest.mark.parametrize('axis', [2, 3]) +def test_mask_along_axis_iid(mask_param, mask_value, axis): + torch.random.manual_seed(42) + specgrams = torch.randn(4, 2, 1025, 400) + + mask_specgrams = F.mask_along_axis_iid(specgrams, mask_param, mask_value, axis) + + other_axis = 2 if axis == 3 else 3 + + masked_columns = (mask_specgrams == mask_value).sum(other_axis) + num_masked_columns = (masked_columns == mask_specgrams.size(other_axis)).sum(-1) + + assert mask_specgrams.size() == specgrams.size() + assert (num_masked_columns < mask_param).sum() == num_masked_columns.numel() diff --git a/test/functional_cuda_test.py b/test/torchaudio_unittest/functional/functional_cuda_test.py similarity index 88% rename from test/functional_cuda_test.py rename to test/torchaudio_unittest/functional/functional_cuda_test.py index 9602dcf071..80ac5fa0c2 100644 --- a/test/functional_cuda_test.py +++ b/test/torchaudio_unittest/functional/functional_cuda_test.py @@ -1,6 +1,6 @@ import torch -from . import common_utils +from torchaudio_unittest import common_utils from .functional_impl import Lfilter diff --git a/test/functional_impl.py b/test/torchaudio_unittest/functional/functional_impl.py similarity index 96% rename from test/functional_impl.py rename to test/torchaudio_unittest/functional/functional_impl.py index fb5e7dc7ac..c63001a68e 100644 --- a/test/functional_impl.py +++ b/test/torchaudio_unittest/functional/functional_impl.py @@ -2,7 +2,7 @@ import torch import torchaudio.functional as F -from . import common_utils +from torchaudio_unittest import common_utils class Lfilter(common_utils.TestBaseMixin): diff --git a/test/test_io.py b/test/torchaudio_unittest/io_test.py similarity index 95% rename from test/test_io.py rename to test/torchaudio_unittest/io_test.py index b55885059a..e30f4c3fd3 100644 --- a/test/test_io.py +++ b/test/torchaudio_unittest/io_test.py @@ -6,8 +6,25 @@ import torch import torchaudio +from torchaudio.utils import sox_utils +from torchaudio._internal.module_utils import is_module_available -from .common_utils import BACKENDS, BACKENDS_MP3, get_asset_path +from torchaudio_unittest.common_utils import get_asset_path + +BACKENDS = [] +BACKENDS_MP3 = [] + +if is_module_available('soundfile'): + BACKENDS.append('soundfile') + +if is_module_available('torchaudio._torchaudio'): + BACKENDS.append('sox') + + if ( + 'mp3' in sox_utils.list_read_formats() and + 'mp3' in sox_utils.list_write_formats() + ): + BACKENDS_MP3 = ['sox'] def create_temp_assets_dir(): @@ -30,15 +47,11 @@ class Test_LoadSave(unittest.TestCase): def test_1_save(self): for backend in BACKENDS_MP3: - if backend == 'sox_io': - continue with self.subTest(): torchaudio.set_audio_backend(backend) self._test_1_save(self.test_filepath, False) for backend in BACKENDS: - if backend == 'sox_io': - continue with self.subTest(): torchaudio.set_audio_backend(backend) self._test_1_save(self.test_filepath_wav, True) @@ -85,8 +98,6 @@ def _test_1_save(self, test_filepath, normalization): def test_1_save_sine(self): for backend in BACKENDS: - if backend == 'sox_io': - continue with self.subTest(): torchaudio.set_audio_backend(backend) self._test_1_save_sine() @@ -120,15 +131,11 @@ def _test_1_save_sine(self): def test_2_load(self): for backend in BACKENDS_MP3: - if backend == 'sox_io': - continue with self.subTest(): torchaudio.set_audio_backend(backend) self._test_2_load(self.test_filepath, 278756) for backend in BACKENDS: - if backend == 'sox_io': - continue with self.subTest(): torchaudio.set_audio_backend(backend) self._test_2_load(self.test_filepath_wav, 276858) @@ -224,8 +231,6 @@ def _test_3_load_and_save_is_identity_across_backend(self, backend1, backend2): def test_4_load_partial(self): for backend in BACKENDS_MP3: - if backend == 'sox_io': - continue with self.subTest(): torchaudio.set_audio_backend(backend) self._test_4_load_partial() @@ -268,8 +273,6 @@ def _test_4_load_partial(self): def test_5_get_info(self): for backend in BACKENDS: - if backend == 'sox_io': - continue with self.subTest(): torchaudio.set_audio_backend(backend) self._test_5_get_info() diff --git a/test/kaldi_compatibility_cpu_test.py b/test/torchaudio_unittest/kaldi_compatibility_cpu_test.py similarity index 87% rename from test/kaldi_compatibility_cpu_test.py rename to test/torchaudio_unittest/kaldi_compatibility_cpu_test.py index 3357123296..43be412b47 100644 --- a/test/kaldi_compatibility_cpu_test.py +++ b/test/torchaudio_unittest/kaldi_compatibility_cpu_test.py @@ -1,6 +1,6 @@ import torch -from . import common_utils +from torchaudio_unittest import common_utils from .kaldi_compatibility_impl import Kaldi diff --git a/test/kaldi_compatibility_cuda_test.py b/test/torchaudio_unittest/kaldi_compatibility_cuda_test.py similarity index 88% rename from test/kaldi_compatibility_cuda_test.py rename to test/torchaudio_unittest/kaldi_compatibility_cuda_test.py index e23dbf3f40..28adb7fce5 100644 --- a/test/kaldi_compatibility_cuda_test.py +++ b/test/torchaudio_unittest/kaldi_compatibility_cuda_test.py @@ -1,6 +1,6 @@ import torch -from . import common_utils +from torchaudio_unittest import common_utils from .kaldi_compatibility_impl import Kaldi diff --git a/test/kaldi_compatibility_impl.py b/test/torchaudio_unittest/kaldi_compatibility_impl.py similarity index 98% rename from test/kaldi_compatibility_impl.py rename to test/torchaudio_unittest/kaldi_compatibility_impl.py index 7e51620f63..bae01203f1 100644 --- a/test/kaldi_compatibility_impl.py +++ b/test/torchaudio_unittest/kaldi_compatibility_impl.py @@ -7,7 +7,7 @@ import torchaudio.compliance.kaldi from parameterized import parameterized -from .common_utils import ( +from torchaudio_unittest.common_utils import ( TestBaseMixin, load_params, skipIfNoExec, diff --git a/test/test_kaldi_io.py b/test/torchaudio_unittest/kaldi_io_test.py similarity index 96% rename from test/test_kaldi_io.py rename to test/torchaudio_unittest/kaldi_io_test.py index 80e6b3dc5a..2153b4cc02 100644 --- a/test/test_kaldi_io.py +++ b/test/torchaudio_unittest/kaldi_io_test.py @@ -3,7 +3,7 @@ import torch import torchaudio.kaldi_io as kio -from . import common_utils +from torchaudio_unittest import common_utils class Test_KaldiIO(common_utils.TorchaudioTestCase): diff --git a/test/test_librosa_compatibility.py b/test/torchaudio_unittest/librosa_compatibility_test.py similarity index 99% rename from test/test_librosa_compatibility.py rename to test/torchaudio_unittest/librosa_compatibility_test.py index 01b0f23732..f779f36dae 100644 --- a/test/test_librosa_compatibility.py +++ b/test/torchaudio_unittest/librosa_compatibility_test.py @@ -17,7 +17,7 @@ import pytest -from . import common_utils +from torchaudio_unittest import common_utils @unittest.skipIf(not LIBROSA_AVAILABLE, "Librosa not available") diff --git a/test/test_models.py b/test/torchaudio_unittest/models_test.py similarity index 75% rename from test/test_models.py rename to test/torchaudio_unittest/models_test.py index 10ca5c827b..f9e96edd27 100644 --- a/test/test_models.py +++ b/test/torchaudio_unittest/models_test.py @@ -1,7 +1,7 @@ import torch -from torchaudio.models import Wav2Letter, _MelResNet, _UpsampleNetwork, _WaveRNN +from torchaudio.models import Wav2Letter, MelResNet, UpsampleNetwork, WaveRNN -from . import common_utils +from torchaudio_unittest import common_utils class TestWav2Letter(common_utils.TorchaudioTestCase): @@ -36,7 +36,7 @@ def test_mfcc(self): class TestMelResNet(common_utils.TorchaudioTestCase): def test_waveform(self): - """Validate the output dimensions of a _MelResNet block. + """Validate the output dimensions of a MelResNet block. """ n_batch = 2 @@ -47,7 +47,7 @@ def test_waveform(self): n_hidden = 128 kernel_size = 5 - model = _MelResNet(n_res_block, n_freq, n_hidden, n_output, kernel_size) + model = MelResNet(n_res_block, n_freq, n_hidden, n_output, kernel_size) x = torch.rand(n_batch, n_freq, n_time) out = model(x) @@ -58,7 +58,7 @@ def test_waveform(self): class TestUpsampleNetwork(common_utils.TorchaudioTestCase): def test_waveform(self): - """Validate the output dimensions of a _UpsampleNetwork block. + """Validate the output dimensions of a UpsampleNetwork block. """ upsample_scales = [5, 5, 8] @@ -74,12 +74,12 @@ def test_waveform(self): for upsample_scale in upsample_scales: total_scale *= upsample_scale - model = _UpsampleNetwork(upsample_scales, - n_res_block, - n_freq, - n_hidden, - n_output, - kernel_size) + model = UpsampleNetwork(upsample_scales, + n_res_block, + n_freq, + n_hidden, + n_output, + kernel_size) x = torch.rand(n_batch, n_freq, n_time) out1, out2 = model(x) @@ -91,7 +91,7 @@ def test_waveform(self): class TestWaveRNN(common_utils.TorchaudioTestCase): def test_waveform(self): - """Validate the output dimensions of a _WaveRNN model. + """Validate the output dimensions of a WaveRNN model. """ upsample_scales = [5, 5, 8] @@ -107,8 +107,8 @@ def test_waveform(self): n_hidden = 128 kernel_size = 5 - model = _WaveRNN(upsample_scales, n_classes, hop_length, n_res_block, - n_rnn, n_fc, kernel_size, n_freq, n_hidden, n_output) + model = WaveRNN(upsample_scales, n_classes, hop_length, n_res_block, + n_rnn, n_fc, kernel_size, n_freq, n_hidden, n_output) x = torch.rand(n_batch, 1, hop_length * (n_time - kernel_size + 1)) mels = torch.rand(n_batch, 1, n_freq, n_time) diff --git a/test/test_sox_compatibility.py b/test/torchaudio_unittest/sox_compatibility_test.py similarity index 99% rename from test/test_sox_compatibility.py rename to test/torchaudio_unittest/sox_compatibility_test.py index 260c435b83..ade98b2aeb 100644 --- a/test/test_sox_compatibility.py +++ b/test/torchaudio_unittest/sox_compatibility_test.py @@ -5,7 +5,7 @@ import torchaudio.transforms as T from parameterized import parameterized -from .common_utils import ( +from torchaudio_unittest.common_utils import ( skipIfNoSoxBackend, skipIfNoExec, TempDirMixin, diff --git a/test/sox_io_backend/__init__.py b/test/torchaudio_unittest/sox_effect/__init__.py similarity index 100% rename from test/sox_io_backend/__init__.py rename to test/torchaudio_unittest/sox_effect/__init__.py diff --git a/test/sox_effect/common.py b/test/torchaudio_unittest/sox_effect/common.py similarity index 92% rename from test/sox_effect/common.py rename to test/torchaudio_unittest/sox_effect/common.py index 86edcf6476..00ac4a4565 100644 --- a/test/sox_effect/common.py +++ b/test/torchaudio_unittest/sox_effect/common.py @@ -2,7 +2,7 @@ from parameterized import param -from ..common_utils import get_asset_path +from torchaudio_unittest.common_utils import get_asset_path def name_func(func, _, params): diff --git a/test/sox_effect/test_dataset.py b/test/torchaudio_unittest/sox_effect/dataset_test.py similarity index 98% rename from test/sox_effect/test_dataset.py rename to test/torchaudio_unittest/sox_effect/dataset_test.py index f1b71eb806..e98095d0dd 100644 --- a/test/sox_effect/test_dataset.py +++ b/test/torchaudio_unittest/sox_effect/dataset_test.py @@ -4,7 +4,7 @@ import torch import torchaudio -from ..common_utils import ( +from torchaudio_unittest.common_utils import ( TempDirMixin, PytorchTestCase, skipIfNoExtension, diff --git a/test/sox_effect/smoke_test.py b/test/torchaudio_unittest/sox_effect/smoke_test.py similarity index 97% rename from test/sox_effect/smoke_test.py rename to test/torchaudio_unittest/sox_effect/smoke_test.py index 4997002170..996c62063f 100644 --- a/test/sox_effect/smoke_test.py +++ b/test/torchaudio_unittest/sox_effect/smoke_test.py @@ -1,7 +1,7 @@ from torchaudio import sox_effects from parameterized import parameterized -from ..common_utils import ( +from torchaudio_unittest.common_utils import ( TempDirMixin, TorchaudioTestCase, skipIfNoExtension, diff --git a/test/sox_effect/test_sox_effect.py b/test/torchaudio_unittest/sox_effect/sox_effect_test.py similarity index 99% rename from test/sox_effect/test_sox_effect.py rename to test/torchaudio_unittest/sox_effect/sox_effect_test.py index 38ab0fa772..27740ca576 100644 --- a/test/sox_effect/test_sox_effect.py +++ b/test/torchaudio_unittest/sox_effect/sox_effect_test.py @@ -3,7 +3,7 @@ from torchaudio import sox_effects from parameterized import parameterized -from ..common_utils import ( +from torchaudio_unittest.common_utils import ( TempDirMixin, PytorchTestCase, skipIfNoExtension, diff --git a/test/sox_effect/sox_effects_chain_test.py b/test/torchaudio_unittest/sox_effect/sox_effects_chain_test.py similarity index 100% rename from test/sox_effect/sox_effects_chain_test.py rename to test/torchaudio_unittest/sox_effect/sox_effects_chain_test.py diff --git a/test/sox_effect/test_torchscript.py b/test/torchaudio_unittest/sox_effect/torchscript_test.py similarity index 98% rename from test/sox_effect/test_torchscript.py rename to test/torchaudio_unittest/sox_effect/torchscript_test.py index ded923ab11..8e1a9a3980 100644 --- a/test/sox_effect/test_torchscript.py +++ b/test/torchaudio_unittest/sox_effect/torchscript_test.py @@ -4,7 +4,7 @@ from torchaudio import sox_effects from parameterized import parameterized -from ..common_utils import ( +from torchaudio_unittest.common_utils import ( TempDirMixin, PytorchTestCase, skipIfNoExtension, diff --git a/test/utils/__init__.py b/test/torchaudio_unittest/sox_io_backend/__init__.py similarity index 100% rename from test/utils/__init__.py rename to test/torchaudio_unittest/sox_io_backend/__init__.py diff --git a/test/sox_io_backend/common.py b/test/torchaudio_unittest/sox_io_backend/common.py similarity index 100% rename from test/sox_io_backend/common.py rename to test/torchaudio_unittest/sox_io_backend/common.py diff --git a/test/sox_io_backend/test_info.py b/test/torchaudio_unittest/sox_io_backend/info_test.py similarity index 98% rename from test/sox_io_backend/test_info.py rename to test/torchaudio_unittest/sox_io_backend/info_test.py index da5207a7e5..f07b72e112 100644 --- a/test/sox_io_backend/test_info.py +++ b/test/torchaudio_unittest/sox_io_backend/info_test.py @@ -3,7 +3,7 @@ from torchaudio.backend import sox_io_backend -from ..common_utils import ( +from torchaudio_unittest.common_utils import ( TempDirMixin, PytorchTestCase, skipIfNoExec, diff --git a/test/sox_io_backend/test_load.py b/test/torchaudio_unittest/sox_io_backend/load_test.py similarity index 99% rename from test/sox_io_backend/test_load.py rename to test/torchaudio_unittest/sox_io_backend/load_test.py index 8366a01f83..1ff8b76dc5 100644 --- a/test/sox_io_backend/test_load.py +++ b/test/torchaudio_unittest/sox_io_backend/load_test.py @@ -3,7 +3,7 @@ from torchaudio.backend import sox_io_backend from parameterized import parameterized -from ..common_utils import ( +from torchaudio_unittest.common_utils import ( TempDirMixin, PytorchTestCase, skipIfNoExec, diff --git a/test/sox_io_backend/test_roundtrip.py b/test/torchaudio_unittest/sox_io_backend/roundtrip_test.py similarity index 97% rename from test/sox_io_backend/test_roundtrip.py rename to test/torchaudio_unittest/sox_io_backend/roundtrip_test.py index 2a051bebd5..85aa3019e0 100644 --- a/test/sox_io_backend/test_roundtrip.py +++ b/test/torchaudio_unittest/sox_io_backend/roundtrip_test.py @@ -3,7 +3,7 @@ from torchaudio.backend import sox_io_backend from parameterized import parameterized -from ..common_utils import ( +from torchaudio_unittest.common_utils import ( TempDirMixin, PytorchTestCase, skipIfNoExec, diff --git a/test/sox_io_backend/test_save.py b/test/torchaudio_unittest/sox_io_backend/save_test.py similarity index 99% rename from test/sox_io_backend/test_save.py rename to test/torchaudio_unittest/sox_io_backend/save_test.py index 53588c456b..8e416b7aa9 100644 --- a/test/sox_io_backend/test_save.py +++ b/test/torchaudio_unittest/sox_io_backend/save_test.py @@ -3,7 +3,7 @@ from torchaudio.backend import sox_io_backend from parameterized import parameterized -from ..common_utils import ( +from torchaudio_unittest.common_utils import ( TempDirMixin, PytorchTestCase, skipIfNoExec, diff --git a/test/sox_io_backend/smoke_test.py b/test/torchaudio_unittest/sox_io_backend/smoke_test.py similarity index 98% rename from test/sox_io_backend/smoke_test.py rename to test/torchaudio_unittest/sox_io_backend/smoke_test.py index 1ae9a8d938..be734afa77 100644 --- a/test/sox_io_backend/smoke_test.py +++ b/test/torchaudio_unittest/sox_io_backend/smoke_test.py @@ -6,7 +6,7 @@ from torchaudio._internal.module_utils import is_module_available from parameterized import parameterized -from ..common_utils import ( +from torchaudio_unittest.common_utils import ( TempDirMixin, TorchaudioTestCase, skipIfNoExtension, diff --git a/test/sox_io_backend/test_torchscript.py b/test/torchaudio_unittest/sox_io_backend/torchscript_test.py similarity index 99% rename from test/sox_io_backend/test_torchscript.py rename to test/torchaudio_unittest/sox_io_backend/torchscript_test.py index 9a30aab0d2..dad678cbc0 100644 --- a/test/sox_io_backend/test_torchscript.py +++ b/test/torchaudio_unittest/sox_io_backend/torchscript_test.py @@ -5,7 +5,7 @@ import torchaudio from parameterized import parameterized -from ..common_utils import ( +from torchaudio_unittest.common_utils import ( TempDirMixin, TorchaudioTestCase, skipIfNoExec, diff --git a/test/torchscript_consistency_cpu_test.py b/test/torchaudio_unittest/torchscript_consistency_cpu_test.py similarity index 93% rename from test/torchscript_consistency_cpu_test.py rename to test/torchaudio_unittest/torchscript_consistency_cpu_test.py index 38fe7961fd..fcc9cb8389 100644 --- a/test/torchscript_consistency_cpu_test.py +++ b/test/torchaudio_unittest/torchscript_consistency_cpu_test.py @@ -1,6 +1,6 @@ import torch -from . import common_utils +from torchaudio_unittest import common_utils from .torchscript_consistency_impl import Functional, Transforms diff --git a/test/torchscript_consistency_cuda_test.py b/test/torchaudio_unittest/torchscript_consistency_cuda_test.py similarity index 94% rename from test/torchscript_consistency_cuda_test.py rename to test/torchaudio_unittest/torchscript_consistency_cuda_test.py index b317334ce4..c205e192ed 100644 --- a/test/torchscript_consistency_cuda_test.py +++ b/test/torchaudio_unittest/torchscript_consistency_cuda_test.py @@ -1,6 +1,6 @@ import torch -from . import common_utils +from torchaudio_unittest import common_utils from .torchscript_consistency_impl import Functional, Transforms diff --git a/test/torchscript_consistency_impl.py b/test/torchaudio_unittest/torchscript_consistency_impl.py similarity index 99% rename from test/torchscript_consistency_impl.py rename to test/torchaudio_unittest/torchscript_consistency_impl.py index 76444dc18a..8d14e538fd 100644 --- a/test/torchscript_consistency_impl.py +++ b/test/torchaudio_unittest/torchscript_consistency_impl.py @@ -5,7 +5,7 @@ import torchaudio.functional as F import torchaudio.transforms as T -from . import common_utils +from torchaudio_unittest import common_utils class Functional(common_utils.TestBaseMixin): diff --git a/test/test_transforms.py b/test/torchaudio_unittest/transforms_test.py similarity index 99% rename from test/test_transforms.py rename to test/torchaudio_unittest/transforms_test.py index f6942e18a5..4a91d40bd9 100644 --- a/test/test_transforms.py +++ b/test/torchaudio_unittest/transforms_test.py @@ -6,7 +6,7 @@ import torchaudio.transforms as transforms import torchaudio.functional as F -from . import common_utils +from torchaudio_unittest import common_utils class Tester(common_utils.TorchaudioTestCase): diff --git a/test/torchaudio_unittest/utils/__init__.py b/test/torchaudio_unittest/utils/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/test/utils/test_sox_utils.py b/test/torchaudio_unittest/utils/sox_utils_test.py similarity index 97% rename from test/utils/test_sox_utils.py rename to test/torchaudio_unittest/utils/sox_utils_test.py index 55a46a235e..7c206fdc0b 100644 --- a/test/utils/test_sox_utils.py +++ b/test/torchaudio_unittest/utils/sox_utils_test.py @@ -1,6 +1,6 @@ from torchaudio.utils import sox_utils -from ..common_utils import ( +from torchaudio_unittest.common_utils import ( PytorchTestCase, skipIfNoExtension, ) diff --git a/torchaudio/compliance/kaldi.py b/torchaudio/compliance/kaldi.py index 6211b09f2d..792f439ccd 100644 --- a/torchaudio/compliance/kaldi.py +++ b/torchaudio/compliance/kaldi.py @@ -135,13 +135,15 @@ def _get_waveform_and_window_properties(waveform: Tensor, r"""Gets the waveform and window properties """ channel = max(channel, 0) - assert channel < waveform.size(0), ('Invalid channel %d for size %d' % (channel, waveform.size(0))) + assert channel < waveform.size(0), ('Invalid channel {} for size {}'.format(channel, waveform.size(0))) waveform = waveform[channel, :] # size (n) window_shift = int(sample_frequency * frame_shift * MILLISECONDS_TO_SECONDS) window_size = int(sample_frequency * frame_length * MILLISECONDS_TO_SECONDS) padded_window_size = _next_power_of_2(window_size) if round_to_power_of_two else window_size - assert 2 <= window_size <= len(waveform), ('choose a window size %d that is [2, %d]' % (window_size, len(waveform))) + assert 2 <= window_size <= len( + waveform), ('choose a window size {} that is [2, {}]' + .format(window_size, len(waveform))) assert 0 < window_shift, '`window_shift` must be greater than 0' assert padded_window_size % 2 == 0, 'the padded `window_size` must be divisible by two.' \ ' use `round_to_power_of_two` or change `frame_length`' @@ -430,7 +432,7 @@ def get_mel_banks(num_bins: int, high_freq += nyquist assert (0.0 <= low_freq < nyquist) and (0.0 < high_freq <= nyquist) and (low_freq < high_freq), \ - ('Bad values in options: low-freq %f and high-freq %f vs. nyquist %f' % (low_freq, high_freq, nyquist)) + ('Bad values in options: low-freq {} and high-freq {} vs. nyquist {}'.format(low_freq, high_freq, nyquist)) # fft-bin width [think of it as Nyquist-freq / half-window-length] fft_bin_width = sample_freq / window_length_padded @@ -446,8 +448,8 @@ def get_mel_banks(num_bins: int, assert vtln_warp_factor == 1.0 or ((low_freq < vtln_low < high_freq) and (0.0 < vtln_high < high_freq) and (vtln_low < vtln_high)), \ - ('Bad values in options: vtln-low %f and vtln-high %f, versus low-freq %f and high-freq %f' % - (vtln_low, vtln_high, low_freq, high_freq)) + ('Bad values in options: vtln-low {} and vtln-high {}, versus ' + 'low-freq {} and high-freq {}'.format(vtln_low, vtln_high, low_freq, high_freq)) bin = torch.arange(num_bins).unsqueeze(1) left_mel = mel_low_freq + bin * mel_freq_delta # size(num_bins, 1) diff --git a/torchaudio/datasets/ljspeech.py b/torchaudio/datasets/ljspeech.py index 0b4ee86acc..5e3b6ee7d2 100644 --- a/torchaudio/datasets/ljspeech.py +++ b/torchaudio/datasets/ljspeech.py @@ -63,7 +63,7 @@ def __init__(self, download_url(url, root, hash_value=checksum) extract_archive(archive) - with open(self._metadata_path, "r") as metadata: + with open(self._metadata_path, "r", newline='') as metadata: walker = unicode_csv_reader(metadata, delimiter="|", quoting=csv.QUOTE_NONE) self._walker = list(walker) diff --git a/torchaudio/functional.py b/torchaudio/functional.py index 53795fef1a..4b79c01960 100644 --- a/torchaudio/functional.py +++ b/torchaudio/functional.py @@ -8,7 +8,6 @@ from torch import Tensor __all__ = [ - "istft", "spectrogram", "griffinlim", "amplitude_to_DB", @@ -45,79 +44,6 @@ ] -def istft( - stft_matrix: Tensor, - n_fft: int, - hop_length: Optional[int] = None, - win_length: Optional[int] = None, - window: Optional[Tensor] = None, - center: bool = True, - pad_mode: Optional[str] = None, - normalized: bool = False, - onesided: bool = True, - length: Optional[int] = None, -) -> Tensor: - r"""Inverse short time Fourier Transform. This is expected to be the inverse of torch.stft. - It has the same parameters (+ additional optional parameter of ``length``) and it should return the - least squares estimation of the original signal. The algorithm will check using the NOLA condition ( - nonzero overlap). - - Important consideration in the parameters ``window`` and ``center`` so that the envelop - created by the summation of all the windows is never zero at certain point in time. Specifically, - :math:`\sum_{t=-\infty}^{\infty} w^2[n-t\times hop\_length] \cancel{=} 0`. - - Since stft discards elements at the end of the signal if they do not fit in a frame, the - istft may return a shorter signal than the original signal (can occur if ``center`` is False - since the signal isn't padded). - - If ``center`` is True, then there will be padding e.g. 'constant', 'reflect', etc. Left padding - can be trimmed off exactly because they can be calculated but right padding cannot be calculated - without additional information. - - Example: Suppose the last window is: - [17, 18, 0, 0, 0] vs [18, 0, 0, 0, 0] - - The n_frame, hop_length, win_length are all the same which prevents the calculation of right padding. - These additional values could be zeros or a reflection of the signal so providing ``length`` - could be useful. If ``length`` is ``None`` then padding will be aggressively removed - (some loss of signal). - - [1] D. W. Griffin and J. S. Lim, "Signal estimation from modified short-time Fourier transform," - IEEE Trans. ASSP, vol.32, no.2, pp.236-243, Apr. 1984. - - Args: - stft_matrix (Tensor): Output of stft where each row of a channel is a frequency and each - column is a window. It has a size of either (..., fft_size, n_frame, 2) - n_fft (int): Size of Fourier transform - hop_length (int or None, optional): The distance between neighboring sliding window frames. - (Default: ``win_length // 4``) - win_length (int or None, optional): The size of window frame and STFT filter. (Default: ``n_fft``) - window (Tensor or None, optional): The optional window function. - (Default: ``torch.ones(win_length)``) - center (bool, optional): Whether ``input`` was padded on both sides so - that the :math:`t`-th frame is centered at time :math:`t \times \text{hop\_length}`. - (Default: ``True``) - pad_mode: This argument was ignored and to be removed. - normalized (bool, optional): Whether the STFT was normalized. (Default: ``False``) - onesided (bool, optional): Whether the STFT is onesided. (Default: ``True``) - length (int or None, optional): The amount to trim the signal by (i.e. the - original signal length). (Default: whole signal) - - Returns: - Tensor: Least squares estimation of the original signal of size (..., signal_length) - """ - warnings.warn( - 'istft has been moved to PyTorch and will be removed from torchaudio, ' - 'please use torch.istft instead.') - if pad_mode is not None: - warnings.warn( - 'The parameter `pad_mode` was ignored in isftft, and is thus being deprecated. ' - 'Please set `pad_mode` to None to suppress this warning.') - return torch.istft( - input=stft_matrix, n_fft=n_fft, hop_length=hop_length, win_length=win_length, window=window, - center=center, normalized=normalized, onesided=onesided, length=length) - - def spectrogram( waveform: Tensor, pad: int, @@ -250,12 +176,12 @@ def griffinlim( tprev = rebuilt # Invert with our current estimate of the phases - inverse = istft(specgram * angles, - n_fft=n_fft, - hop_length=hop_length, - win_length=win_length, - window=window, - length=length).float() + inverse = torch.istft(specgram * angles, + n_fft=n_fft, + hop_length=hop_length, + win_length=win_length, + window=window, + length=length).float() # Rebuild the spectrogram rebuilt = torch.stft(inverse, n_fft, hop_length, win_length, window, @@ -268,12 +194,12 @@ def griffinlim( angles = angles.div(complex_norm(angles).add(1e-16).unsqueeze(-1).expand_as(angles)) # Return the final phase estimates - waveform = istft(specgram * angles, - n_fft=n_fft, - hop_length=hop_length, - win_length=win_length, - window=window, - length=length) + waveform = torch.istft(specgram * angles, + n_fft=n_fft, + hop_length=hop_length, + win_length=win_length, + window=window, + length=length) # unpack batch waveform = waveform.reshape(shape[:-2] + waveform.shape[-1:]) diff --git a/torchaudio/models/__init__.py b/torchaudio/models/__init__.py index 20c1bdf265..8e05b8b509 100644 --- a/torchaudio/models/__init__.py +++ b/torchaudio/models/__init__.py @@ -1,2 +1,2 @@ from .wav2letter import * -from ._wavernn import * +from .wavernn import * diff --git a/torchaudio/models/_wavernn.py b/torchaudio/models/wavernn.py similarity index 83% rename from torchaudio/models/_wavernn.py rename to torchaudio/models/wavernn.py index 37a06edfc3..8fbd111a72 100644 --- a/torchaudio/models/_wavernn.py +++ b/torchaudio/models/wavernn.py @@ -4,10 +4,10 @@ from torch import Tensor from torch import nn -__all__ = ["_ResBlock", "_MelResNet", "_Stretch2d", "_UpsampleNetwork", "_WaveRNN"] +__all__ = ["ResBlock", "MelResNet", "Stretch2d", "UpsampleNetwork", "WaveRNN"] -class _ResBlock(nn.Module): +class ResBlock(nn.Module): r"""ResNet block based on "Deep Residual Learning for Image Recognition" The paper link is https://arxiv.org/pdf/1512.03385.pdf. @@ -16,7 +16,7 @@ class _ResBlock(nn.Module): n_freq: the number of bins in a spectrogram. (Default: ``128``) Examples - >>> resblock = _ResBlock() + >>> resblock = ResBlock() >>> input = torch.rand(10, 128, 512) # a random spectrogram >>> output = resblock(input) # shape: (10, 128, 512) """ @@ -33,9 +33,9 @@ def __init__(self, n_freq: int = 128) -> None: ) def forward(self, specgram: Tensor) -> Tensor: - r"""Pass the input through the _ResBlock layer. + r"""Pass the input through the ResBlock layer. Args: - specgram (Tensor): the input sequence to the _ResBlock layer (n_batch, n_freq, n_time). + specgram (Tensor): the input sequence to the ResBlock layer (n_batch, n_freq, n_time). Return: Tensor shape: (n_batch, n_freq, n_time) @@ -44,7 +44,7 @@ def forward(self, specgram: Tensor) -> Tensor: return self.resblock_model(specgram) + specgram -class _MelResNet(nn.Module): +class MelResNet(nn.Module): r"""MelResNet layer uses a stack of ResBlocks on spectrogram. Args: @@ -55,7 +55,7 @@ class _MelResNet(nn.Module): kernel_size: the number of kernel size in the first Conv1d layer. (Default: ``5``) Examples - >>> melresnet = _MelResNet() + >>> melresnet = MelResNet() >>> input = torch.rand(10, 128, 512) # a random spectrogram >>> output = melresnet(input) # shape: (10, 128, 508) """ @@ -68,7 +68,7 @@ def __init__(self, kernel_size: int = 5) -> None: super().__init__() - ResBlocks = [_ResBlock(n_hidden) for _ in range(n_res_block)] + ResBlocks = [ResBlock(n_hidden) for _ in range(n_res_block)] self.melresnet_model = nn.Sequential( nn.Conv1d(in_channels=n_freq, out_channels=n_hidden, kernel_size=kernel_size, bias=False), @@ -79,9 +79,9 @@ def __init__(self, ) def forward(self, specgram: Tensor) -> Tensor: - r"""Pass the input through the _MelResNet layer. + r"""Pass the input through the MelResNet layer. Args: - specgram (Tensor): the input sequence to the _MelResNet layer (n_batch, n_freq, n_time). + specgram (Tensor): the input sequence to the MelResNet layer (n_batch, n_freq, n_time). Return: Tensor shape: (n_batch, n_output, n_time - kernel_size + 1) @@ -90,7 +90,7 @@ def forward(self, specgram: Tensor) -> Tensor: return self.melresnet_model(specgram) -class _Stretch2d(nn.Module): +class Stretch2d(nn.Module): r"""Upscale the frequency and time dimensions of a spectrogram. Args: @@ -98,7 +98,7 @@ class _Stretch2d(nn.Module): freq_scale: the scale factor in frequency dimension Examples - >>> stretch2d = _Stretch2d(time_scale=10, freq_scale=5) + >>> stretch2d = Stretch2d(time_scale=10, freq_scale=5) >>> input = torch.rand(10, 100, 512) # a random spectrogram >>> output = stretch2d(input) # shape: (10, 500, 5120) @@ -113,10 +113,10 @@ def __init__(self, self.time_scale = time_scale def forward(self, specgram: Tensor) -> Tensor: - r"""Pass the input through the _Stretch2d layer. + r"""Pass the input through the Stretch2d layer. Args: - specgram (Tensor): the input sequence to the _Stretch2d layer (..., n_freq, n_time). + specgram (Tensor): the input sequence to the Stretch2d layer (..., n_freq, n_time). Return: Tensor shape: (..., n_freq * freq_scale, n_time * time_scale) @@ -125,7 +125,7 @@ def forward(self, specgram: Tensor) -> Tensor: return specgram.repeat_interleave(self.freq_scale, -2).repeat_interleave(self.time_scale, -1) -class _UpsampleNetwork(nn.Module): +class UpsampleNetwork(nn.Module): r"""Upscale the dimensions of a spectrogram. Args: @@ -137,7 +137,7 @@ class _UpsampleNetwork(nn.Module): kernel_size: the number of kernel size in the first Conv1d layer. (Default: ``5``) Examples - >>> upsamplenetwork = _UpsampleNetwork(upsample_scales=[4, 4, 16]) + >>> upsamplenetwork = UpsampleNetwork(upsample_scales=[4, 4, 16]) >>> input = torch.rand(10, 128, 10) # a random spectrogram >>> output = upsamplenetwork(input) # shape: (10, 1536, 128), (10, 1536, 128) """ @@ -156,12 +156,12 @@ def __init__(self, total_scale *= upsample_scale self.indent = (kernel_size - 1) // 2 * total_scale - self.resnet = _MelResNet(n_res_block, n_freq, n_hidden, n_output, kernel_size) - self.resnet_stretch = _Stretch2d(total_scale, 1) + self.resnet = MelResNet(n_res_block, n_freq, n_hidden, n_output, kernel_size) + self.resnet_stretch = Stretch2d(total_scale, 1) up_layers = [] for scale in upsample_scales: - stretch = _Stretch2d(scale, 1) + stretch = Stretch2d(scale, 1) conv = nn.Conv2d(in_channels=1, out_channels=1, kernel_size=(1, scale * 2 + 1), @@ -173,10 +173,10 @@ def __init__(self, self.upsample_layers = nn.Sequential(*up_layers) def forward(self, specgram: Tensor) -> Tuple[Tensor, Tensor]: - r"""Pass the input through the _UpsampleNetwork layer. + r"""Pass the input through the UpsampleNetwork layer. Args: - specgram (Tensor): the input sequence to the _UpsampleNetwork layer (n_batch, n_freq, n_time) + specgram (Tensor): the input sequence to the UpsampleNetwork layer (n_batch, n_freq, n_time) Return: Tensor shape: (n_batch, n_freq, (n_time - kernel_size + 1) * total_scale), @@ -195,7 +195,7 @@ def forward(self, specgram: Tensor) -> Tuple[Tensor, Tensor]: return upsampling_output, resnet_output -class _WaveRNN(nn.Module): +class WaveRNN(nn.Module): r"""WaveRNN model based on the implementation from `fatchord `_. The original implementation was introduced in @@ -216,7 +216,7 @@ class _WaveRNN(nn.Module): n_output: the number of output dimensions of melresnet. (Default: ``128``) Example - >>> wavernn = _waveRNN(upsample_scales=[5,5,8], n_classes=512, hop_length=200) + >>> wavernn = WaveRNN(upsample_scales=[5,5,8], n_classes=512, hop_length=200) >>> waveform, sample_rate = torchaudio.load(file) >>> # waveform shape: (n_batch, n_channel, (n_time - kernel_size + 1) * hop_length) >>> specgram = MelSpectrogram(sample_rate)(waveform) # shape: (n_batch, n_channel, n_freq, n_time) @@ -249,12 +249,12 @@ def __init__(self, if total_scale != self.hop_length: raise ValueError(f"Expected: total_scale == hop_length, but found {total_scale} != {hop_length}") - self.upsample = _UpsampleNetwork(upsample_scales, - n_res_block, - n_freq, - n_hidden, - n_output, - kernel_size) + self.upsample = UpsampleNetwork(upsample_scales, + n_res_block, + n_freq, + n_hidden, + n_output, + kernel_size) self.fc = nn.Linear(n_freq + self.n_aux + 1, n_rnn) self.rnn1 = nn.GRU(n_rnn, n_rnn, batch_first=True) @@ -268,11 +268,11 @@ def __init__(self, self.fc3 = nn.Linear(n_fc, self.n_classes) def forward(self, waveform: Tensor, specgram: Tensor) -> Tensor: - r"""Pass the input through the _WaveRNN model. + r"""Pass the input through the WaveRNN model. Args: - waveform: the input waveform to the _WaveRNN layer (n_batch, 1, (n_time - kernel_size + 1) * hop_length) - specgram: the input spectrogram to the _WaveRNN layer (n_batch, 1, n_freq, n_time) + waveform: the input waveform to the WaveRNN layer (n_batch, 1, (n_time - kernel_size + 1) * hop_length) + specgram: the input spectrogram to the WaveRNN layer (n_batch, 1, n_freq, n_time) Return: Tensor shape: (n_batch, 1, (n_time - kernel_size + 1) * hop_length, n_classes) diff --git a/torchaudio/transforms.py b/torchaudio/transforms.py index ea0d6db492..ef0a58e637 100644 --- a/torchaudio/transforms.py +++ b/torchaudio/transforms.py @@ -141,8 +141,8 @@ def __init__(self, rand_init: bool = True) -> None: super(GriffinLim, self).__init__() - assert momentum < 1, 'momentum=%s > 1 can be unstable' % momentum - assert momentum > 0, 'momentum=%s < 0' % momentum + assert momentum < 1, 'momentum={} > 1 can be unstable'.format(momentum) + assert momentum > 0, 'momentum={} < 0'.format(momentum) self.n_fft = n_fft self.n_iter = n_iter @@ -237,7 +237,7 @@ def __init__(self, self.f_max = f_max if f_max is not None else float(sample_rate // 2) self.f_min = f_min - assert f_min <= self.f_max, 'Require f_min: %f < f_max: %f' % (f_min, self.f_max) + assert f_min <= self.f_max, 'Require f_min: {} < f_max: {}'.format(f_min, self.f_max) fb = torch.empty(0) if n_stft is None else F.create_fb_matrix( n_stft, self.f_min, self.f_max, self.n_mels, self.sample_rate) @@ -313,7 +313,7 @@ def __init__(self, self.tolerance_change = tolerance_change self.sgdargs = sgdargs or {'lr': 0.1, 'momentum': 0.9} - assert f_min <= self.f_max, 'Require f_min: %f < f_max: %f' % (f_min, self.f_max) + assert f_min <= self.f_max, 'Require f_min: {} < f_max: {}'.format(f_min, self.f_max) fb = F.create_fb_matrix(n_stft, self.f_min, self.f_max, self.n_mels, self.sample_rate) self.register_buffer('fb', fb) @@ -607,7 +607,7 @@ def forward(self, waveform: Tensor) -> Tensor: return waveform - raise ValueError('Invalid resampling method: ' + str(self.resampling_method)) + raise ValueError('Invalid resampling method: {}'.format(self.resampling_method)) class ComplexNorm(torch.nn.Module): From 3019ce03a2855abdfc397721f4299ba79fbe7b2e Mon Sep 17 00:00:00 2001 From: Andres Suarez Date: Wed, 5 Aug 2020 18:26:48 -0700 Subject: [PATCH 16/73] Remove .python3 markers Reviewed By: ashwinp-fb Differential Revision: D22955630 fbshipit-source-id: f00ef17a905e4c7cd9196c8924db39f9cdfe8cfa --- .python3 | 0 1 file changed, 0 insertions(+), 0 deletions(-) delete mode 100644 .python3 diff --git a/.python3 b/.python3 deleted file mode 100644 index e69de29bb2..0000000000 From aa8c98d3aca64739266a8fb714d299b5f7ff3507 Mon Sep 17 00:00:00 2001 From: Moto Hira Date: Tue, 22 Sep 2020 10:59:56 -0700 Subject: [PATCH 17/73] Import torchaudio 20200821 Reviewed By: cpuhrsch Differential Revision: D23273584 fbshipit-source-id: 2fe7effa11b7f7cdf0cee1da6b1cac5556e9f55b --- .circleci/config.yml | 42 +++++- .circleci/config.yml.in | 42 +++++- .circleci/torchscript_bc_test/common.sh | 73 +++++++++ .circleci/torchscript_bc_test/environment.yml | 17 +++ .../torchscript_bc_test/generate_objects.sh | 26 ++++ .../torchscript_bc_test/setup_master_envs.sh | 17 +++ .../torchscript_bc_test/setup_release_envs.sh | 18 +++ .../torchscript_bc_test/validate_objects.sh | 30 ++++ .../unittest/linux/scripts/environment.yml | 5 +- .../unittest/windows/scripts/environment.yml | 3 +- docs/source/datasets.rst | 7 + examples/pipeline_wavernn/main.py | 5 +- examples/pipeline_wavernn/processing.py | 13 +- test/README.md | 131 +--------------- test/torchaudio_unittest/README.md | 131 ++++++++++++++++ .../torchaudio_unittest/datasets/vctk_test.py | 91 ++++++++++++ .../sox_io_backend/info_test.py | 14 ++ .../sox_io_backend/load_test.py | 30 ++++ .../sox_io_backend/save_test.py | 40 +++++ .../torchscript_consistency_impl.py | 7 + test/torchscript_bc_test/README.md | 23 +++ test/torchscript_bc_test/main.py | 71 +++++++++ test/torchscript_bc_test/ver_060.py | 71 +++++++++ torchaudio/backend/sox_io_backend.py | 4 +- torchaudio/csrc/register.cpp | 140 ++++++++---------- torchaudio/csrc/sox_utils.cpp | 6 + torchaudio/datasets/__init__.py | 3 +- torchaudio/datasets/vctk.py | 139 +++++++++++++++-- torchaudio/functional.py | 3 +- 29 files changed, 970 insertions(+), 232 deletions(-) create mode 100644 .circleci/torchscript_bc_test/common.sh create mode 100644 .circleci/torchscript_bc_test/environment.yml create mode 100755 .circleci/torchscript_bc_test/generate_objects.sh create mode 100755 .circleci/torchscript_bc_test/setup_master_envs.sh create mode 100755 .circleci/torchscript_bc_test/setup_release_envs.sh create mode 100755 .circleci/torchscript_bc_test/validate_objects.sh create mode 100644 test/torchaudio_unittest/README.md create mode 100644 test/torchaudio_unittest/datasets/vctk_test.py create mode 100644 test/torchscript_bc_test/README.md create mode 100755 test/torchscript_bc_test/main.py create mode 100644 test/torchscript_bc_test/ver_060.py diff --git a/.circleci/config.yml b/.circleci/config.yml index 771dccc515..70b7c54ef5 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -277,12 +277,13 @@ jobs: steps: - attach_workspace: at: ~/workspace + - designate_upload_channel - run: name: install binaries command: | set -x source /usr/local/etc/profile.d/conda.sh && conda activate python${PYTHON_VERSION} - conda install -v -y -c pytorch-test -c pytorch-nightly pytorch + conda install -v -y -c pytorch-${UPLOAD_CHANNEL} pytorch conda install -v -y $(ls ~/workspace/torchaudio*.tar.bz2) - run: name: smoke test @@ -604,6 +605,42 @@ jobs: name: Run style check command: .circleci/unittest/linux/scripts/run_style_checks.sh + torchscript_bc_test: + docker: + - image: "pytorch/torchaudio_unittest_base:manylinux" + resource_class: large + steps: + - checkout + - generate_cache_key + - restore_cache: + + keys: + - torchscript-bc-test-release-envs-v1-{{ arch }}-{{ checksum ".cachekey" }} + + - run: + name: Generate Objects + command: | + .circleci/torchscript_bc_test/setup_release_envs.sh + .circleci/torchscript_bc_test/generate_objects.sh + - save_cache: + + key: torchscript-bc-test-release-envs-v1-{{ arch }}-{{ checksum ".cachekey" }} + + paths: + - conda + - envs + - store_artifacts: + path: test/torchscript_bc_test/assets + - persist_to_workspace: + root: . + paths: + - test/torchscript_bc_test/assets + - run: + name: Run BC check test + command: | + .circleci/torchscript_bc_test/setup_master_envs.sh + .circleci/torchscript_bc_test/validate_objects.sh + workflows: build: jobs: @@ -690,6 +727,9 @@ workflows: python_version: '3.8' unittest: jobs: + - torchscript_bc_test: + requires: + - download_third_parties_nix - download_third_parties_nix: name: download_third_parties_nix - unittest_linux_cpu: diff --git a/.circleci/config.yml.in b/.circleci/config.yml.in index 6d6d77d50f..94220d02c0 100644 --- a/.circleci/config.yml.in +++ b/.circleci/config.yml.in @@ -277,12 +277,13 @@ jobs: steps: - attach_workspace: at: ~/workspace + - designate_upload_channel - run: name: install binaries command: | set -x source /usr/local/etc/profile.d/conda.sh && conda activate python${PYTHON_VERSION} - conda install -v -y -c pytorch-test -c pytorch-nightly pytorch + conda install -v -y -c pytorch-${UPLOAD_CHANNEL} pytorch conda install -v -y $(ls ~/workspace/torchaudio*.tar.bz2) - run: name: smoke test @@ -604,6 +605,42 @@ jobs: name: Run style check command: .circleci/unittest/linux/scripts/run_style_checks.sh + torchscript_bc_test: + docker: + - image: "pytorch/torchaudio_unittest_base:manylinux" + resource_class: large + steps: + - checkout + - generate_cache_key + - restore_cache: + {% raw %} + keys: + - torchscript-bc-test-release-envs-v1-{{ arch }}-{{ checksum ".cachekey" }} + {% endraw %} + - run: + name: Generate Objects + command: | + .circleci/torchscript_bc_test/setup_release_envs.sh + .circleci/torchscript_bc_test/generate_objects.sh + - save_cache: + {% raw %} + key: torchscript-bc-test-release-envs-v1-{{ arch }}-{{ checksum ".cachekey" }} + {% endraw %} + paths: + - conda + - envs + - store_artifacts: + path: test/torchscript_bc_test/assets + - persist_to_workspace: + root: . + paths: + - test/torchscript_bc_test/assets + - run: + name: Run BC check test + command: | + .circleci/torchscript_bc_test/setup_master_envs.sh + .circleci/torchscript_bc_test/validate_objects.sh + workflows: build: jobs: @@ -611,6 +648,9 @@ workflows: {{ build_workflows() }} unittest: jobs: + - torchscript_bc_test: + requires: + - download_third_parties_nix {{ unittest_workflows() }} nightly: jobs: diff --git a/.circleci/torchscript_bc_test/common.sh b/.circleci/torchscript_bc_test/common.sh new file mode 100644 index 0000000000..51d258a2d9 --- /dev/null +++ b/.circleci/torchscript_bc_test/common.sh @@ -0,0 +1,73 @@ +#!/usr/bin/env bash + +declare -a TORCHAUDIO_VERSIONS=("0.6.0") +declare -a PYTHON_VERSIONS=("3.6" "3.7" "3.8") + +export TORCHAUDIO_VERSIONS +export PYTHON_VERSIONS + +export KALDI_ROOT="${KALDI_ROOT:-$HOME}" # Just to disable warning emitted from kaldi_io + +_this_dir="$( cd "$( dirname "${BASH_SOURCE[0]}" )" >/dev/null 2>&1 && pwd )" +_root_dir="$(git rev-parse --show-toplevel)" +_conda_dir="${_root_dir}/conda" +case "$(uname -s)" in + Darwin*) _os="MacOSX";; + *) _os="Linux" +esac + +install_conda() { + if [ ! -d "${_conda_dir}" ]; then + printf "* Installing conda\n" + wget -nv -O miniconda.sh "http://repo.continuum.io/miniconda/Miniconda3-latest-${_os}-x86_64.sh" + bash ./miniconda.sh -b -f -p "${_conda_dir}" + rm miniconda.sh + fi +} + +init_conda() { + eval "$("${_conda_dir}/bin/conda" shell.bash hook)" +} + +get_name() { + echo "${1}-py${2}" +} + +get_env_dir() { + echo "${_root_dir}/envs/$(get_name "$1" "$2")" +} + +create_env() { + env_dir="$(get_env_dir "$1" "$2")" + if [ ! -d "${env_dir}" ]; then + printf "* Creating environment torchaudio: %s, Python: %s\n" "$1" "$2" + conda create -q --prefix "${env_dir}" -y python="$2" + fi +} + +activate_env() { + printf "* Activating environment torchaudio: %s, Python: %s\n" "$1" "$2" + conda activate "$(get_env_dir "$1" "$2")" +} + +install_release() { + printf "* Installing torchaudio: %s\n" "$1" + conda install -y -q torchaudio="$1" packaging -c pytorch + # packaging is required in test to validate the torchaudio version for dump +} + +install_build_dependencies() { + printf "* Installing torchaudio dependencies except PyTorch - (Python: %s)\n" "$1" + conda env update -q --file "${_this_dir}/environment.yml" --prune + if [ "${_os}" == Linux ]; then + pip install clang-format + fi +} + +build_master() { + printf "* Installing PyTorch (py%s)\n" "$1" + conda install -y -q pytorch "cpuonly" -c pytorch-nightly + printf "* Installing torchaudio\n" + cd "${_root_dir}" || exit 1 + BUILD_SOX=1 python setup.py clean install +} diff --git a/.circleci/torchscript_bc_test/environment.yml b/.circleci/torchscript_bc_test/environment.yml new file mode 100644 index 0000000000..108d97d193 --- /dev/null +++ b/.circleci/torchscript_bc_test/environment.yml @@ -0,0 +1,17 @@ +channels: + - conda-forge + - defaults +dependencies: + - flake8 + - numpy + - pytest + - pytest-cov + - codecov + - librosa + - llvmlite==0.31 # See https://github.com/pytorch/audio/pull/766 + - pip + - pip: + - kaldi-io + - scipy + - parameterized + - numba==0.48 # See https://github.com/librosa/librosa/issues/1160 diff --git a/.circleci/torchscript_bc_test/generate_objects.sh b/.circleci/torchscript_bc_test/generate_objects.sh new file mode 100755 index 0000000000..352f137ad2 --- /dev/null +++ b/.circleci/torchscript_bc_test/generate_objects.sh @@ -0,0 +1,26 @@ +#!/usr/bin/env bash + +set -e + +this_dir="$( cd "$( dirname "${BASH_SOURCE[0]}" )" >/dev/null 2>&1 && pwd )" +pushd "${this_dir}" +. "common.sh" +popd + +init_conda + +# Move to test directory so that the checked out torchaudio source +# will not shadow the conda-installed version of torchaudio +cd test + +for torchaudio in "${TORCHAUDIO_VERSIONS[@]}" ; do + for python in "${PYTHON_VERSIONS[@]}" ; do + activate_env "${torchaudio}" "${python}" + python -m torch.utils.collect_env + printf "***********************************************************\n" + printf "* Generating\n" + printf " Objects: Python: %s, torchaudio: %s\n" "${python}" "${torchaudio}" + printf "***********************************************************\n" + ./torchscript_bc_test/main.py --mode generate --version "${torchaudio}" + done +done diff --git a/.circleci/torchscript_bc_test/setup_master_envs.sh b/.circleci/torchscript_bc_test/setup_master_envs.sh new file mode 100755 index 0000000000..2321ee0529 --- /dev/null +++ b/.circleci/torchscript_bc_test/setup_master_envs.sh @@ -0,0 +1,17 @@ +#!/usr/bin/env bash + +set -e + +cd "$( dirname "${BASH_SOURCE[0]}" )" +. "common.sh" + +install_conda +init_conda + +# Install torchaudio environments +for python in "${PYTHON_VERSIONS[@]}" ; do + create_env master "${python}" + activate_env master "${python}" + install_build_dependencies "${python}" + build_master "${python}" +done diff --git a/.circleci/torchscript_bc_test/setup_release_envs.sh b/.circleci/torchscript_bc_test/setup_release_envs.sh new file mode 100755 index 0000000000..3816c091d4 --- /dev/null +++ b/.circleci/torchscript_bc_test/setup_release_envs.sh @@ -0,0 +1,18 @@ +#!/usr/bin/env bash + +set -e + +cd "$( dirname "${BASH_SOURCE[0]}" )" +. "common.sh" + +install_conda +init_conda + +# Install torchaudio environments +for torchaudio in "${TORCHAUDIO_VERSIONS[@]}" ; do + for python in "${PYTHON_VERSIONS[@]}" ; do + create_env "${torchaudio}" "${python}" + activate_env "${torchaudio}" "${python}" + install_release "${torchaudio}" + done +done diff --git a/.circleci/torchscript_bc_test/validate_objects.sh b/.circleci/torchscript_bc_test/validate_objects.sh new file mode 100755 index 0000000000..852ed0acc8 --- /dev/null +++ b/.circleci/torchscript_bc_test/validate_objects.sh @@ -0,0 +1,30 @@ +#!/usr/bin/env bash + +set -e + +this_dir="$( cd "$( dirname "${BASH_SOURCE[0]}" )" >/dev/null 2>&1 && pwd )" +pushd "${this_dir}" +. "common.sh" +popd + +init_conda + +# Move to test directory so that the checked out torchaudio source +# will not shadow the conda-installed version of torchaudio +cd test + +# Validate torchscript objects for each +for runtime_python in "${PYTHON_VERSIONS[@]}" ; do + activate_env master "${runtime_python}" + python -m torch.utils.collect_env + for object_torchaudio in "${TORCHAUDIO_VERSIONS[@]}" ; do + for object_python in "${PYTHON_VERSIONS[@]}" ; do + printf "***********************************************************\n" + printf "* Validating\n" + printf " Runtime: Python: %s, torchaudio: master (%s)\n" "${runtime_python}" "$(python -c 'import torchaudio;print(torchaudio.__version__)')" + printf " Objects: Python: %s, torchaudio: %s\n" "${object_python}" "${object_torchaudio}" + printf "***********************************************************\n" + ./torchscript_bc_test/main.py --mode validate --version "${object_torchaudio}" + done + done +done diff --git a/.circleci/unittest/linux/scripts/environment.yml b/.circleci/unittest/linux/scripts/environment.yml index 121478165e..f68fb130a2 100644 --- a/.circleci/unittest/linux/scripts/environment.yml +++ b/.circleci/unittest/linux/scripts/environment.yml @@ -3,16 +3,15 @@ channels: - defaults dependencies: - flake8 - - numpy + - numpy >= 1.11 - pytest - pytest-cov - pytest-xdist - codecov - - librosa + - librosa>=0.8.0 - llvmlite==0.31 # See https://github.com/pytorch/audio/pull/766 - pip - pip: - kaldi-io - scipy - parameterized - - numba==0.48 # See https://github.com/librosa/librosa/issues/1160 diff --git a/.circleci/unittest/windows/scripts/environment.yml b/.circleci/unittest/windows/scripts/environment.yml index fb57f0facc..3a41020645 100644 --- a/.circleci/unittest/windows/scripts/environment.yml +++ b/.circleci/unittest/windows/scripts/environment.yml @@ -12,7 +12,6 @@ dependencies: - scipy == 1.4.1 - kaldi-io - PySoundFile - - librosa + - librosa >= 0.8.0 - future - parameterized - - numba==0.48 diff --git a/docs/source/datasets.rst b/docs/source/datasets.rst index 96ba045c5e..6cdf44e223 100644 --- a/docs/source/datasets.rst +++ b/docs/source/datasets.rst @@ -88,6 +88,13 @@ VCTK :members: __getitem__ :special-members: + +VCTK_092 +~~~~~~~~ + +.. autoclass:: VCTK_092 + + YESNO ~~~~~ diff --git a/examples/pipeline_wavernn/main.py b/examples/pipeline_wavernn/main.py index 9620dd5d45..28ecb76fb9 100644 --- a/examples/pipeline_wavernn/main.py +++ b/examples/pipeline_wavernn/main.py @@ -163,6 +163,9 @@ def parse_args(): parser.add_argument( "--file-path", default="", type=str, help="the path of audio files", ) + parser.add_argument( + "--normalization", default=True, action="store_true", help="if True, spectrogram is normalized", + ) args = parser.parse_args() return args @@ -273,7 +276,7 @@ def main(args): n_mels=args.n_freq, fmin=args.f_min, ), - NormalizeDB(min_level_db=args.min_level_db), + NormalizeDB(min_level_db=args.min_level_db, normalization=args.normalization), ) train_dataset, val_dataset = split_process_dataset(args, transforms) diff --git a/examples/pipeline_wavernn/processing.py b/examples/pipeline_wavernn/processing.py index b22d60dae4..dca45e97f4 100644 --- a/examples/pipeline_wavernn/processing.py +++ b/examples/pipeline_wavernn/processing.py @@ -31,15 +31,18 @@ class NormalizeDB(nn.Module): r"""Normalize the spectrogram with a minimum db value """ - def __init__(self, min_level_db): + def __init__(self, min_level_db, normalization): super().__init__() self.min_level_db = min_level_db + self.normalization = normalization def forward(self, specgram): - specgram = 20 * torch.log10(torch.clamp(specgram, min=1e-5)) - return torch.clamp( - (self.min_level_db - specgram) / self.min_level_db, min=0, max=1 - ) + specgram = torch.log10(torch.clamp(specgram, min=1e-5)) + if self.normalization: + return torch.clamp( + (self.min_level_db - 20 * specgram) / self.min_level_db, min=0, max=1 + ) + return specgram def normalized_waveform_to_bits(waveform, bits): diff --git a/test/README.md b/test/README.md index 629e5b54be..62d32b428d 100644 --- a/test/README.md +++ b/test/README.md @@ -1,131 +1,4 @@ # Torchaudio Test Suite -## How to run test - -You can use `pytest` to run `torchaudio`'s test suites. See https://docs.pytest.org/ for the detail of how to use `pytest` command. - -``` -# List up all the tests -pytest test --collect-only -# Run all the test suites -pytest test -# Run tests on sox_effects module -pytest test/sox_effect -# use -k to apply filter -pytest test/sox_io_backend -k load # only runs tests where their names contain load -# Some other useful options; -# Stop on the first failure -x -# Run failure fast --ff -# Only rerun the failure --lf -``` - -**Note** -We use PyTorch's test utilities instead of `pytest` frameworks when writing tests to avoid reinventing the wheel for Tensor comparison. - -## Structure of tests - -The following is an overview of the tests and related modules for `torchaudio`. - -### Purpose specific test suites - -#### Numerical compatibility agains existing software -- [Librosa compatibility test](./torchaudio_unittest/librosa_compatibility_test.py) - Test suite for numerical compatibility against librosa. -- [SoX compatibility test](./torchaudio_unittest/sox_compatibility_test.py) - Test suite for numerical compatibility against SoX. -- [Kaldi compatibility test](./torchaudio_unittest/kaldi_compatibility_test.py) - Test suite for numerical compatibility against Kaldi. - -#### Result consistency with PyTorch framework -- [TorchScript consistency test](./torchaudio_unittest/torchscript_consistency_impl.py) - Test suite to check 1. if an API is TorchScript-able, and 2. the results from Python and Torchscript match. -- [Batch consistency test](./torchaudio_unittest/batch_consistency_test.py) - Test suite to check if functionals/Transforms handle single sample input and batch input and return the same result. - -### Module specific test suites - -The following test modules are defined for corresponding `torchaudio` module/functions. - -- [`torchaudio.datasets`](./torchaudio_unittest/datasets) -- [`torchaudio.functional`](./torchaudio_unittest/functional) -- [`torchaudio.transforms`](./torchaudio_unittest/transforms_test.py) -- [`torchaudio.compliance.kaldi`](./torchaudio_unittest/compliance_kaldi_test.py) -- [`torchaudio.kaldi_io`](./torchaudio_unittest/kaldi_io_test.py) -- [`torchaudio.sox_effects`](test/sox_effects) -- [`torchaudio.save`, `torchaudio.load`, `torchaudio.info`](./torchaudio_unittest/io_test.py) - -### Test modules that do not fall into the above categories -- [test_dataloader.py](./torchaudio_unittest/dataloader_test.py) - Simple test for loading data and applying preprocessing. - -### Support files -- [assets](./torchaudio_unittest/assets): Contain sample audio files. -- [assets/kaldi](./torchaudio_unittest/assets/kaldi): Contains Kaldi format matrix files used in [./torchaudio_unittest/test_compliance_kaldi.py](./torchaudio_unittest/test_compliance_kaldi.py). -- [compliance](./torchaudio_unittest/compliance): Scripts used to generate above Kaldi matrix files. - -### Waveforms for Testing Purposes - -When testing transforms we often need waveforms of specific type (ex: pure tone, noise, or voice), with specific bitrate (ex. 8 or 16 kHz) and number of channels (ex. mono, stereo). Below are some tips on how to construct waveforms and guidance around existing audio files. - -#### Load a Waveform from a File - -```python -filepath = common_utils.get_asset_path('filename.wav') -waveform, sample_rate = common_utils.load_wav(filepath) -``` - -*Note: Should you choose to contribute an audio file, please leave a comment in the issue or pull request, mentioning content source and licensing information. WAV files are preferred. Other formats should be used only when there is no alternative. (i.e. dataset implementation comes with hardcoded non-wav extension).* - -#### Pure Tone - -Code: - -```python -waveform = common_utils.get_sinusoid( - frequency=300, - sample_rate=16000, - duration=1, # seconds - n_channels=1, - dtype="float32", - device="cpu", -) -``` - -#### Noise - -Code: - -```python -tensor = common_utils.get_whitenoise() -``` - -Files: - -* `steam-train-whistle-daniel_simon.wav` - -#### Voice - -Files: - -* `CommonVoice/cv-corpus-4-2019-12-10/tt/clips/common_voice_tt_00000000.wav` -* `VCTK-Corpus/wav48/p224/p224_002.wav` -* `vad-go-stereo-44100.wav` -* `vad-go-mono-32000.wav` - -## Adding test - -The following is the current practice of torchaudio test suite. - -1. Unless the tests are related to I/O, use synthetic data. [`common_utils`](./torchaudio_unittest/common_utils) has some data generator functions. -1. When you add a new test case, use `common_utils.TorchaudioTestCase` as base class unless you are writing tests that are common to CPU / CUDA. - - Set class memeber `dtype`, `device` and `backend` for the desired behavior. - - If you do not set `backend` value in your test suite, then I/O functions will be unassigned and attempt to load/save file will fail. - - For `backend` value, in addition to available backends, you can also provide the value "default" and backend will be picked automatically based on availability. -1. If you are writing tests that should pass on diffrent dtype/devices, write a common class inheriting `common_utils.TestBaseMixin`, then inherit `common_utils.PytorchTestCase` and define class attributes (`dtype` / `device` / `backend`) there. See [Torchscript consistency test implementation](./torchaudio_unittest/torchscript_consistency_impl.py) and test definitions for [CPU](./torchaudio_unittest/torchscript_consistency_cpu_test.py) and [CUDA](./torchaudio_unittest/torchscript_consistency_cuda_test.py) devices. -1. For numerically comparing Tensors, use `assertEqual` method from torchaudio_unittest.common_utils.PytorchTestCase` class. This method has a better support for a wide variety of Tensor types. - -When you add a new feature(functional/transform), consider the following - -1. When you add a new feature, please make it Torchscript-able and batch-consistent unless it degrades the performance. Please add the tests to see if the new feature meet these requirements. -1. If the feature should be numerical compatible against existing software (SoX, Librosa, Kaldi etc), add a corresponding test. -1. If the new feature is unique to `torchaudio` (not a PyTorch implementation of an existing Software functionality), consider adding correctness tests (wheather the expected output is produced for the set of input) under the corresponding test module (`test_functional.py`, `test_transforms.py`). +- [Unit Test](./torchaudio_unittest/) +- [Torchscript Backward Compatibility Test](./torchscript_bc_test/) \ No newline at end of file diff --git a/test/torchaudio_unittest/README.md b/test/torchaudio_unittest/README.md new file mode 100644 index 0000000000..306ca23098 --- /dev/null +++ b/test/torchaudio_unittest/README.md @@ -0,0 +1,131 @@ +# Torchaudio Unit Test Suite + +## How to run test + +You can use `pytest` to run `torchaudio`'s test suites. See https://docs.pytest.org/ for the detail of how to use `pytest` command. + +``` +# List up all the tests +pytest test --collect-only +# Run all the test suites +pytest test +# Run tests on sox_effects module +pytest test/sox_effect +# use -k to apply filter +pytest test/sox_io_backend -k load # only runs tests where their names contain load +# Some other useful options; +# Stop on the first failure -x +# Run failure fast --ff +# Only rerun the failure --lf +``` + +**Note** +We use PyTorch's test utilities instead of `pytest` frameworks when writing tests to avoid reinventing the wheel for Tensor comparison. + +## Structure of tests + +The following is an overview of the tests and related modules for `torchaudio`. + +### Purpose specific test suites + +#### Numerical compatibility agains existing software +- [Librosa compatibility test](./librosa_compatibility_test.py) + Test suite for numerical compatibility against librosa. +- [SoX compatibility test](./sox_compatibility_test.py) + Test suite for numerical compatibility against SoX. +- [Kaldi compatibility test](./kaldi_compatibility_test.py) + Test suite for numerical compatibility against Kaldi. + +#### Result consistency with PyTorch framework +- [TorchScript consistency test](./torchscript_consistency_impl.py) + Test suite to check 1. if an API is TorchScript-able, and 2. the results from Python and Torchscript match. +- [Batch consistency test](./batch_consistency_test.py) + Test suite to check if functionals/Transforms handle single sample input and batch input and return the same result. + +### Module specific test suites + +The following test modules are defined for corresponding `torchaudio` module/functions. + +- [`torchaudio.datasets`](./datasets) +- [`torchaudio.functional`](./functional) +- [`torchaudio.transforms`](./transforms_test.py) +- [`torchaudio.compliance.kaldi`](./compliance_kaldi_test.py) +- [`torchaudio.kaldi_io`](./kaldi_io_test.py) +- [`torchaudio.sox_effects`](test/sox_effects) +- [`torchaudio.save`, `torchaudio.load`, `torchaudio.info`](./io_test.py) + +### Test modules that do not fall into the above categories +- [test_dataloader.py](./dataloader_test.py) + Simple test for loading data and applying preprocessing. + +### Support files +- [assets](./assets): Contain sample audio files. +- [assets/kaldi](./assets/kaldi): Contains Kaldi format matrix files used in [./test_compliance_kaldi.py](./test_compliance_kaldi.py). +- [compliance](./compliance): Scripts used to generate above Kaldi matrix files. + +### Waveforms for Testing Purposes + +When testing transforms we often need waveforms of specific type (ex: pure tone, noise, or voice), with specific bitrate (ex. 8 or 16 kHz) and number of channels (ex. mono, stereo). Below are some tips on how to construct waveforms and guidance around existing audio files. + +#### Load a Waveform from a File + +```python +filepath = common_utils.get_asset_path('filename.wav') +waveform, sample_rate = common_utils.load_wav(filepath) +``` + +*Note: Should you choose to contribute an audio file, please leave a comment in the issue or pull request, mentioning content source and licensing information. WAV files are preferred. Other formats should be used only when there is no alternative. (i.e. dataset implementation comes with hardcoded non-wav extension).* + +#### Pure Tone + +Code: + +```python +waveform = common_utils.get_sinusoid( + frequency=300, + sample_rate=16000, + duration=1, # seconds + n_channels=1, + dtype="float32", + device="cpu", +) +``` + +#### Noise + +Code: + +```python +tensor = common_utils.get_whitenoise() +``` + +Files: + +* `steam-train-whistle-daniel_simon.wav` + +#### Voice + +Files: + +* `CommonVoice/cv-corpus-4-2019-12-10/tt/clips/common_voice_tt_00000000.wav` +* `VCTK-Corpus/wav48/p224/p224_002.wav` +* `vad-go-stereo-44100.wav` +* `vad-go-mono-32000.wav` + +## Adding test + +The following is the current practice of torchaudio test suite. + +1. Unless the tests are related to I/O, use synthetic data. [`common_utils`](./common_utils) has some data generator functions. +1. When you add a new test case, use `common_utils.TorchaudioTestCase` as base class unless you are writing tests that are common to CPU / CUDA. + - Set class memeber `dtype`, `device` and `backend` for the desired behavior. + - If you do not set `backend` value in your test suite, then I/O functions will be unassigned and attempt to load/save file will fail. + - For `backend` value, in addition to available backends, you can also provide the value "default" and backend will be picked automatically based on availability. +1. If you are writing tests that should pass on diffrent dtype/devices, write a common class inheriting `common_utils.TestBaseMixin`, then inherit `common_utils.PytorchTestCase` and define class attributes (`dtype` / `device` / `backend`) there. See [Torchscript consistency test implementation](./torchscript_consistency_impl.py) and test definitions for [CPU](./torchscript_consistency_cpu_test.py) and [CUDA](./torchscript_consistency_cuda_test.py) devices. +1. For numerically comparing Tensors, use `assertEqual` method from torchaudio_unittest.common_utils.PytorchTestCase` class. This method has a better support for a wide variety of Tensor types. + +When you add a new feature(functional/transform), consider the following + +1. When you add a new feature, please make it Torchscript-able and batch-consistent unless it degrades the performance. Please add the tests to see if the new feature meet these requirements. +1. If the feature should be numerical compatible against existing software (SoX, Librosa, Kaldi etc), add a corresponding test. +1. If the new feature is unique to `torchaudio` (not a PyTorch implementation of an existing Software functionality), consider adding correctness tests (wheather the expected output is produced for the set of input) under the corresponding test module (`test_functional.py`, `test_transforms.py`). diff --git a/test/torchaudio_unittest/datasets/vctk_test.py b/test/torchaudio_unittest/datasets/vctk_test.py new file mode 100644 index 0000000000..26b14f5d04 --- /dev/null +++ b/test/torchaudio_unittest/datasets/vctk_test.py @@ -0,0 +1,91 @@ +import os + +from torchaudio.datasets import vctk + +from torchaudio_unittest.common_utils import ( + TempDirMixin, + TorchaudioTestCase, + get_whitenoise, + save_wav, + normalize_wav, +) + +# Used to generate a unique utterance for each dummy audio file +UTTERANCE = [ + 'Please call Stella', + 'Ask her to bring these things', + 'with her from the store', + 'Six spoons of fresh snow peas, five thick slabs of blue cheese, and maybe a snack for her brother Bob', + 'We also need a small plastic snake and a big toy frog for the kids', + 'She can scoop these things into three red bags, and we will go meet her Wednesday at the train station', + 'When the sunlight strikes raindrops in the air, they act as a prism and form a rainbow', + 'The rainbow is a division of white light into many beautiful colors', + 'These take the shape of a long round arch, with its path high above, and its two ends \ + apparently beyond the horizon', + 'There is, according to legend, a boiling pot of gold at one end' +] + + +class TestVCTK(TempDirMixin, TorchaudioTestCase): + backend = 'default' + + root_dir = None + samples = [] + + @classmethod + def setUpClass(cls): + cls.root_dir = cls.get_base_temp_dir() + dataset_dir = os.path.join(cls.root_dir, 'VCTK-Corpus-0.92') + os.makedirs(dataset_dir, exist_ok=True) + sample_rate = 48000 + seed = 0 + + for speaker in range(225, 230): + speaker_id = 'p' + str(speaker) + audio_dir = os.path.join(dataset_dir, 'wav48_silence_trimmed', speaker_id) + os.makedirs(audio_dir, exist_ok=True) + + file_dir = os.path.join(dataset_dir, 'txt', speaker_id) + os.makedirs(file_dir, exist_ok=True) + + for utterance_id in range(1, 11): + filename = f'{speaker_id}_{utterance_id:03d}_mic2' + audio_file_path = os.path.join(audio_dir, filename + '.wav') + + data = get_whitenoise( + sample_rate=sample_rate, + duration=0.01, + n_channels=1, + dtype='float32', + seed=seed + ) + save_wav(audio_file_path, data, sample_rate) + + txt_file_path = os.path.join(file_dir, filename[:-5] + '.txt') + utterance = UTTERANCE[utterance_id - 1] + with open(txt_file_path, 'w') as f: + f.write(utterance) + + sample = ( + normalize_wav(data), + sample_rate, + utterance, + speaker_id, + utterance_id + ) + cls.samples.append(sample) + + seed += 1 + + def test_vctk(self): + dataset = vctk.VCTK_092(self.root_dir, audio_ext=".wav") + num_samples = 0 + for i, (data, sample_rate, utterance, speaker_id, utterance_id) in enumerate(dataset): + self.assertEqual(data, self.samples[i][0], atol=5e-5, rtol=1e-8) + assert sample_rate == self.samples[i][1] + assert utterance == self.samples[i][2] + assert speaker_id == self.samples[i][3] + assert int(utterance_id) == self.samples[i][4] + num_samples += 1 + + assert num_samples == len(self.samples) diff --git a/test/torchaudio_unittest/sox_io_backend/info_test.py b/test/torchaudio_unittest/sox_io_backend/info_test.py index f07b72e112..b16203cfd3 100644 --- a/test/torchaudio_unittest/sox_io_backend/info_test.py +++ b/test/torchaudio_unittest/sox_io_backend/info_test.py @@ -108,6 +108,20 @@ def test_vorbis(self, sample_rate, num_channels, quality_level): assert info.num_frames == sample_rate * duration assert info.num_channels == num_channels + @parameterized.expand(list(itertools.product( + [8000, 16000], + [1, 2], + )), name_func=name_func) + def test_sphere(self, sample_rate, num_channels): + """`sox_io_backend.info` can check sph file correctly""" + duration = 1 + path = self.get_temp_path('data.sph') + sox_utils.gen_audio_file(path, sample_rate, num_channels, duration=duration) + info = sox_io_backend.info(path) + assert info.sample_rate == sample_rate + assert info.num_frames == sample_rate * duration + assert info.num_channels == num_channels + @skipIfNoExtension class TestInfoOpus(PytorchTestCase): diff --git a/test/torchaudio_unittest/sox_io_backend/load_test.py b/test/torchaudio_unittest/sox_io_backend/load_test.py index 1ff8b76dc5..59bcaea386 100644 --- a/test/torchaudio_unittest/sox_io_backend/load_test.py +++ b/test/torchaudio_unittest/sox_io_backend/load_test.py @@ -120,6 +120,28 @@ def assert_vorbis(self, sample_rate, num_channels, quality_level, duration): assert sr == sample_rate self.assertEqual(data, data_ref, atol=4e-05, rtol=1.3e-06) + def assert_sphere(self, sample_rate, num_channels, duration): + """`sox_io_backend.load` can load sph format. + + This test takes the same strategy as mp3 to compare the result + """ + path = self.get_temp_path('1.original.sph') + ref_path = self.get_temp_path('2.reference.wav') + + # 1. Generate sph with sox + sox_utils.gen_audio_file( + path, sample_rate, num_channels, + bit_depth=32, duration=duration) + # 2. Convert to wav with sox + sox_utils.convert_audio_file(path, ref_path) + # 3. Load sph with torchaudio + data, sr = sox_io_backend.load(path) + # 4. Load wav with scipy + data_ref = load_wav(ref_path)[0] + # 5. Compare + assert sr == sample_rate + self.assertEqual(data, data_ref, atol=4e-05, rtol=1.3e-06) + @skipIfNoExec('sox') @skipIfNoExtension @@ -230,6 +252,14 @@ def test_opus(self, bitrate, num_channels, compression_level): assert sample_rate == sr self.assertEqual(expected, found) + @parameterized.expand(list(itertools.product( + [8000, 16000], + [1, 2], + )), name_func=name_func) + def test_sphere(self, sample_rate, num_channels): + """`sox_io_backend.load` can load sph format correctly.""" + self.assert_sphere(sample_rate, num_channels, duration=1) + @skipIfNoExec('sox') @skipIfNoExtension diff --git a/test/torchaudio_unittest/sox_io_backend/save_test.py b/test/torchaudio_unittest/sox_io_backend/save_test.py index 8e416b7aa9..f7d4da3931 100644 --- a/test/torchaudio_unittest/sox_io_backend/save_test.py +++ b/test/torchaudio_unittest/sox_io_backend/save_test.py @@ -168,6 +168,38 @@ def assert_vorbis(self, *args, **kwargs): else: raise error + def assert_sphere(self, sample_rate, num_channels, duration): + """`sox_io_backend.save` can save sph format. + + This test takes the same strategy as mp3 to compare the result + """ + src_path = self.get_temp_path('1.reference.wav') + flc_path = self.get_temp_path('2.1.torchaudio.sph') + wav_path = self.get_temp_path('2.2.torchaudio.wav') + flc_path_sox = self.get_temp_path('3.1.sox.sph') + wav_path_sox = self.get_temp_path('3.2.sox.wav') + + # 1. Generate original wav + data = get_wav_data('float32', num_channels, normalize=True, num_frames=duration * sample_rate) + save_wav(src_path, data, sample_rate) + # 2.1. Convert the original wav to sph with torchaudio + sox_io_backend.save(flc_path, load_wav(src_path)[0], sample_rate) + # 2.2. Convert the sph to wav with Sox + # converting to 32 bit because sph file has 24 bit depth which scipy cannot handle. + sox_utils.convert_audio_file(flc_path, wav_path, bit_depth=32) + # 2.3. Load + found = load_wav(wav_path)[0] + + # 3.1. Convert the original wav to sph with SoX + sox_utils.convert_audio_file(src_path, flc_path_sox) + # 3.2. Convert the sph to wav with Sox + # converting to 32 bit because sph file has 24 bit depth which scipy cannot handle. + sox_utils.convert_audio_file(flc_path_sox, wav_path_sox, bit_depth=32) + # 3.3. Load + expected = load_wav(wav_path_sox)[0] + + self.assertEqual(found, expected) + @skipIfNoExec('sox') @skipIfNoExtension @@ -262,6 +294,14 @@ def test_vorbis_large(self, sample_rate, num_channels, quality_level): self.assert_vorbis(sample_rate, num_channels, quality_level, two_hours) ''' + @parameterized.expand(list(itertools.product( + [8000, 16000], + [1, 2], + )), name_func=name_func) + def test_sphere(self, sample_rate, num_channels): + """`sox_io_backend.save` can save sph format.""" + self.assert_sphere(sample_rate, num_channels, duration=1) + @skipIfNoExec('sox') @skipIfNoExtension diff --git a/test/torchaudio_unittest/torchscript_consistency_impl.py b/test/torchaudio_unittest/torchscript_consistency_impl.py index 8d14e538fd..82c6a300a6 100644 --- a/test/torchaudio_unittest/torchscript_consistency_impl.py +++ b/test/torchaudio_unittest/torchscript_consistency_impl.py @@ -194,6 +194,13 @@ def func(tensor): tensor = common_utils.get_whitenoise(n_channels=2) self._assert_consistency(func, tensor, shape_only=True) + def test_dither_noise_shaping(self): + def func(tensor): + return F.dither(tensor, noise_shaping=True) + + tensor = common_utils.get_whitenoise(n_channels=2) + self._assert_consistency(func, tensor) + def test_lfilter(self): if self.dtype == torch.float64: raise unittest.SkipTest("This test is known to fail for float64") diff --git a/test/torchscript_bc_test/README.md b/test/torchscript_bc_test/README.md new file mode 100644 index 0000000000..4cf0e2b226 --- /dev/null +++ b/test/torchscript_bc_test/README.md @@ -0,0 +1,23 @@ +# Torchscript Backward Compatibility Test Suite + +This directory contains tools to generate Torchscript object of a specific torchaudio version (given that you have the corresponding environments setup correctly) and validate it in the current version. + +## Usage + +### Generate torchscript object + +``` +./main.py --mode generate --version 0.6.0 +``` + +will generate Torchscript dump files in [`assets`](./assets/) directory. This requries your Python runtime to have torchaudio `0.6.0`. + + +### Validate torchscript object + + +``` +./main.py --mode validate --version 0.6.0 +``` + +will validate if the Torchscript files created in the previous step are compatible with the version of torchaudio available in your environment (master). diff --git a/test/torchscript_bc_test/main.py b/test/torchscript_bc_test/main.py new file mode 100755 index 0000000000..3c1c8d974e --- /dev/null +++ b/test/torchscript_bc_test/main.py @@ -0,0 +1,71 @@ +#!/usr/bin/env python3 +"""Generate torchscript object of specific torhcaudio version. + +This requires that the corresponding torchaudio (and torch) is installed. +""" +import os +import sys +import argparse + + +_BASE_OBJ_DIR = os.path.join(os.path.dirname(os.path.abspath(__file__)), 'assets') + + +def _parse_args(): + parser = argparse.ArgumentParser( + description=__doc__ + ) + parser.add_argument( + '--mode', choices=['generate', 'validate'], required=True, + help=( + '"generate" generates Torchscript objects of the specific torchaudio ' + 'in the given directory. ' + '"validate" validates if the objects in the givcen directory are compatible ' + 'with the current torhcaudio.' + ) + ) + parser.add_argument( + '--version', choices=['0.6.0'], required=True, + help='torchaudio version.' + ) + parser.add_argument( + '--base-obj-dir', default=_BASE_OBJ_DIR, + help='Directory where objects are saved/loaded.' + ) + return parser.parse_args() + + +def _generate(version, output_dir): + if version == '0.6.0': + import ver_060 + ver_060.generate(output_dir) + else: + raise ValueError(f'Unexpected torchaudio version: {version}') + + +def _validate(version, input_dir): + if version == '0.6.0': + import ver_060 + ver_060.validate(input_dir) + else: + raise ValueError(f'Unexpected torchaudio version: {version}') + + +def _get_obj_dir(base_dir, version): + py_version = f'{sys.version_info.major}.{sys.version_info.minor}' + return os.path.join(base_dir, f'{version}-py{py_version}') + + +def _main(): + args = _parse_args() + obj_dir = _get_obj_dir(args.base_obj_dir, args.version) + if args.mode == 'generate': + _generate(args.version, obj_dir) + elif args.mode == 'validate': + _validate(args.version, obj_dir) + else: + raise ValueError(f'Unexpected mode: {args.mode}') + + +if __name__ == '__main__': + _main() diff --git a/test/torchscript_bc_test/ver_060.py b/test/torchscript_bc_test/ver_060.py new file mode 100644 index 0000000000..78b8da228c --- /dev/null +++ b/test/torchscript_bc_test/ver_060.py @@ -0,0 +1,71 @@ +import os +import tempfile +from typing import Optional +from packaging import version + +import torch +import torchaudio + +_MIN_VER = version.parse('0.6.0a0') +_MAX_VER = version.parse('0.7.0') +_RUNTIME_VER = version.parse(torchaudio.__version__) + + +def info(filepath: str) -> torchaudio.backend.sox_io_backend.AudioMetaData: + return torchaudio.info(filepath) + + +def load( + filepath: str, + frame_offset: int, + num_frames: int, + normalize: bool, + channels_first: bool): + return torchaudio.load(filepath, frame_offset, num_frames, normalize, channels_first) + + +def save( + filepath: str, + tensor: torch.Tensor, + sample_rate: int, + channels_first: bool = True, + compression: Optional[float] = None, +): + torchaudio.save(filepath, tensor, sample_rate, channels_first, compression) + + +def generate(output_dir): + if not (_MIN_VER <= _RUNTIME_VER < _MAX_VER): + raise RuntimeError(f'Invalid torchaudio runtime version: {_RUNTIME_VER}') + + torchaudio.set_audio_backend('sox_io') + + funcs = [ + info, + load, + save, + ] + + os.makedirs(output_dir, exist_ok=True) + for func in funcs: + torch.jit.script(func).save(os.path.join(output_dir, f'{func.__name__}.zip')) + + +def validate(input_dir): + torchaudio.set_audio_backend('sox_io') + + # See https://github.com/pytorch/pytorch/issues/42258 + # info_ = torch.jit.load(os.path.join(input_dir, 'info.zip')) + load_ = torch.jit.load(os.path.join(input_dir, 'load.zip')) + save_ = torch.jit.load(os.path.join(input_dir, 'save.zip')) + + sample_rate = 44100 + normalize = True + channels_first = True + with tempfile.TemporaryDirectory() as temp_dir: + temp_file = os.path.join(temp_dir, 'test.wav') + temp_data = torch.rand(2, sample_rate, dtype=torch.float32) + + save_(temp_file, temp_data, sample_rate, channels_first, 0.) + # info_(temp_file) + load_(temp_file, 0, -1, normalize, channels_first) diff --git a/torchaudio/backend/sox_io_backend.py b/torchaudio/backend/sox_io_backend.py index 57d8db7723..9c0695d723 100644 --- a/torchaudio/backend/sox_io_backend.py +++ b/torchaudio/backend/sox_io_backend.py @@ -58,6 +58,7 @@ def load( * FLAC * OGG/VORBIS * OPUS + * SPHERE To load ``MP3``, ``FLAC``, ``OGG/VORBIS``, ``OPUS`` and other codecs ``libsox`` does not handle natively, your installation of ``torchaudio`` has to be linked to ``libsox`` @@ -132,6 +133,7 @@ def save( * MP3 * FLAC * OGG/VORBIS + * SPHERE To save ``MP3``, ``FLAC``, ``OGG/VORBIS``, and other codecs ``libsox`` does not handle natively, your installation of ``torchaudio`` has to be linked to ``libsox`` @@ -158,7 +160,7 @@ def save( """ if compression is None: ext = str(filepath)[-3:].lower() - if ext == 'wav': + if ext in ['wav', 'sph']: compression = 0. elif ext == 'mp3': compression = -4.5 diff --git a/torchaudio/csrc/register.cpp b/torchaudio/csrc/register.cpp index 476dcc3ebb..a1ec8f2254 100644 --- a/torchaudio/csrc/register.cpp +++ b/torchaudio/csrc/register.cpp @@ -5,86 +5,70 @@ #include #include -namespace torchaudio { -namespace { +TORCH_LIBRARY(torchaudio, m) { + ////////////////////////////////////////////////////////////////////////////// + // sox_utils.h + ////////////////////////////////////////////////////////////////////////////// + m.class_("TensorSignal") + .def(torch::init()) + .def("get_tensor", &torchaudio::sox_utils::TensorSignal::getTensor) + .def( + "get_sample_rate", + &torchaudio::sox_utils::TensorSignal::getSampleRate) + .def( + "get_channels_first", + &torchaudio::sox_utils::TensorSignal::getChannelsFirst); -//////////////////////////////////////////////////////////////////////////////// -// sox_utils.h -//////////////////////////////////////////////////////////////////////////////// -static auto registerTensorSignal = - torch::class_("torchaudio", "TensorSignal") - .def(torch::init()) - .def("get_tensor", &sox_utils::TensorSignal::getTensor) - .def("get_sample_rate", &sox_utils::TensorSignal::getSampleRate) - .def("get_channels_first", &sox_utils::TensorSignal::getChannelsFirst); + m.def("torchaudio::sox_utils_set_seed", &torchaudio::sox_utils::set_seed); + m.def( + "torchaudio::sox_utils_set_verbosity", + &torchaudio::sox_utils::set_verbosity); + m.def( + "torchaudio::sox_utils_set_use_threads", + &torchaudio::sox_utils::set_use_threads); + m.def( + "torchaudio::sox_utils_set_buffer_size", + &torchaudio::sox_utils::set_buffer_size); + m.def( + "torchaudio::sox_utils_list_effects", + &torchaudio::sox_utils::list_effects); + m.def( + "torchaudio::sox_utils_list_read_formats", + &torchaudio::sox_utils::list_read_formats); + m.def( + "torchaudio::sox_utils_list_write_formats", + &torchaudio::sox_utils::list_write_formats); -static auto registerSetSoxOptions = - torch::RegisterOperators() - .op("torchaudio::sox_utils_set_seed", &sox_utils::set_seed) - .op("torchaudio::sox_utils_set_verbosity", &sox_utils::set_verbosity) - .op("torchaudio::sox_utils_set_use_threads", - &sox_utils::set_use_threads) - .op("torchaudio::sox_utils_set_buffer_size", - &sox_utils::set_buffer_size) - .op("torchaudio::sox_utils_list_effects", &sox_utils::list_effects) - .op("torchaudio::sox_utils_list_read_formats", - &sox_utils::list_read_formats) - .op("torchaudio::sox_utils_list_write_formats", - &sox_utils::list_write_formats); + ////////////////////////////////////////////////////////////////////////////// + // sox_io.h + ////////////////////////////////////////////////////////////////////////////// + m.class_("SignalInfo") + .def("get_sample_rate", &torchaudio::sox_io::SignalInfo::getSampleRate) + .def("get_num_channels", &torchaudio::sox_io::SignalInfo::getNumChannels) + .def("get_num_frames", &torchaudio::sox_io::SignalInfo::getNumFrames); -//////////////////////////////////////////////////////////////////////////////// -// sox_io.h -//////////////////////////////////////////////////////////////////////////////// -static auto registerSignalInfo = - torch::class_("torchaudio", "SignalInfo") - .def("get_sample_rate", &sox_io::SignalInfo::getSampleRate) - .def("get_num_channels", &sox_io::SignalInfo::getNumChannels) - .def("get_num_frames", &sox_io::SignalInfo::getNumFrames); + m.def("torchaudio::sox_io_get_info", &torchaudio::sox_io::get_info); + m.def( + "torchaudio::sox_io_load_audio_file", + &torchaudio::sox_io::load_audio_file); + m.def( + "torchaudio::sox_io_save_audio_file", + &torchaudio::sox_io::save_audio_file); -static auto registerGetInfo = torch::RegisterOperators().op( - torch::RegisterOperators::options() - .schema( - "torchaudio::sox_io_get_info(str path) -> __torch__.torch.classes.torchaudio.SignalInfo info") - .catchAllKernel()); - -static auto registerLoadAudioFile = torch::RegisterOperators().op( - torch::RegisterOperators::options() - .schema( - "torchaudio::sox_io_load_audio_file(str path, int frame_offset, int num_frames, bool normalize, bool channels_first) -> __torch__.torch.classes.torchaudio.TensorSignal signal") - .catchAllKernel< - decltype(sox_io::load_audio_file), - &sox_io::load_audio_file>()); - -static auto registerSaveAudioFile = torch::RegisterOperators().op( - torch::RegisterOperators::options() - .schema( - "torchaudio::sox_io_save_audio_file(str path, __torch__.torch.classes.torchaudio.TensorSignal signal, float compression) -> ()") - .catchAllKernel< - decltype(sox_io::save_audio_file), - &sox_io::save_audio_file>()); - -//////////////////////////////////////////////////////////////////////////////// -// sox_effects.h -//////////////////////////////////////////////////////////////////////////////// -static auto registerSoxEffects = - torch::RegisterOperators() - .op("torchaudio::sox_effects_initialize_sox_effects", - &sox_effects::initialize_sox_effects) - .op("torchaudio::sox_effects_shutdown_sox_effects", - &sox_effects::shutdown_sox_effects) - .op(torch::RegisterOperators::options() - .schema( - "torchaudio::sox_effects_apply_effects_tensor(__torch__.torch.classes.torchaudio.TensorSignal input_signal, str[][] effects) -> __torch__.torch.classes.torchaudio.TensorSignal output_signal") - .catchAllKernel< - decltype(sox_effects::apply_effects_tensor), - &sox_effects::apply_effects_tensor>()) - .op(torch::RegisterOperators::options() - .schema( - "torchaudio::sox_effects_apply_effects_file(str path, str[][] effects, bool normalize, bool channels_first) -> __torch__.torch.classes.torchaudio.TensorSignal output_signal") - .catchAllKernel< - decltype(sox_effects::apply_effects_file), - &sox_effects::apply_effects_file>()); - -} // namespace -} // namespace torchaudio + ////////////////////////////////////////////////////////////////////////////// + // sox_effects.h + ////////////////////////////////////////////////////////////////////////////// + m.def( + "torchaudio::sox_effects_initialize_sox_effects", + &torchaudio::sox_effects::initialize_sox_effects); + m.def( + "torchaudio::sox_effects_shutdown_sox_effects", + &torchaudio::sox_effects::shutdown_sox_effects); + m.def( + "torchaudio::sox_effects_apply_effects_tensor", + &torchaudio::sox_effects::apply_effects_tensor); + m.def( + "torchaudio::sox_effects_apply_effects_file", + &torchaudio::sox_effects::apply_effects_file); +} #endif diff --git a/torchaudio/csrc/sox_utils.cpp b/torchaudio/csrc/sox_utils.cpp index c6b73c5795..25fe376c8b 100644 --- a/torchaudio/csrc/sox_utils.cpp +++ b/torchaudio/csrc/sox_utils.cpp @@ -234,6 +234,8 @@ sox_encoding_t get_encoding( return SOX_ENCODING_FLOAT; throw std::runtime_error("Unsupported dtype."); } + if (filetype == "sph") + return SOX_ENCODING_SIGN2; throw std::runtime_error("Unsupported file type."); } @@ -257,6 +259,8 @@ unsigned get_precision( return 32; throw std::runtime_error("Unsupported dtype."); } + if (filetype == "sph") + return 32; throw std::runtime_error("Unsupported file type."); } @@ -285,6 +289,8 @@ sox_encodinginfo_t get_encodinginfo( return compression; if (filetype == "wav") return 0.; + if (filetype == "sph") + return 0.; throw std::runtime_error("Unsupported file type."); }(); diff --git a/torchaudio/datasets/__init__.py b/torchaudio/datasets/__init__.py index 187142db46..fb9e0db506 100644 --- a/torchaudio/datasets/__init__.py +++ b/torchaudio/datasets/__init__.py @@ -2,7 +2,7 @@ from .librispeech import LIBRISPEECH from .speechcommands import SPEECHCOMMANDS from .utils import bg_iterator, diskcache_iterator -from .vctk import VCTK +from .vctk import VCTK, VCTK_092 from .gtzan import GTZAN from .yesno import YESNO from .ljspeech import LJSPEECH @@ -14,6 +14,7 @@ "LIBRISPEECH", "SPEECHCOMMANDS", "VCTK", + "VCTK_092", "YESNO", "LJSPEECH", "GTZAN", diff --git a/torchaudio/datasets/vctk.py b/torchaudio/datasets/vctk.py index c84373713d..8fa874c7cf 100644 --- a/torchaudio/datasets/vctk.py +++ b/torchaudio/datasets/vctk.py @@ -1,6 +1,7 @@ import os import warnings from typing import Any, Tuple +from collections import namedtuple import torchaudio from torch import Tensor @@ -11,13 +12,16 @@ walk_files ) -URL = "http://homepages.inf.ed.ac.uk/jyamagis/release/VCTK-Corpus.tar.gz" +URL = "https://datashare.is.ed.ac.uk/bitstream/handle/10283/3443/VCTK-Corpus-0.92.zip" FOLDER_IN_ARCHIVE = "VCTK-Corpus" _CHECKSUMS = { - "http://homepages.inf.ed.ac.uk/jyamagis/release/VCTK-Corpus.tar.gz": - "45e8dede780278ef5541fde0b82ac292" + "https://datashare.is.ed.ac.uk/bitstream/handle/10283/3443/VCTK-Corpus-0.92.zip": "8a6ba2946b36fcbef0212cad601f4bfa" } +Sample = namedtuple( + "Sample", ["waveform", "sample_rate", "utterance", "speaker_id", "utterance_id"] +) + def load_vctk_item(fileid: str, path: str, @@ -96,15 +100,15 @@ def __init__(self, self._path = os.path.join(root, folder_in_archive) if download: - if not os.path.isdir(self._path): - if not os.path.isfile(archive): - checksum = _CHECKSUMS.get(url, None) - download_url(url, root, hash_value=checksum, hash_type="md5") - extract_archive(archive) + raise RuntimeError( + "This Dataset is no longer available. " + "Please use `VCTK_092` class to download the latest version." + ) if not os.path.isdir(self._path): raise RuntimeError( - "Dataset not found. Please use `download=True` to download it." + "Dataset not found. Please use `VCTK_092` class " + "with `download=True` to donwload the latest version." ) walker = walk_files( @@ -136,3 +140,120 @@ def __getitem__(self, n: int) -> Tuple[Tensor, int, str, str, str]: def __len__(self) -> int: return len(self._walker) + + +class VCTK_092(Dataset): + """Create VCTK 0.92 Dataset + + An item is a ``namedtuple`` of (``waveform``, ``sample_rate``, ``utterance``, + ``speaker_id``, ``utterance_id``) + + Args: + root (str): Root directory where the dataset's top level directory is found. + mic_id (str): Microphone ID. Either ``"mic1"`` or ``"mic2"`` + download (bool, optional): Download the dataset if not found in the given directory. + url (str, optional): URL from which the dataset is downloaded. + audio_ext (str, optional): Custom audio extension if dataset is converted to non-default audio format. + + Note: + * All the speeches from speaker ``p315`` will be skipped due to the lack of the corresponding text files. + * All the speeches from ``p280`` will be skipped for ``mic_id="mic2"`` due to the lack of the audio files. + * Some of the speeches from speaker ``p362`` will be skipped due to the lack of the audio files. + * See Also: https://datashare.is.ed.ac.uk/handle/10283/3443 + """ + + def __init__( + self, + root: str, + mic_id: str = "mic2", + download: bool = False, + url: str = URL, + audio_ext=".flac", + ): + if mic_id not in ["mic1", "mic2"]: + raise RuntimeError( + f'`mic_id` has to be either "mic1" or "mic2". Found: {mic_id}' + ) + + archive = os.path.join(root, "VCTK-Corpus-0.92.zip") + + self._path = os.path.join(root, "VCTK-Corpus-0.92") + self._txt_dir = os.path.join(self._path, "txt") + self._audio_dir = os.path.join(self._path, "wav48_silence_trimmed") + self._mic_id = mic_id + self._audio_ext = audio_ext + + if download: + if not os.path.isdir(self._path): + if not os.path.isfile(archive): + checksum = _CHECKSUMS.get(url, None) + download_url(url, root, hash_value=checksum, hash_type="md5") + extract_archive(archive, self._path) + + if not os.path.isdir(self._path): + raise RuntimeError( + "Dataset not found. Please use `download=True` to download it." + ) + + # Extracting speaker IDs from the folder structure + self._speaker_ids = sorted(os.listdir(self._txt_dir)) + self._sample_ids = [] + + """ + Due to some insufficient data complexity in the 0.92 version of this dataset, + we start traversing the audio folder structure in accordance with the text folder. + As some of the audio files are missing of either ``mic_1`` or ``mic_2`` but the + text is present for the same, we first check for the existence of the audio file + before adding it to the ``sample_ids`` list. + + Once the ``audio_ids`` are loaded into memory we can quickly access the list for + different parameters required by the user. + """ + for speaker_id in self._speaker_ids: + if speaker_id == "p280" and mic_id == "mic2": + continue + utterance_dir = os.path.join(self._txt_dir, speaker_id) + for utterance_file in sorted( + f for f in os.listdir(utterance_dir) if f.endswith(".txt") + ): + utterance_id = os.path.splitext(utterance_file)[0] + audio_path_mic = os.path.join( + self._audio_dir, + speaker_id, + f"{utterance_id}_{mic_id}{self._audio_ext}", + ) + if speaker_id == "p362" and not os.path.isfile(audio_path_mic): + continue + self._sample_ids.append(utterance_id.split("_")) + + def _load_text(self, file_path) -> str: + with open(file_path) as file_path: + return file_path.readlines()[0] + + def _load_audio(self, file_path) -> Tuple[Tensor, int]: + return torchaudio.load(file_path) + + def _load_sample(self, speaker_id: str, utterance_id: str, mic_id: str) -> Sample: + utterance_path = os.path.join( + self._txt_dir, speaker_id, f"{speaker_id}_{utterance_id}.txt" + ) + audio_path = os.path.join( + self._audio_dir, + speaker_id, + f"{speaker_id}_{utterance_id}_{mic_id}{self._audio_ext}", + ) + + # Reading text + utterance = self._load_text(utterance_path) + + # Reading FLAC + waveform, sample_rate = self._load_audio(audio_path) + + return Sample(waveform, sample_rate, utterance, speaker_id, utterance_id) + + def __getitem__(self, n: int) -> Sample: + speaker_id, utterance_id = self._sample_ids[n] + return self._load_sample(speaker_id, utterance_id, self._mic_id) + + def __len__(self) -> int: + return len(self._sample_ids) diff --git a/torchaudio/functional.py b/torchaudio/functional.py index 4b79c01960..4e8e62848e 100644 --- a/torchaudio/functional.py +++ b/torchaudio/functional.py @@ -1655,9 +1655,10 @@ def _add_noise_shaping( error = dithered_waveform - waveform # add error[n-1] to dithered_waveform[n], so offset the error by 1 index + zeros = torch.zeros(1, dtype=error.dtype, device=error.device) for index in range(error.size()[0]): err = error[index] - error_offset = torch.cat((torch.zeros(1), err)) + error_offset = torch.cat((zeros, err)) error[index] = error_offset[:waveform.size()[1]] noise_shaped = dithered_waveform + error From 7d5591f5b90c3fe70902fede6af157ea92e3206a Mon Sep 17 00:00:00 2001 From: Moto Hira Date: Wed, 23 Sep 2020 08:59:35 -0700 Subject: [PATCH 18/73] Import torchaudio 20200922 Summary: Up to #914 Reviewed By: vincentqb, cpuhrsch Differential Revision: D23846718 fbshipit-source-id: 9feb4e58563b900965467bd9ff66c979211c50df --- .circleci/config.yml | 22 +- .circleci/config.yml.in | 22 +- .../unittest/linux/scripts/environment.yml | 1 + docs/source/datasets.rst | 15 +- examples/interactive_asr/utils.py | 8 +- packaging/pkg_helpers.bash | 2 +- .../datasets/tedlium_test.py | 153 +++++++++++++ .../functional/functional_cpu_test.py | 17 ++ .../sox_io_backend/save_test.py | 4 +- torchaudio/backend/soundfile_backend.py | 1 + torchaudio/backend/sox_backend.py | 1 + torchaudio/backend/sox_io_backend.py | 22 +- torchaudio/backend/utils.py | 5 + torchaudio/datasets/__init__.py | 4 +- torchaudio/datasets/tedlium.py | 208 ++++++++++++++++++ torchaudio/functional.py | 7 + 16 files changed, 454 insertions(+), 38 deletions(-) create mode 100644 test/torchaudio_unittest/datasets/tedlium_test.py create mode 100644 torchaudio/datasets/tedlium.py diff --git a/.circleci/config.yml b/.circleci/config.yml index 70b7c54ef5..b2b0dd45c3 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -144,14 +144,14 @@ jobs: - store_artifacts: path: /opt/conda/conda-bld/linux-64 - persist_to_workspace: - root: /opt/conda/conda-bld/linux-64 + root: /opt/conda paths: - - "*" + - "conda-bld/*" binary_macos_wheel: <<: *binary_common macos: - xcode: "9.0" + xcode: "9.4.1" steps: - checkout - install_build_tools_macos @@ -176,7 +176,7 @@ jobs: binary_macos_conda: <<: *binary_common macos: - xcode: "9.0" + xcode: "9.4.1" steps: - checkout - install_build_tools_macos @@ -192,9 +192,9 @@ jobs: - store_artifacts: path: /Users/distiller/miniconda3/conda-bld/osx-64 - persist_to_workspace: - root: /Users/distiller/miniconda3/conda-bld/osx-64 + root: /Users/distiller/miniconda3 paths: - - "*" + - "conda-bld/*" binary_windows_wheel: <<: *binary_common @@ -231,9 +231,9 @@ jobs: - store_artifacts: path: C:/tools/miniconda3/conda-bld/win-64 - persist_to_workspace: - root: C:/tools/miniconda3/conda-bld/win-64 + root: C:/tools/miniconda3 paths: - - "*" + - "conda-bld/*" # Requires org-member context binary_conda_upload: @@ -248,7 +248,7 @@ jobs: # Prevent credential from leaking conda install -yq anaconda-client set -x - anaconda -t "${CONDA_PYTORCHBOT_TOKEN}" upload ~/workspace/*.tar.bz2 -u "pytorch-${UPLOAD_CHANNEL}" --label main --no-progress --force + anaconda -t "${CONDA_PYTORCHBOT_TOKEN}" upload ~/workspace/conda-bld/*/*.tar.bz2 -u "pytorch-${UPLOAD_CHANNEL}" --label main --no-progress --force # Requires org-member context binary_wheel_upload: @@ -284,7 +284,7 @@ jobs: set -x source /usr/local/etc/profile.d/conda.sh && conda activate python${PYTHON_VERSION} conda install -v -y -c pytorch-${UPLOAD_CHANNEL} pytorch - conda install -v -y $(ls ~/workspace/torchaudio*.tar.bz2) + conda install -v -y -c file://$HOME/workspace/conda-bld torchaudio - run: name: smoke test command: | @@ -537,7 +537,7 @@ jobs: unittest_macos_cpu: <<: *binary_common macos: - xcode: "9.0" + xcode: "9.4.1" resource_class: large steps: - checkout diff --git a/.circleci/config.yml.in b/.circleci/config.yml.in index 94220d02c0..b1f40c24c0 100644 --- a/.circleci/config.yml.in +++ b/.circleci/config.yml.in @@ -144,14 +144,14 @@ jobs: - store_artifacts: path: /opt/conda/conda-bld/linux-64 - persist_to_workspace: - root: /opt/conda/conda-bld/linux-64 + root: /opt/conda paths: - - "*" + - "conda-bld/*" binary_macos_wheel: <<: *binary_common macos: - xcode: "9.0" + xcode: "9.4.1" steps: - checkout - install_build_tools_macos @@ -176,7 +176,7 @@ jobs: binary_macos_conda: <<: *binary_common macos: - xcode: "9.0" + xcode: "9.4.1" steps: - checkout - install_build_tools_macos @@ -192,9 +192,9 @@ jobs: - store_artifacts: path: /Users/distiller/miniconda3/conda-bld/osx-64 - persist_to_workspace: - root: /Users/distiller/miniconda3/conda-bld/osx-64 + root: /Users/distiller/miniconda3 paths: - - "*" + - "conda-bld/*" binary_windows_wheel: <<: *binary_common @@ -231,9 +231,9 @@ jobs: - store_artifacts: path: C:/tools/miniconda3/conda-bld/win-64 - persist_to_workspace: - root: C:/tools/miniconda3/conda-bld/win-64 + root: C:/tools/miniconda3 paths: - - "*" + - "conda-bld/*" # Requires org-member context binary_conda_upload: @@ -248,7 +248,7 @@ jobs: # Prevent credential from leaking conda install -yq anaconda-client set -x - anaconda -t "${CONDA_PYTORCHBOT_TOKEN}" upload ~/workspace/*.tar.bz2 -u "pytorch-${UPLOAD_CHANNEL}" --label main --no-progress --force + anaconda -t "${CONDA_PYTORCHBOT_TOKEN}" upload ~/workspace/conda-bld/*/*.tar.bz2 -u "pytorch-${UPLOAD_CHANNEL}" --label main --no-progress --force # Requires org-member context binary_wheel_upload: @@ -284,7 +284,7 @@ jobs: set -x source /usr/local/etc/profile.d/conda.sh && conda activate python${PYTHON_VERSION} conda install -v -y -c pytorch-${UPLOAD_CHANNEL} pytorch - conda install -v -y $(ls ~/workspace/torchaudio*.tar.bz2) + conda install -v -y -c file://$HOME/workspace/conda-bld torchaudio - run: name: smoke test command: | @@ -537,7 +537,7 @@ jobs: unittest_macos_cpu: <<: *binary_common macos: - xcode: "9.0" + xcode: "9.4.1" resource_class: large steps: - checkout diff --git a/.circleci/unittest/linux/scripts/environment.yml b/.circleci/unittest/linux/scripts/environment.yml index f68fb130a2..42acafb984 100644 --- a/.circleci/unittest/linux/scripts/environment.yml +++ b/.circleci/unittest/linux/scripts/environment.yml @@ -1,3 +1,4 @@ +# a comment for these trying times channels: - conda-forge - defaults diff --git a/docs/source/datasets.rst b/docs/source/datasets.rst index 6cdf44e223..b3f1b3c725 100644 --- a/docs/source/datasets.rst +++ b/docs/source/datasets.rst @@ -4,11 +4,11 @@ torchaudio.datasets All datasets are subclasses of :class:`torch.utils.data.Dataset` i.e, they have ``__getitem__`` and ``__len__`` methods implemented. Hence, they can all be passed to a :class:`torch.utils.data.DataLoader` -which can load multiple samples parallelly using ``torch.multiprocessing`` workers. +which can load multiple samples parallelly using ``torch.multiprocessing`` workers. For example: :: - + yesno_data = torchaudio.datasets.YESNO('.', download=True) - data_loader = torch.utils.data.DataLoader(yesno_data, + data_loader = torch.utils.data.DataLoader(yesno_data, batch_size=1, shuffle=True, num_workers=args.nThreads) @@ -22,7 +22,7 @@ All the datasets have almost similar API. They all have two common arguments: ``transform`` and ``target_transform`` to transform the input and target respectively. -.. currentmodule:: torchaudio.datasets +.. currentmodule:: torchaudio.datasets CMUARCTIC @@ -81,6 +81,13 @@ SPEECHCOMMANDS :special-members: +TEDLIUM +~~~~~~~~~~~~~~ + +.. autoclass:: TEDLIUM + :members: __getitem__ + :special-members: get_phoneme_dict + VCTK ~~~~ diff --git a/examples/interactive_asr/utils.py b/examples/interactive_asr/utils.py index 713954029a..37f5ae5303 100644 --- a/examples/interactive_asr/utils.py +++ b/examples/interactive_asr/utils.py @@ -55,8 +55,9 @@ def check_args(args): def process_predictions(args, hypos, sp, tgt_dict): res = [] + device = torch.device("cuda:0" if torch.cuda.is_available() and not args.cpu else "cpu") for hypo in hypos[: min(len(hypos), args.nbest)]: - hyp_pieces = tgt_dict.string(hypo["tokens"].int().cpu()) + hyp_pieces = tgt_dict.string(hypo["tokens"].int().to(device)) hyp_words = sp.DecodePieces(hyp_pieces.split()) res.append(hyp_words) return res @@ -96,7 +97,8 @@ def calcMN(features): def transcribe(waveform, args, task, generator, models, sp, tgt_dict): num_features = 80 output = torchaudio.compliance.kaldi.fbank(waveform, num_mel_bins=num_features) - output_cmvn = calcMN(output.cpu().detach()) + device = torch.device("cuda:0" if torch.cuda.is_available() and not args.cpu else "cpu") + output_cmvn = calcMN(output.to(device).detach()) # size (m, n) source = output_cmvn @@ -151,7 +153,7 @@ def setup_asr(args, logger): optimize_models(args, use_cuda, models) # Initialize generator - generator = task.build_generator(args) + generator = task.build_generator(models, args) sp = spm.SentencePieceProcessor() sp.Load(os.path.join(args.data, "spm.model")) diff --git a/packaging/pkg_helpers.bash b/packaging/pkg_helpers.bash index 3ec49a0269..57b23b93d3 100644 --- a/packaging/pkg_helpers.bash +++ b/packaging/pkg_helpers.bash @@ -32,7 +32,7 @@ setup_cuda() { # First, compute version suffixes. By default, assume no version suffixes export VERSION_SUFFIX="" export PYTORCH_VERSION_SUFFIX="" - export WHEEL_DIR="" + export WHEEL_DIR="cpu/" # Wheel builds need suffixes (but not if they're on OS X, which never has suffix) if [[ "$BUILD_TYPE" == "wheel" ]] && [[ "$(uname)" != Darwin ]]; then # The default CUDA has no suffix diff --git a/test/torchaudio_unittest/datasets/tedlium_test.py b/test/torchaudio_unittest/datasets/tedlium_test.py new file mode 100644 index 0000000000..c19984cac2 --- /dev/null +++ b/test/torchaudio_unittest/datasets/tedlium_test.py @@ -0,0 +1,153 @@ +import os + +from torchaudio.datasets import tedlium + +from torchaudio_unittest.common_utils import ( + TempDirMixin, + TorchaudioTestCase, + get_whitenoise, + save_wav, + normalize_wav, +) + +# Used to generate a unique utterance for each dummy audio file +UTTERANCES = [ + "AaronHuey_2010X 1 AaronHuey_2010X 0.0 2.0 script1\n", + "AaronHuey_2010X 1 AaronHuey_2010X 2.0 4.0 script2\n", + "AaronHuey_2010X 1 AaronHuey_2010X 4.0 6.0 script3\n", + "AaronHuey_2010X 1 AaronHuey_2010X 6.0 8.0 script4\n", + "AaronHuey_2010X 1 AaronHuey_2010X 8.0 10.0 script5\n", +] + +PHONEME = [ + "a AH", + "a(2) EY", + "aachen AA K AH N", + "aad AE D", + "aaden EY D AH N", + "aadmi AE D M IY", + "aae EY EY", +] + + +class TestTedlium(TempDirMixin, TorchaudioTestCase): + backend = "default" + + root_dir = None + samples = {} + + @classmethod + def setUpClass(cls): + cls.root_dir = cls.get_base_temp_dir() + cls.root_dir = dataset_dir = os.path.join(cls.root_dir, "tedlium") + os.makedirs(dataset_dir, exist_ok=True) + sample_rate = 16000 # 16kHz + seed = 0 + + for release in ["release1", "release2", "release3"]: + data = get_whitenoise(sample_rate=sample_rate, duration=10.00, n_channels=1, dtype="float32", seed=seed) + if release in ["release1", "release2"]: + release_dir = os.path.join( + dataset_dir, + tedlium._RELEASE_CONFIGS[release]["folder_in_archive"], + tedlium._RELEASE_CONFIGS[release]["subset"], + ) + else: + release_dir = os.path.join( + dataset_dir, + tedlium._RELEASE_CONFIGS[release]["folder_in_archive"], + tedlium._RELEASE_CONFIGS[release]["data_path"], + ) + os.makedirs(release_dir, exist_ok=True) + os.makedirs(os.path.join(release_dir, "stm"), exist_ok=True) # Subfolder for transcripts + os.makedirs(os.path.join(release_dir, "sph"), exist_ok=True) # Subfolder for audio files + filename = f"{release}.sph" + path = os.path.join(os.path.join(release_dir, "sph"), filename) + save_wav(path, data, sample_rate) + + trans_filename = f"{release}.stm" + trans_path = os.path.join(os.path.join(release_dir, "stm"), trans_filename) + with open(trans_path, "w") as f: + f.write("".join(UTTERANCES)) + + dict_filename = f"{release}.dic" + dict_path = os.path.join(release_dir, dict_filename) + with open(dict_path, "w") as f: + f.write("\n".join(PHONEME)) + + # Create a samples list to compare with + cls.samples[release] = [] + for utterance in UTTERANCES: + talk_id, _, speaker_id, start_time, end_time, identifier, transcript = utterance.split(" ", 6) + start_time = int(float(start_time)) * sample_rate + end_time = int(float(end_time)) * sample_rate + sample = ( + data[:, start_time:end_time], + sample_rate, + transcript, + talk_id, + speaker_id, + identifier, + ) + cls.samples[release].append(sample) + seed += 1 + + def test_tedlium_release1(self): + release = "release1" + dataset = tedlium.TEDLIUM(self.root_dir, release=release) + num_samples = 0 + for i, (data, sample_rate, transcript, talk_id, speaker_id, identifier) in enumerate(dataset): + self.assertEqual(data, self.samples[release][i][0], atol=5e-5, rtol=1e-8) + assert sample_rate == self.samples[release][i][1] + assert transcript == self.samples[release][i][2] + assert talk_id == self.samples[release][i][3] + assert speaker_id == self.samples[release][i][4] + assert identifier == self.samples[release][i][5] + num_samples += 1 + + assert num_samples == len(self.samples[release]) + + dataset._dict_path = os.path.join(dataset._path, f"{release}.dic") + phoneme_dict = dataset.phoneme_dict + phoenemes = [f"{key} {' '.join(value)}" for key, value in phoneme_dict.items()] + assert phoenemes == PHONEME + + def test_tedlium_release2(self): + release = "release2" + dataset = tedlium.TEDLIUM(self.root_dir, release=release) + num_samples = 0 + for i, (data, sample_rate, transcript, talk_id, speaker_id, identifier) in enumerate(dataset): + self.assertEqual(data, self.samples[release][i][0], atol=5e-5, rtol=1e-8) + assert sample_rate == self.samples[release][i][1] + assert transcript == self.samples[release][i][2] + assert talk_id == self.samples[release][i][3] + assert speaker_id == self.samples[release][i][4] + assert identifier == self.samples[release][i][5] + num_samples += 1 + + assert num_samples == len(self.samples[release]) + + dataset._dict_path = os.path.join(dataset._path, f"{release}.dic") + phoneme_dict = dataset.phoneme_dict + phoenemes = [f"{key} {' '.join(value)}" for key, value in phoneme_dict.items()] + assert phoenemes == PHONEME + + def test_tedlium_release3(self): + release = "release3" + dataset = tedlium.TEDLIUM(self.root_dir, release=release) + num_samples = 0 + for i, (data, sample_rate, transcript, talk_id, speaker_id, identifier) in enumerate(dataset): + self.assertEqual(data, self.samples[release][i][0], atol=5e-5, rtol=1e-8) + assert sample_rate == self.samples[release][i][1] + assert transcript == self.samples[release][i][2] + assert talk_id == self.samples[release][i][3] + assert speaker_id == self.samples[release][i][4] + assert identifier == self.samples[release][i][5] + num_samples += 1 + + assert num_samples == len(self.samples[release]) + + dataset._dict_path = os.path.join(dataset._path, f"{release}.dic") + phoneme_dict = dataset.phoneme_dict + phoenemes = [f"{key} {' '.join(value)}" for key, value in phoneme_dict.items()] + assert phoenemes == PHONEME diff --git a/test/torchaudio_unittest/functional/functional_cpu_test.py b/test/torchaudio_unittest/functional/functional_cpu_test.py index 96aac4e770..4fbe4d871e 100644 --- a/test/torchaudio_unittest/functional/functional_cpu_test.py +++ b/test/torchaudio_unittest/functional/functional_cpu_test.py @@ -21,6 +21,23 @@ class TestLFilterFloat64(Lfilter, common_utils.PytorchTestCase): device = torch.device('cpu') +class TestCreateFBMatrix(common_utils.TorchaudioTestCase): + def test_no_warning_high_n_freq(self): + with pytest.warns(None) as w: + F.create_fb_matrix(288, 0, 8000, 128, 16000) + assert len(w) == 0 + + def test_no_warning_low_n_mels(self): + with pytest.warns(None) as w: + F.create_fb_matrix(201, 0, 8000, 89, 16000) + assert len(w) == 0 + + def test_warning(self): + with pytest.warns(None) as w: + F.create_fb_matrix(201, 0, 8000, 128, 16000) + assert len(w) == 1 + + class TestComputeDeltas(common_utils.TorchaudioTestCase): """Test suite for correctness of compute_deltas""" def test_one_channel(self): diff --git a/test/torchaudio_unittest/sox_io_backend/save_test.py b/test/torchaudio_unittest/sox_io_backend/save_test.py index f7d4da3931..deed1aa1ad 100644 --- a/test/torchaudio_unittest/sox_io_backend/save_test.py +++ b/test/torchaudio_unittest/sox_io_backend/save_test.py @@ -254,7 +254,7 @@ def test_mp3_large(self, sample_rate, num_channels, bit_rate): @parameterized.expand(list(itertools.product( [8000, 16000], [1, 2], - list(range(9)), + [None] + list(range(9)), )), name_func=name_func) def test_flac(self, sample_rate, num_channels, compression_level): """`sox_io_backend.save` can save flac format.""" @@ -273,7 +273,7 @@ def test_flac_large(self, sample_rate, num_channels, compression_level): @parameterized.expand(list(itertools.product( [8000, 16000], [1, 2], - [-1, 0, 1, 2, 3, 3.6, 5, 10], + [None, -1, 0, 1, 2, 3, 3.6, 5, 10], )), name_func=name_func) def test_vorbis(self, sample_rate, num_channels, quality_level): """`sox_io_backend.save` can save vorbis format.""" diff --git a/torchaudio/backend/soundfile_backend.py b/torchaudio/backend/soundfile_backend.py index 680264bcd6..49cada21b0 100644 --- a/torchaudio/backend/soundfile_backend.py +++ b/torchaudio/backend/soundfile_backend.py @@ -73,6 +73,7 @@ def load(filepath: str, @_mod_utils.requires_module('soundfile') +@_mod_utils.deprecated('Please use "torchaudio.load".', '0.9.0') @common._impl_load_wav def load_wav(filepath, **kwargs): kwargs['normalization'] = 1 << 16 diff --git a/torchaudio/backend/sox_backend.py b/torchaudio/backend/sox_backend.py index 4e2b118f8b..45d75817af 100644 --- a/torchaudio/backend/sox_backend.py +++ b/torchaudio/backend/sox_backend.py @@ -63,6 +63,7 @@ def load(filepath: str, @_mod_utils.requires_module('torchaudio._torchaudio') +@_mod_utils.deprecated('Please use "torchaudio.load".', '0.9.0') @common._impl_load_wav def load_wav(filepath, **kwargs): kwargs['normalization'] = 1 << 16 diff --git a/torchaudio/backend/sox_io_backend.py b/torchaudio/backend/sox_io_backend.py index 9c0695d723..e2823ada00 100644 --- a/torchaudio/backend/sox_io_backend.py +++ b/torchaudio/backend/sox_io_backend.py @@ -24,11 +24,15 @@ def info(filepath: str) -> AudioMetaData: """Get signal information of an audio file. Args: - filepath (str): Path to audio file + filepath (str or pathlib.Path): + Path to audio file. This function also handles ``pathlib.Path`` objects, but is annotated as + ``str`` for TorchScript compiler compatibility. Returns: AudioMetaData: meta data of the given audio. """ + # Cast to str in case type is `pathlib.Path` + filepath = str(filepath) sinfo = torch.ops.torchaudio.sox_io_get_info(filepath) return AudioMetaData(sinfo.get_sample_rate(), sinfo.get_num_frames(), sinfo.get_num_channels()) @@ -80,8 +84,9 @@ def load( ``[-1.0, 1.0]``. Args: - filepath (str): - Path to audio file + filepath (str or pathlib.Path): + Path to audio file. This function also handles ``pathlib.Path`` objects, but is + annotated as ``str`` for TorchScript compiler compatibility. frame_offset (int): Number of frames to skip before start reading data. num_frames (int): @@ -105,6 +110,8 @@ def load( integer type, else ``float32`` type. If ``channels_first=True``, it has ``[channel, time]`` else ``[time, channel]``. """ + # Cast to str in case type is `pathlib.Path` + filepath = str(filepath) signal = torch.ops.torchaudio.sox_io_load_audio_file( filepath, frame_offset, num_frames, normalize, channels_first) return signal.get_tensor(), signal.get_sample_rate() @@ -140,7 +147,9 @@ def save( and corresponding codec libraries such as ``libmad`` or ``libmp3lame`` etc. Args: - filepath (str): Path to save file. + filepath (str or pathlib.Path): + Path to save file. This function also handles ``pathlib.Path`` objects, but is annotated + as ``str`` for TorchScript compiler compatibility. tensor (torch.Tensor): Audio data to save. must be 2D tensor. sample_rate (int): sampling rate channels_first (bool): @@ -158,8 +167,10 @@ def save( See the detail at http://sox.sourceforge.net/soxformat.html. """ + # Cast to str in case type is `pathlib.Path` + filepath = str(filepath) if compression is None: - ext = str(filepath)[-3:].lower() + ext = str(filepath).split('.')[-1].lower() if ext in ['wav', 'sph']: compression = 0. elif ext == 'mp3': @@ -175,6 +186,7 @@ def save( @_mod_utils.requires_module('torchaudio._torchaudio') +@_mod_utils.deprecated('Please use "torchaudio.load".', '0.9.0') def load_wav( filepath: str, frame_offset: int = 0, diff --git a/torchaudio/backend/utils.py b/torchaudio/backend/utils.py index 84ec2fa3f5..87ec948fba 100644 --- a/torchaudio/backend/utils.py +++ b/torchaudio/backend/utils.py @@ -49,6 +49,11 @@ def set_audio_backend(backend: Optional[str]): if backend is None: module = no_backend elif backend == 'sox': + warnings.warn( + '"sox" backend is being deprecated. ' + 'The default backend will be changed to "sox_io" backend in 0.8.0 and ' + '"sox" backend will be removed in 0.9.0. Please migrate to "sox_io" backend. ' + 'Please refer to https://github.com/pytorch/audio/issues/903 for the detail.') module = sox_backend elif backend == 'sox_io': module = sox_io_backend diff --git a/torchaudio/datasets/__init__.py b/torchaudio/datasets/__init__.py index fb9e0db506..5e5b9c1118 100644 --- a/torchaudio/datasets/__init__.py +++ b/torchaudio/datasets/__init__.py @@ -8,6 +8,7 @@ from .ljspeech import LJSPEECH from .cmuarctic import CMUARCTIC from .libritts import LIBRITTS +from .tedlium import TEDLIUM __all__ = ( "COMMONVOICE", @@ -19,7 +20,8 @@ "LJSPEECH", "GTZAN", "CMUARCTIC", - "LIBRITTS" + "LIBRITTS", "diskcache_iterator", "bg_iterator", + "TEDLIUM", ) diff --git a/torchaudio/datasets/tedlium.py b/torchaudio/datasets/tedlium.py new file mode 100644 index 0000000000..4ae1ddeb0f --- /dev/null +++ b/torchaudio/datasets/tedlium.py @@ -0,0 +1,208 @@ +import os +from typing import Tuple + +import torchaudio +from torch import Tensor +from torch.utils.data import Dataset +from torchaudio.datasets.utils import ( + download_url, + extract_archive, +) + + +_RELEASE_CONFIGS = { + "release1": { + "folder_in_archive": "TEDLIUM_release1", + "url": "http://www.openslr.org/resources/7/TEDLIUM_release1.tar.gz", + "checksum": "30301975fd8c5cac4040c261c0852f57cfa8adbbad2ce78e77e4986957445f27", + "data_path": "", + "subset": "train", + "supported_subsets": ["train", "test", "dev"], + "dict": "TEDLIUM.150K.dic", + }, + "release2": { + "folder_in_archive": "TEDLIUM_release2", + "url": "http://www.openslr.org/resources/19/TEDLIUM_release2.tar.gz", + "checksum": "93281b5fcaaae5c88671c9d000b443cb3c7ea3499ad12010b3934ca41a7b9c58", + "data_path": "", + "subset": "train", + "supported_subsets": ["train", "test", "dev"], + "dict": "TEDLIUM.152k.dic", + }, + "release3": { + "folder_in_archive": "TEDLIUM_release-3", + "url": "http://www.openslr.org/resources/51/TEDLIUM_release-3.tgz", + "checksum": "ad1e454d14d1ad550bc2564c462d87c7a7ec83d4dc2b9210f22ab4973b9eccdb", + "data_path": "data/", + "subset": None, + "supported_subsets": [None], + "dict": "TEDLIUM.152k.dic", + }, +} + + +class TEDLIUM(Dataset): + """ + Create a Dataset for Tedlium. It supports releases 1,2 and 3, each item is a list containings: + [waveform, sample_rate, transcript, talk_id, speaker_id, identifier]. + + Constructor arguments: + + Args: + root (str): Path containing dataset or target path where its downloaded if needed + release (str, optional): TEDLIUM identifier (release1,release2,release3). Defaults to RELEASE. + subset (str, optional): train/dev/test for releases 1&2, None for release3. Defaults to Train/None + download (bool, optional): Download dataset in case is not founded in root path. Defaults to False. + audio_ext (str, optional): Overwrite audio extension when loading items. Defaults to ".sph". + + Special functions: + + _load_tedlium_item: Loads a TEDLIUM dataset sample given a file name and corresponding sentence name + + _load_audio: Default load function used in TEDLIUM dataset, you can overwrite this function to customize + functionality and load individual sentences from a full ted audio talk file + + get_phoneme_dict: Returns the phoneme dictionary of a TEDLIUM release + + """ + + def __init__( + self, root: str, release: str = "release1", subset: str = None, download: bool = False, audio_ext=".sph" + ) -> None: + """Constructor for TEDLIUM dataset. + + Args: + root (str): Path containing dataset or target path where its downloaded if needed + release (str, optional): TEDLIUM identifier (release1,release2,release3). Defaults to RELEASE. + subset (str, optional): train/dev/test for releases 1&2, None for release3. Defaults to Train/None + download (bool, optional): Download dataset in case is not founded in root path. Defaults to False. + audio_ext (str, optional): Overwrite audio extension when loading items. Defaults to ".sph". + + Raises: + RuntimeError: If release identifier does not match any supported release, + """ + self._ext_audio = audio_ext + if release in _RELEASE_CONFIGS.keys(): + folder_in_archive = _RELEASE_CONFIGS[release]["folder_in_archive"] + url = _RELEASE_CONFIGS[release]["url"] + subset = subset if subset else _RELEASE_CONFIGS[release]["subset"] + else: + # Raise warning + raise RuntimeError( + "The release {} does not match any of the supported tedlium releases{} ".format( + release, _RELEASE_CONFIGS.keys(), + ) + ) + if subset not in _RELEASE_CONFIGS[release]["supported_subsets"]: + # Raise warning + raise RuntimeError( + "The subset {} does not match any of the supported tedlium subsets{} ".format( + subset, _RELEASE_CONFIGS[release]["supported_subsets"], + ) + ) + + basename = os.path.basename(url) + archive = os.path.join(root, basename) + + basename = basename.split(".")[0] + + self._path = os.path.join(root, folder_in_archive, _RELEASE_CONFIGS[release]["data_path"]) + if subset in ["train", "dev", "test"]: + self._path = os.path.join(self._path, subset) + + if download: + if not os.path.isdir(self._path): + if not os.path.isfile(archive): + checksum = _RELEASE_CONFIGS[release]["checksum"] + download_url(url, root, hash_value=checksum) + extract_archive(archive) + + # Create list for all samples + self._filelist = [] + stm_path = os.path.join(self._path, "stm") + for file in sorted(os.listdir(stm_path)): + if file.endswith(".stm"): + stm_path = os.path.join(self._path, "stm", file) + with open(stm_path) as f: + l = len(f.readlines()) + file = file.replace(".stm", "") + self._filelist.extend((file, line) for line in range(l)) + # Create dict path for later read + self._dict_path = os.path.join(root, folder_in_archive, _RELEASE_CONFIGS[release]["dict"]) + self._phoneme_dict = None + + def _load_tedlium_item(self, fileid: str, line: int, path: str) -> Tuple[Tensor, int, str, int, int, int]: + """Loads a TEDLIUM dataset sample given a file name and corresponding sentence name. + + Args: + fileid (str): File id to identify both text and audio files corresponding to the sample + line (int): Line identifier for the sample inside the text file + path (str): Dataset root path + + Returns: + Tedlium_item: A namedTuple containing [waveform, sample_rate, transcript, talk_id, speaker_id, identifier] + """ + transcript_path = os.path.join(path, "stm", fileid) + with open(transcript_path + ".stm") as f: + transcript = f.readlines()[line] + talk_id, _, speaker_id, start_time, end_time, identifier, transcript = transcript.split(" ", 6) + + wave_path = os.path.join(path, "sph", fileid) + waveform, sample_rate = self._load_audio(wave_path + self._ext_audio, start_time=start_time, end_time=end_time) + + return (waveform, sample_rate, transcript, talk_id, speaker_id, identifier) + + def _load_audio(self, path: str, start_time: float, end_time: float, sample_rate: int = 16000) -> [Tensor, int]: + """Default load function used in TEDLIUM dataset, you can overwrite this function to customize functionality + and load individual sentences from a full ted audio talk file. + + Args: + path (str): Path to audio file + start_time (int, optional): Time in seconds where the sample sentence stars + end_time (int, optional): Time in seconds where the sample sentence finishes + + Returns: + [Tensor, int]: Audio tensor representation and sample rate + """ + start_time = int(float(start_time) * sample_rate) + end_time = int(float(end_time) * sample_rate) + if torchaudio.get_audio_backend() == "sox_io": + return torchaudio.load(path, frame_offset=start_time, num_frames=end_time - start_time) + return torchaudio.load(path)[:, start_time:end_time] + + def __getitem__(self, n: int) -> Tuple[Tensor, int, str, int, int, int]: + """TEDLIUM dataset custom function overwritting default loadbehaviour + Loads a TEDLIUM sample given a index N. + + Args: + n (int): Index of sample to be loaded + + Returns: + Tedlium_item: A namedTuple containing [waveform, sample_rate, transcript, talk_id, speaker_id, identifier] + """ + fileid, line = self._filelist[n] + return self._load_tedlium_item(fileid, line, self._path) + + def __len__(self) -> int: + """TEDLIUM dataset custom function overwritting len default behaviour. + + Returns: + int: TEDLIUM dataset length + """ + return len(self._filelist) + + @property + def phoneme_dict(self): + """Returns the phoneme dictionary of a TEDLIUM release. + + Returns: + dictionary: Phoneme dictionary for the current tedlium release + """ + # Read phoneme dictionary + if not self._phoneme_dict: + self._phoneme_dict = {} + with open(self._dict_path, "r", encoding="utf-8") as f: + for line in f.readlines(): + content = line.strip().split() + self._phoneme_dict[content[0]] = tuple(content[1:]) # content[1:] can be empty list + return self._phoneme_dict.copy() diff --git a/torchaudio/functional.py b/torchaudio/functional.py index 4e8e62848e..a6514c79f2 100644 --- a/torchaudio/functional.py +++ b/torchaudio/functional.py @@ -313,6 +313,13 @@ def create_fb_matrix( enorm = 2.0 / (f_pts[2:n_mels + 2] - f_pts[:n_mels]) fb *= enorm.unsqueeze(0) + if (fb.max(dim=0).values == 0.).any(): + warnings.warn( + "At least one mel filterbank has all zero values. " + f"The value for `n_mels` ({n_mels}) may be set too high. " + f"Or, the value for `n_freqs` ({n_freqs}) may be set too low." + ) + return fb From f4611b75da718bbc312b55e5262127bd397059f8 Mon Sep 17 00:00:00 2001 From: Alexei Baevski Date: Tue, 6 Oct 2020 16:59:20 -0700 Subject: [PATCH 19/73] replace max-sentences with batch-size for dependencies Summary: this fixes some regressions introduced by D24121305. fairseq configuration is changing from command line to dataclasses (via hydra eventually) which no longer supports option aliases. one such alias is --max-sentences / --batch-size, and D24121305 removed --max-sentences as --batch-size is more appropriate (fairseq is not just an nlp framework dealing with sentences). unfortunately it seems some existing flows broke and this diff attempts to fix this Differential Revision: D24142488 fbshipit-source-id: 075180ea10a9d706a3f8d64b978d66dfd83c3d2b --- examples/interactive_asr/utils.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/interactive_asr/utils.py b/examples/interactive_asr/utils.py index 37f5ae5303..3aae6c6864 100644 --- a/examples/interactive_asr/utils.py +++ b/examples/interactive_asr/utils.py @@ -124,7 +124,7 @@ def setup_asr(args, logger): check_args(args) import_user_module(args) - if args.max_tokens is None and args.max_sentences is None: + if args.max_tokens is None and args.batch_size is None: args.max_tokens = 30000 logger.info(args) From d0e2281b4e8e3a2089162f43d3efeebe1e79bfec Mon Sep 17 00:00:00 2001 From: Moto Hira Date: Mon, 2 Nov 2020 11:36:53 -0800 Subject: [PATCH 20/73] Import torchaudio #996 758f6c2 Reviewed By: cpuhrsch Differential Revision: D24606263 fbshipit-source-id: 4301b1df84d20c671783ec34c52d5b257374abf1 --- .circleci/config.yml | 47 +- .circleci/config.yml.in | 41 +- .circleci/regenerate.py | 2 +- .circleci/torchscript_bc_test/common.sh | 3 - .../unittest/linux/scripts/environment.yml | 1 - .circleci/unittest/linux/scripts/install.sh | 39 +- .../linux/scripts/run_style_checks.sh | 19 +- .circleci/unittest/linux/scripts/run_test.sh | 17 +- .circleci/unittest/linux/scripts/setup_env.sh | 11 +- .../unittest/windows/scripts/environment.yml | 1 + .circleci/unittest/windows/scripts/install.sh | 20 +- .../unittest/windows/scripts/setup_env.sh | 4 - README.md | 1 + docs/requirements.txt | 2 +- .../source/_static/img/pytorch-logo-flame.png | Bin 0 -> 22916 bytes docs/source/backend.rst | 155 ++-- docs/source/datasets.rst | 43 +- docs/source/index.rst | 35 + docs/source/models.rst | 8 + docs/source/sox_effects.rst | 19 - examples/pipeline_wav2letter/README.md | 45 ++ examples/pipeline_wav2letter/ctc_decoders.py | 15 + examples/pipeline_wav2letter/datasets.py | 113 +++ .../pipeline_wav2letter/languagemodels.py | 38 + examples/pipeline_wav2letter/main.py | 668 ++++++++++++++++++ examples/pipeline_wav2letter/metrics.py | 38 + examples/pipeline_wav2letter/transforms.py | 11 + examples/pipeline_wav2letter/utils.py | 55 ++ examples/source_separation/README.md | 168 +++++ .../source_separation/conv_tasnet/README.md | 52 ++ .../source_separation/conv_tasnet/__init__.py | 4 + .../source_separation/conv_tasnet/train.py | 332 +++++++++ .../source_separation/conv_tasnet/trainer.py | 165 +++++ examples/source_separation/train.py | 176 +++++ examples/source_separation/utils/__init__.py | 5 + .../utils/dataset/__init__.py | 1 + .../source_separation/utils/dataset/utils.py | 83 +++ .../utils/dataset/wsj0mix.py | 70 ++ .../source_separation/utils/dist_utils.py | 86 +++ examples/source_separation/utils/metrics.py | 204 ++++++ packaging/build_conda.sh | 2 +- packaging/build_wheel.sh | 2 +- packaging/pkg_helpers.bash | 5 +- setup.py | 2 +- test/torchaudio_unittest/backend_test.py | 14 +- .../common_utils/backend_utils.py | 6 +- .../common_utils/wav_utils.py | 12 +- test/torchaudio_unittest/dataloader_test.py | 39 - .../datasets/speechcommands_test.py | 143 +++- .../datasets/tedlium_test.py | 23 +- test/torchaudio_unittest/example/__init__.py | 8 + .../example/souce_sepration/__init__.py | 0 .../example/souce_sepration/metrics_test.py | 39 + .../example/souce_sepration/sdr_reference.py | 98 +++ .../example/souce_sepration/wsj0mix_test.py | 111 +++ test/torchaudio_unittest/io_test.py | 3 + test/torchaudio_unittest/models_test.py | 63 +- .../soundfile_backend/__init__.py | 0 .../soundfile_backend/common.py | 34 + .../soundfile_backend/info_test.py | 95 +++ .../soundfile_backend/load_test.py | 265 +++++++ .../soundfile_backend/save_test.py | 211 ++++++ .../sox_effect/sox_effects_chain_test.py | 224 ------ torchaudio/__init__.py | 31 +- torchaudio/backend/_soundfile_backend.py | 223 ++++++ torchaudio/backend/common.py | 30 +- torchaudio/backend/sox_backend.py | 18 + torchaudio/backend/sox_io_backend.py | 20 +- torchaudio/backend/utils.py | 27 +- torchaudio/compliance/kaldi.py | 8 +- torchaudio/csrc/sox.cpp | 201 ------ torchaudio/csrc/sox.h | 22 - torchaudio/datasets/cmuarctic.py | 25 +- torchaudio/datasets/commonvoice.py | 37 +- torchaudio/datasets/gtzan.py | 32 +- torchaudio/datasets/librispeech.py | 24 +- torchaudio/datasets/libritts.py | 25 +- torchaudio/datasets/ljspeech.py | 21 +- torchaudio/datasets/speechcommands.py | 67 +- torchaudio/datasets/tedlium.py | 67 +- torchaudio/datasets/vctk.py | 64 +- torchaudio/datasets/yesno.py | 23 +- torchaudio/functional.py | 18 +- torchaudio/models/__init__.py | 5 +- torchaudio/models/conv_tasnet.py | 327 +++++++++ torchaudio/sox_effects/__init__.py | 2 - torchaudio/sox_effects/sox_effects.py | 198 +----- torchaudio/transforms.py | 3 +- 88 files changed, 4664 insertions(+), 1050 deletions(-) create mode 100644 docs/source/_static/img/pytorch-logo-flame.png create mode 100644 examples/pipeline_wav2letter/README.md create mode 100644 examples/pipeline_wav2letter/ctc_decoders.py create mode 100644 examples/pipeline_wav2letter/datasets.py create mode 100644 examples/pipeline_wav2letter/languagemodels.py create mode 100644 examples/pipeline_wav2letter/main.py create mode 100644 examples/pipeline_wav2letter/metrics.py create mode 100644 examples/pipeline_wav2letter/transforms.py create mode 100644 examples/pipeline_wav2letter/utils.py create mode 100644 examples/source_separation/README.md create mode 100644 examples/source_separation/conv_tasnet/README.md create mode 100644 examples/source_separation/conv_tasnet/__init__.py create mode 100644 examples/source_separation/conv_tasnet/train.py create mode 100644 examples/source_separation/conv_tasnet/trainer.py create mode 100644 examples/source_separation/train.py create mode 100644 examples/source_separation/utils/__init__.py create mode 100644 examples/source_separation/utils/dataset/__init__.py create mode 100644 examples/source_separation/utils/dataset/utils.py create mode 100644 examples/source_separation/utils/dataset/wsj0mix.py create mode 100644 examples/source_separation/utils/dist_utils.py create mode 100644 examples/source_separation/utils/metrics.py delete mode 100644 test/torchaudio_unittest/dataloader_test.py create mode 100644 test/torchaudio_unittest/example/__init__.py create mode 100644 test/torchaudio_unittest/example/souce_sepration/__init__.py create mode 100644 test/torchaudio_unittest/example/souce_sepration/metrics_test.py create mode 100644 test/torchaudio_unittest/example/souce_sepration/sdr_reference.py create mode 100644 test/torchaudio_unittest/example/souce_sepration/wsj0mix_test.py create mode 100644 test/torchaudio_unittest/soundfile_backend/__init__.py create mode 100644 test/torchaudio_unittest/soundfile_backend/common.py create mode 100644 test/torchaudio_unittest/soundfile_backend/info_test.py create mode 100644 test/torchaudio_unittest/soundfile_backend/load_test.py create mode 100644 test/torchaudio_unittest/soundfile_backend/save_test.py delete mode 100644 test/torchaudio_unittest/sox_effect/sox_effects_chain_test.py create mode 100644 torchaudio/backend/_soundfile_backend.py create mode 100644 torchaudio/models/conv_tasnet.py diff --git a/.circleci/config.yml b/.circleci/config.yml index b2b0dd45c3..472c3f0af6 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -34,7 +34,7 @@ commands: command: | our_upload_channel=nightly # On tags upload to test instead - if [[ -n "${CIRCLE_TAG}" ]]; then + if [[ -n "${CIRCLE_TAG}" ]] || [[ ${CIRCLE_BRANCH} =~ release/* ]]; then our_upload_channel=test fi echo "export UPLOAD_CHANNEL=${our_upload_channel}" >> ${BASH_ENV} @@ -296,12 +296,13 @@ jobs: steps: - attach_workspace: at: ~/workspace + - designate_upload_channel - run: name: install binaries command: | set -x source /usr/local/etc/profile.d/conda.sh && conda activate python${PYTHON_VERSION} - pip install $(ls ~/workspace/torchaudio*.whl) -f https://download.pytorch.org/whl/nightly/torch_nightly.html -f https://download.pytorch.org/whl/test/torch_test.html + pip install $(ls ~/workspace/torchaudio*.whl) -f "https://download.pytorch.org/whl/${UPLOAD_CHANNEL}/torch_${UPLOAD_CHANNEL}.html" - run: name: smoke test command: | @@ -315,6 +316,7 @@ jobs: steps: - attach_workspace: at: ~/workspace + - designate_upload_channel - run: name: install binaries command: | @@ -323,7 +325,7 @@ jobs: conda env remove -n python${PYTHON_VERSION} || true conda create -yn python${PYTHON_VERSION} python=${PYTHON_VERSION} conda activate python${PYTHON_VERSION} - conda install -v -y -c pytorch-test -c pytorch-nightly pytorch + conda install -v -y -c pytorch-${UPLOAD_CHANNEL} pytorch conda install -v -y $(ls ~/workspace/torchaudio*.tar.bz2) - run: name: smoke test @@ -339,6 +341,7 @@ jobs: steps: - attach_workspace: at: ~/workspace + - designate_upload_channel - run: name: install binaries command: | @@ -347,7 +350,7 @@ jobs: conda env remove -n python${PYTHON_VERSION} || true conda create -yn python${PYTHON_VERSION} python=${PYTHON_VERSION} conda activate python${PYTHON_VERSION} - pip install $(ls ~/workspace/torchaudio*.whl) -f https://download.pytorch.org/whl/nightly/torch_nightly.html -f https://download.pytorch.org/whl/test/torch_test.html + pip install $(ls ~/workspace/torchaudio*.whl) -f "https://download.pytorch.org/whl/${UPLOAD_CHANNEL}/torch_${UPLOAD_CHANNEL}.html" - run: name: smoke test command: | @@ -391,18 +394,19 @@ jobs: - checkout - attach_workspace: at: third_party + - designate_upload_channel - generate_cache_key - restore_cache: keys: - - env-v3-linux-{{ arch }}-py<< parameters.python_version >>-{{ checksum ".circleci/unittest/linux/scripts/environment.yml" }}-{{ checksum "third_party/CMakeLists.txt" }}-{{ checksum ".cachekey" }} + - env-v3-linux-{{ arch }}-py<< parameters.python_version >>-{{ checksum ".circleci/unittest/linux/scripts/setup_env.sh" }}-{{ checksum "third_party/CMakeLists.txt" }}-{{ checksum ".cachekey" }} - run: name: Setup command: .circleci/unittest/linux/scripts/setup_env.sh - save_cache: - key: env-v3-linux-{{ arch }}-py<< parameters.python_version >>-{{ checksum ".circleci/unittest/linux/scripts/environment.yml" }}-{{ checksum "third_party/CMakeLists.txt" }}-{{ checksum ".cachekey" }} + key: env-v3-linux-{{ arch }}-py<< parameters.python_version >>-{{ checksum ".circleci/unittest/linux/scripts/setup_env.sh" }}-{{ checksum "third_party/CMakeLists.txt" }}-{{ checksum ".cachekey" }} paths: - conda @@ -433,18 +437,19 @@ jobs: - checkout - attach_workspace: at: third_party + - designate_upload_channel - generate_cache_key - restore_cache: keys: - - env-v3-linux-{{ arch }}-py<< parameters.python_version >>-{{ checksum ".circleci/unittest/linux/scripts/environment.yml" }}-{{ checksum "third_party/CMakeLists.txt" }}-{{ checksum ".cachekey" }} + - env-v3-linux-{{ arch }}-py<< parameters.python_version >>-{{ checksum ".circleci/unittest/linux/scripts/setup_env.sh" }}-{{ checksum "third_party/CMakeLists.txt" }}-{{ checksum ".cachekey" }} - run: name: Setup command: docker run -t --gpus all -v $PWD:$PWD -w $PWD "${image_name}" .circleci/unittest/linux/scripts/setup_env.sh - save_cache: - key: env-v3-linux-{{ arch }}-py<< parameters.python_version >>-{{ checksum ".circleci/unittest/linux/scripts/environment.yml" }}-{{ checksum "third_party/CMakeLists.txt" }}-{{ checksum ".cachekey" }} + key: env-v3-linux-{{ arch }}-py<< parameters.python_version >>-{{ checksum ".circleci/unittest/linux/scripts/setup_env.sh" }}-{{ checksum "third_party/CMakeLists.txt" }}-{{ checksum ".cachekey" }} paths: - conda @@ -470,18 +475,19 @@ jobs: name: windows-cpu steps: - checkout + - designate_upload_channel - generate_cache_key - restore_cache: keys: - - env-v3-windows-{{ arch }}-py<< parameters.python_version >>-{{ checksum ".circleci/unittest/windows/scripts/environment.yml" }}-{{ checksum ".cachekey" }} + - env-v3-windows-{{ arch }}-py<< parameters.python_version >>-{{ checksum ".circleci/unittest/windows/scripts/setup_env.sh" }}-{{ checksum ".cachekey" }} - run: name: Setup command: .circleci/unittest/windows/scripts/setup_env.sh - save_cache: - key: env-v3-windows-{{ arch }}-py<< parameters.python_version >>-{{ checksum ".circleci/unittest/windows/scripts/environment.yml" }}-{{ checksum ".cachekey" }} + key: env-v3-windows-{{ arch }}-py<< parameters.python_version >>-{{ checksum ".circleci/unittest/windows/scripts/setup_env.sh" }}-{{ checksum ".cachekey" }} paths: - conda @@ -506,18 +512,19 @@ jobs: CUDA_VERSION: "10.1" steps: - checkout + - designate_upload_channel - generate_cache_key - restore_cache: keys: - - env-v1-windows-{{ arch }}-py<< parameters.python_version >>-{{ checksum ".circleci/unittest/windows/scripts/environment.yml" }}-{{ checksum ".cachekey" }} + - env-v1-windows-{{ arch }}-py<< parameters.python_version >>-{{ checksum ".circleci/unittest/windows/scripts/setup_env.sh" }}-{{ checksum ".cachekey" }} - run: name: Setup command: .circleci/unittest/windows/scripts/setup_env.sh - save_cache: - key: env-v1-windows-{{ arch }}-py<< parameters.python_version >>-{{ checksum ".circleci/unittest/windows/scripts/environment.yml" }}-{{ checksum ".cachekey" }} + key: env-v1-windows-{{ arch }}-py<< parameters.python_version >>-{{ checksum ".circleci/unittest/windows/scripts/setup_env.sh" }}-{{ checksum ".cachekey" }} paths: - conda @@ -544,18 +551,19 @@ jobs: - install_build_tools_macos - attach_workspace: at: third_party + - designate_upload_channel - generate_cache_key - restore_cache: keys: - - env-v3-macos-{{ arch }}-py<< parameters.python_version >>-{{ checksum ".circleci/unittest/linux/scripts/environment.yml" }}-{{ checksum "third_party/CMakeLists.txt" }}-{{ checksum ".cachekey" }} + - env-v3-macos-{{ arch }}-py<< parameters.python_version >>-{{ checksum ".circleci/unittest/linux/scripts/setup_env.sh" }}-{{ checksum "third_party/CMakeLists.txt" }}-{{ checksum ".cachekey" }} - run: name: Setup command: .circleci/unittest/linux/scripts/setup_env.sh - save_cache: - key: env-v3-macos-{{ arch }}-py<< parameters.python_version >>-{{ checksum ".circleci/unittest/linux/scripts/environment.yml" }}-{{ checksum "third_party/CMakeLists.txt" }}-{{ checksum ".cachekey" }} + key: env-v3-macos-{{ arch }}-py<< parameters.python_version >>-{{ checksum ".circleci/unittest/linux/scripts/setup_env.sh" }}-{{ checksum "third_party/CMakeLists.txt" }}-{{ checksum ".cachekey" }} paths: - conda @@ -582,18 +590,19 @@ jobs: resource_class: medium steps: - checkout + - designate_upload_channel - generate_cache_key - restore_cache: keys: - - env-v2-linux-{{ arch }}-py<< parameters.python_version >>-{{ checksum ".circleci/unittest/linux/scripts/environment.yml" }}-{{ checksum ".cachekey" }} + - env-v2-linux-{{ arch }}-py<< parameters.python_version >>-{{ checksum ".circleci/unittest/linux/scripts/setup_env.sh" }}-{{ checksum ".cachekey" }} - run: name: Setup command: .circleci/unittest/linux/scripts/setup_env.sh - save_cache: - key: env-v2-linux-{{ arch }}-py<< parameters.python_version >>-{{ checksum ".circleci/unittest/linux/scripts/environment.yml" }}-{{ checksum ".cachekey" }} + key: env-v2-linux-{{ arch }}-py<< parameters.python_version >>-{{ checksum ".circleci/unittest/linux/scripts/setup_env.sh" }}-{{ checksum ".cachekey" }} paths: - conda @@ -756,6 +765,7 @@ workflows: only: - master - nightly + - release/* tags: only: /v[0-9]+(\.[0-9]+)*-rc[0-9]+/ name: unittest_linux_gpu_py3.6 @@ -768,6 +778,7 @@ workflows: only: - master - nightly + - release/* tags: only: /v[0-9]+(\.[0-9]+)*-rc[0-9]+/ name: unittest_linux_gpu_py3.7 @@ -780,6 +791,7 @@ workflows: only: - master - nightly + - release/* tags: only: /v[0-9]+(\.[0-9]+)*-rc[0-9]+/ name: unittest_linux_gpu_py3.8 @@ -801,6 +813,7 @@ workflows: only: - master - nightly + - release/* tags: only: /v[0-9]+(\.[0-9]+)*-rc[0-9]+/ name: unittest_windows_gpu_py3.6 @@ -811,6 +824,7 @@ workflows: only: - master - nightly + - release/* tags: only: /v[0-9]+(\.[0-9]+)*-rc[0-9]+/ name: unittest_windows_gpu_py3.7 @@ -821,6 +835,7 @@ workflows: only: - master - nightly + - release/* tags: only: /v[0-9]+(\.[0-9]+)*-rc[0-9]+/ name: unittest_windows_gpu_py3.8 diff --git a/.circleci/config.yml.in b/.circleci/config.yml.in index b1f40c24c0..6f6838deff 100644 --- a/.circleci/config.yml.in +++ b/.circleci/config.yml.in @@ -34,7 +34,7 @@ commands: command: | our_upload_channel=nightly # On tags upload to test instead - if [[ -n "${CIRCLE_TAG}" ]]; then + if [[ -n "${CIRCLE_TAG}" ]] || [[ ${CIRCLE_BRANCH} =~ release/* ]]; then our_upload_channel=test fi echo "export UPLOAD_CHANNEL=${our_upload_channel}" >> ${BASH_ENV} @@ -296,12 +296,13 @@ jobs: steps: - attach_workspace: at: ~/workspace + - designate_upload_channel - run: name: install binaries command: | set -x source /usr/local/etc/profile.d/conda.sh && conda activate python${PYTHON_VERSION} - pip install $(ls ~/workspace/torchaudio*.whl) -f https://download.pytorch.org/whl/nightly/torch_nightly.html -f https://download.pytorch.org/whl/test/torch_test.html + pip install $(ls ~/workspace/torchaudio*.whl) -f "https://download.pytorch.org/whl/${UPLOAD_CHANNEL}/torch_${UPLOAD_CHANNEL}.html" - run: name: smoke test command: | @@ -315,6 +316,7 @@ jobs: steps: - attach_workspace: at: ~/workspace + - designate_upload_channel - run: name: install binaries command: | @@ -323,7 +325,7 @@ jobs: conda env remove -n python${PYTHON_VERSION} || true conda create -yn python${PYTHON_VERSION} python=${PYTHON_VERSION} conda activate python${PYTHON_VERSION} - conda install -v -y -c pytorch-test -c pytorch-nightly pytorch + conda install -v -y -c pytorch-${UPLOAD_CHANNEL} pytorch conda install -v -y $(ls ~/workspace/torchaudio*.tar.bz2) - run: name: smoke test @@ -339,6 +341,7 @@ jobs: steps: - attach_workspace: at: ~/workspace + - designate_upload_channel - run: name: install binaries command: | @@ -347,7 +350,7 @@ jobs: conda env remove -n python${PYTHON_VERSION} || true conda create -yn python${PYTHON_VERSION} python=${PYTHON_VERSION} conda activate python${PYTHON_VERSION} - pip install $(ls ~/workspace/torchaudio*.whl) -f https://download.pytorch.org/whl/nightly/torch_nightly.html -f https://download.pytorch.org/whl/test/torch_test.html + pip install $(ls ~/workspace/torchaudio*.whl) -f "https://download.pytorch.org/whl/${UPLOAD_CHANNEL}/torch_${UPLOAD_CHANNEL}.html" - run: name: smoke test command: | @@ -391,18 +394,19 @@ jobs: - checkout - attach_workspace: at: third_party + - designate_upload_channel - generate_cache_key - restore_cache: {% raw %} keys: - - env-v3-linux-{{ arch }}-py<< parameters.python_version >>-{{ checksum ".circleci/unittest/linux/scripts/environment.yml" }}-{{ checksum "third_party/CMakeLists.txt" }}-{{ checksum ".cachekey" }} + - env-v3-linux-{{ arch }}-py<< parameters.python_version >>-{{ checksum ".circleci/unittest/linux/scripts/setup_env.sh" }}-{{ checksum "third_party/CMakeLists.txt" }}-{{ checksum ".cachekey" }} {% endraw %} - run: name: Setup command: .circleci/unittest/linux/scripts/setup_env.sh - save_cache: {% raw %} - key: env-v3-linux-{{ arch }}-py<< parameters.python_version >>-{{ checksum ".circleci/unittest/linux/scripts/environment.yml" }}-{{ checksum "third_party/CMakeLists.txt" }}-{{ checksum ".cachekey" }} + key: env-v3-linux-{{ arch }}-py<< parameters.python_version >>-{{ checksum ".circleci/unittest/linux/scripts/setup_env.sh" }}-{{ checksum "third_party/CMakeLists.txt" }}-{{ checksum ".cachekey" }} {% endraw %} paths: - conda @@ -433,18 +437,19 @@ jobs: - checkout - attach_workspace: at: third_party + - designate_upload_channel - generate_cache_key - restore_cache: {% raw %} keys: - - env-v3-linux-{{ arch }}-py<< parameters.python_version >>-{{ checksum ".circleci/unittest/linux/scripts/environment.yml" }}-{{ checksum "third_party/CMakeLists.txt" }}-{{ checksum ".cachekey" }} + - env-v3-linux-{{ arch }}-py<< parameters.python_version >>-{{ checksum ".circleci/unittest/linux/scripts/setup_env.sh" }}-{{ checksum "third_party/CMakeLists.txt" }}-{{ checksum ".cachekey" }} {% endraw %} - run: name: Setup command: docker run -t --gpus all -v $PWD:$PWD -w $PWD "${image_name}" .circleci/unittest/linux/scripts/setup_env.sh - save_cache: {% raw %} - key: env-v3-linux-{{ arch }}-py<< parameters.python_version >>-{{ checksum ".circleci/unittest/linux/scripts/environment.yml" }}-{{ checksum "third_party/CMakeLists.txt" }}-{{ checksum ".cachekey" }} + key: env-v3-linux-{{ arch }}-py<< parameters.python_version >>-{{ checksum ".circleci/unittest/linux/scripts/setup_env.sh" }}-{{ checksum "third_party/CMakeLists.txt" }}-{{ checksum ".cachekey" }} {% endraw %} paths: - conda @@ -470,18 +475,19 @@ jobs: name: windows-cpu steps: - checkout + - designate_upload_channel - generate_cache_key - restore_cache: {% raw %} keys: - - env-v3-windows-{{ arch }}-py<< parameters.python_version >>-{{ checksum ".circleci/unittest/windows/scripts/environment.yml" }}-{{ checksum ".cachekey" }} + - env-v3-windows-{{ arch }}-py<< parameters.python_version >>-{{ checksum ".circleci/unittest/windows/scripts/setup_env.sh" }}-{{ checksum ".cachekey" }} {% endraw %} - run: name: Setup command: .circleci/unittest/windows/scripts/setup_env.sh - save_cache: {% raw %} - key: env-v3-windows-{{ arch }}-py<< parameters.python_version >>-{{ checksum ".circleci/unittest/windows/scripts/environment.yml" }}-{{ checksum ".cachekey" }} + key: env-v3-windows-{{ arch }}-py<< parameters.python_version >>-{{ checksum ".circleci/unittest/windows/scripts/setup_env.sh" }}-{{ checksum ".cachekey" }} {% endraw %} paths: - conda @@ -506,18 +512,19 @@ jobs: CUDA_VERSION: "10.1" steps: - checkout + - designate_upload_channel - generate_cache_key - restore_cache: {% raw %} keys: - - env-v1-windows-{{ arch }}-py<< parameters.python_version >>-{{ checksum ".circleci/unittest/windows/scripts/environment.yml" }}-{{ checksum ".cachekey" }} + - env-v1-windows-{{ arch }}-py<< parameters.python_version >>-{{ checksum ".circleci/unittest/windows/scripts/setup_env.sh" }}-{{ checksum ".cachekey" }} {% endraw %} - run: name: Setup command: .circleci/unittest/windows/scripts/setup_env.sh - save_cache: {% raw %} - key: env-v1-windows-{{ arch }}-py<< parameters.python_version >>-{{ checksum ".circleci/unittest/windows/scripts/environment.yml" }}-{{ checksum ".cachekey" }} + key: env-v1-windows-{{ arch }}-py<< parameters.python_version >>-{{ checksum ".circleci/unittest/windows/scripts/setup_env.sh" }}-{{ checksum ".cachekey" }} {% endraw %} paths: - conda @@ -544,18 +551,19 @@ jobs: - install_build_tools_macos - attach_workspace: at: third_party + - designate_upload_channel - generate_cache_key - restore_cache: {% raw %} keys: - - env-v3-macos-{{ arch }}-py<< parameters.python_version >>-{{ checksum ".circleci/unittest/linux/scripts/environment.yml" }}-{{ checksum "third_party/CMakeLists.txt" }}-{{ checksum ".cachekey" }} + - env-v3-macos-{{ arch }}-py<< parameters.python_version >>-{{ checksum ".circleci/unittest/linux/scripts/setup_env.sh" }}-{{ checksum "third_party/CMakeLists.txt" }}-{{ checksum ".cachekey" }} {% endraw %} - run: name: Setup command: .circleci/unittest/linux/scripts/setup_env.sh - save_cache: {% raw %} - key: env-v3-macos-{{ arch }}-py<< parameters.python_version >>-{{ checksum ".circleci/unittest/linux/scripts/environment.yml" }}-{{ checksum "third_party/CMakeLists.txt" }}-{{ checksum ".cachekey" }} + key: env-v3-macos-{{ arch }}-py<< parameters.python_version >>-{{ checksum ".circleci/unittest/linux/scripts/setup_env.sh" }}-{{ checksum "third_party/CMakeLists.txt" }}-{{ checksum ".cachekey" }} {% endraw %} paths: - conda @@ -582,18 +590,19 @@ jobs: resource_class: medium steps: - checkout + - designate_upload_channel - generate_cache_key - restore_cache: {% raw %} keys: - - env-v2-linux-{{ arch }}-py<< parameters.python_version >>-{{ checksum ".circleci/unittest/linux/scripts/environment.yml" }}-{{ checksum ".cachekey" }} + - env-v2-linux-{{ arch }}-py<< parameters.python_version >>-{{ checksum ".circleci/unittest/linux/scripts/setup_env.sh" }}-{{ checksum ".cachekey" }} {% endraw %} - run: name: Setup command: .circleci/unittest/linux/scripts/setup_env.sh - save_cache: {% raw %} - key: env-v2-linux-{{ arch }}-py<< parameters.python_version >>-{{ checksum ".circleci/unittest/linux/scripts/environment.yml" }}-{{ checksum ".cachekey" }} + key: env-v2-linux-{{ arch }}-py<< parameters.python_version >>-{{ checksum ".circleci/unittest/linux/scripts/setup_env.sh" }}-{{ checksum ".cachekey" }} {% endraw %} paths: - conda diff --git a/.circleci/regenerate.py b/.circleci/regenerate.py index 2c9fe7ee4f..2f4d4088d9 100755 --- a/.circleci/regenerate.py +++ b/.circleci/regenerate.py @@ -148,7 +148,7 @@ def unittest_workflows(indentation=6): } if device_type == 'gpu': - job['filters'] = gen_filter_branch_tree('master', 'nightly') + job['filters'] = gen_filter_branch_tree('master', 'nightly', 'release/*') if os_type != "windows": job['requires'] = ['download_third_parties_nix'] diff --git a/.circleci/torchscript_bc_test/common.sh b/.circleci/torchscript_bc_test/common.sh index 51d258a2d9..24ad5e45fb 100644 --- a/.circleci/torchscript_bc_test/common.sh +++ b/.circleci/torchscript_bc_test/common.sh @@ -59,9 +59,6 @@ install_release() { install_build_dependencies() { printf "* Installing torchaudio dependencies except PyTorch - (Python: %s)\n" "$1" conda env update -q --file "${_this_dir}/environment.yml" --prune - if [ "${_os}" == Linux ]; then - pip install clang-format - fi } build_master() { diff --git a/.circleci/unittest/linux/scripts/environment.yml b/.circleci/unittest/linux/scripts/environment.yml index 42acafb984..4315a2205b 100644 --- a/.circleci/unittest/linux/scripts/environment.yml +++ b/.circleci/unittest/linux/scripts/environment.yml @@ -7,7 +7,6 @@ dependencies: - numpy >= 1.11 - pytest - pytest-cov - - pytest-xdist - codecov - librosa>=0.8.0 - llvmlite==0.31 # See https://github.com/pytorch/audio/pull/766 diff --git a/.circleci/unittest/linux/scripts/install.sh b/.circleci/unittest/linux/scripts/install.sh index 8346e6c825..27dec79251 100755 --- a/.circleci/unittest/linux/scripts/install.sh +++ b/.circleci/unittest/linux/scripts/install.sh @@ -7,17 +7,48 @@ unset PYTORCH_VERSION set -e -eval "$(./conda/bin/conda shell.bash hook)" -conda activate ./env +root_dir="$(git rev-parse --show-toplevel)" +conda_dir="${root_dir}/conda" +env_dir="${root_dir}/env" +cd "${root_dir}" + +case "$(uname -s)" in + Darwin*) os=MacOSX;; + *) os=Linux +esac + +# 0. Activate conda env +eval "$("${conda_dir}/bin/conda" shell.bash hook)" +conda activate "${env_dir}" + +# 1. Install PyTorch if [ -z "${CUDA_VERSION:-}" ] ; then - cudatoolkit="cpuonly" + if [ "${os}" == MacOSX ] ; then + cudatoolkit='' + else + cudatoolkit="cpuonly" + fi else version="$(python -c "print('.'.join(\"${CUDA_VERSION}\".split('.')[:2]))")" cudatoolkit="cudatoolkit=${version}" fi printf "Installing PyTorch with %s\n" "${cudatoolkit}" -conda install -y -c pytorch-nightly pytorch "${cudatoolkit}" +conda install -y -c "pytorch-${UPLOAD_CHANNEL}" pytorch ${cudatoolkit} +# 2. Install torchaudio printf "* Installing torchaudio\n" BUILD_SOX=1 python setup.py install + +# 3. Install Test tools +printf "* Installing test tools\n" +if [ "${os}" == Linux ] ; then + # TODO: move this to docker + apt install -y -q libsndfile1 + conda install -y -c conda-forge codecov pytest pytest-cov + pip install kaldi-io 'librosa>=0.8.0' parameterized SoundFile scipy +else + # Note: installing librosa via pip fail because it will try to compile numba. + conda install -y -c conda-forge codecov pytest pytest-cov 'librosa>=0.8.0' parameterized scipy + pip install kaldi-io SoundFile +fi diff --git a/.circleci/unittest/linux/scripts/run_style_checks.sh b/.circleci/unittest/linux/scripts/run_style_checks.sh index 70b83e19f5..468fa415b5 100755 --- a/.circleci/unittest/linux/scripts/run_style_checks.sh +++ b/.circleci/unittest/linux/scripts/run_style_checks.sh @@ -2,9 +2,20 @@ set -u -eval "$(./conda/bin/conda shell.bash hook)" -conda activate ./env +root_dir="$(git rev-parse --show-toplevel)" +conda_dir="${root_dir}/conda" +env_dir="${root_dir}/env" +eval "$("${conda_dir}/bin/conda" shell.bash hook)" +conda activate "${env_dir}" + +# 1. Install tools +conda install flake8 +clangformat_path="${root_dir}/clang-format" +curl https://oss-clang-format.s3.us-east-2.amazonaws.com/linux64/clang-format-linux64 -o "${clangformat_path}" +chmod +x "${clangformat_path}" + +# 2. Run style checks # We want to run all the style checks even if one of them fail. exit_status=0 @@ -20,9 +31,9 @@ if [ "${status}" -ne 0 ]; then fi printf "\x1b[34mRunning clang-format: " -clang-format --version +./clang-format --version printf "\x1b[0m\n" -git-clang-format origin/master +git-clang-format --binary ./clang-format origin/master git diff --exit-code status=$? exit_status="$((exit_status+status))" diff --git a/.circleci/unittest/linux/scripts/run_test.sh b/.circleci/unittest/linux/scripts/run_test.sh index 50bcf711d6..e9016d266c 100755 --- a/.circleci/unittest/linux/scripts/run_test.sh +++ b/.circleci/unittest/linux/scripts/run_test.sh @@ -2,12 +2,6 @@ set -e -case "$(uname -s)" in - Darwin*) os=MacOSX;; - *) os=Linux -esac - - eval "$(./conda/bin/conda shell.bash hook)" conda activate ./env @@ -15,15 +9,12 @@ python -m torch.utils.collect_env export TORCHAUDIO_TEST_FAIL_IF_NO_EXTENSION=1 export PATH="${PWD}/third_party/install/bin/:${PATH}" -declare -a common_args=( +declare -a args=( + '-v' '--cov=torchaudio' "--junitxml=${PWD}/test-results/junit.xml" '--durations' '20' ) -if [ "${os}" == MacOSX ] ; then - declare -a args=('-q' '-n' 'auto' '--dist=loadscope') -else - declare -a args=('-v') -fi + cd test -pytest "${args[@]}" "${common_args[@]}" torchaudio_unittest +pytest "${args[@]}" torchaudio_unittest diff --git a/.circleci/unittest/linux/scripts/setup_env.sh b/.circleci/unittest/linux/scripts/setup_env.sh index 290f0f8f97..6e203dea27 100755 --- a/.circleci/unittest/linux/scripts/setup_env.sh +++ b/.circleci/unittest/linux/scripts/setup_env.sh @@ -7,7 +7,6 @@ set -e -this_dir="$( cd "$( dirname "${BASH_SOURCE[0]}" )" >/dev/null 2>&1 && pwd )" root_dir="$(git rev-parse --show-toplevel)" conda_dir="${root_dir}/conda" env_dir="${root_dir}/env" @@ -34,17 +33,13 @@ if [ ! -d "${env_dir}" ]; then fi conda activate "${env_dir}" -# 3. Install Conda dependencies -printf "* Installing dependencies (except PyTorch)\n" -conda env update --file "${this_dir}/environment.yml" --prune -if [ "${os}" == Linux ] ; then - pip install clang-format -fi +# 3. Install minimal build tools +pip install cmake ninja # 4. Buld codecs mkdir -p third_party/build ( cd third_party/build - cmake .. + cmake -GNinja .. cmake --build . ) diff --git a/.circleci/unittest/windows/scripts/environment.yml b/.circleci/unittest/windows/scripts/environment.yml index 3a41020645..4a0b71d653 100644 --- a/.circleci/unittest/windows/scripts/environment.yml +++ b/.circleci/unittest/windows/scripts/environment.yml @@ -15,3 +15,4 @@ dependencies: - librosa >= 0.8.0 - future - parameterized + - dataclasses diff --git a/.circleci/unittest/windows/scripts/install.sh b/.circleci/unittest/windows/scripts/install.sh index 2b9c88b4af..901cb40450 100644 --- a/.circleci/unittest/windows/scripts/install.sh +++ b/.circleci/unittest/windows/scripts/install.sh @@ -7,9 +7,17 @@ unset PYTORCH_VERSION set -e -eval "$(./conda/Scripts/conda.exe 'shell.bash' 'hook')" -conda activate ./env +root_dir="$(git rev-parse --show-toplevel)" +conda_dir="${root_dir}/conda" +env_dir="${root_dir}/env" +cd "${root_dir}" + +# 0. Activate conda env +eval "$("${conda_dir}/Scripts/conda.exe" 'shell.bash' 'hook')" +conda activate "${env_dir}" + +# 1. Install PyTorch if [ -z "${CUDA_VERSION:-}" ] ; then cudatoolkit="cpuonly" else @@ -17,7 +25,13 @@ else cudatoolkit="cudatoolkit=${version}" fi printf "Installing PyTorch with %s\n" "${cudatoolkit}" -conda install -y -c pytorch-nightly pytorch "${cudatoolkit}" +conda install -y -c "pytorch-${UPLOAD_CHANNEL}" pytorch "${cudatoolkit}" +# 2. Install torchaudio printf "* Installing torchaudio\n" python setup.py install + +# 3. Install Test tools +printf "* Installing test tools\n" +conda install -y -c conda-forge codecov pytest pytest-cov +pip install kaldi-io 'librosa>=0.8.0' parameterized PySoundFile scipy diff --git a/.circleci/unittest/windows/scripts/setup_env.sh b/.circleci/unittest/windows/scripts/setup_env.sh index a45cf856ac..71b556d2bd 100644 --- a/.circleci/unittest/windows/scripts/setup_env.sh +++ b/.circleci/unittest/windows/scripts/setup_env.sh @@ -33,7 +33,3 @@ if [ ! -d "${env_dir}" ]; then conda create --prefix "${env_dir}" -y python="$PYTHON_VERSION" fi conda activate "${env_dir}" - -# 3. Install Conda dependencies -printf "* Installing dependencies (except PyTorch)\n" -conda env update --file "${this_dir}/environment.yml" --prune diff --git a/README.md b/README.md index 70f30be243..861af2a04b 100644 --- a/README.md +++ b/README.md @@ -37,6 +37,7 @@ The following is the corresponding ``torchaudio`` versions and supported Python | ``torch`` | ``torchaudio`` | ``python`` | | ------------------------ | ------------------------ | ------------------------------- | | ``master`` / ``nightly`` | ``master`` / ``nightly`` | ``>=3.6`` | +| ``1.7.0`` | ``0.7.0`` | ``>=3.6`` | | ``1.6.0`` | ``0.6.0`` | ``>=3.6`` | | ``1.5.0`` | ``0.5.0`` | ``>=3.5`` | | ``1.4.0`` | ``0.4.0`` | ``==2.7``, ``>=3.5``, ``<=3.8`` | diff --git a/docs/requirements.txt b/docs/requirements.txt index c591f08491..99a7811de6 100644 --- a/docs/requirements.txt +++ b/docs/requirements.txt @@ -1,4 +1,4 @@ -sphinx +sphinx==2.4.4 -e git+git://github.com/pytorch/pytorch_sphinx_theme.git#egg=pytorch_sphinx_theme sphinxcontrib.katex matplotlib diff --git a/docs/source/_static/img/pytorch-logo-flame.png b/docs/source/_static/img/pytorch-logo-flame.png new file mode 100644 index 0000000000000000000000000000000000000000..bad49bf30b4afe5bb34f76d73a03e39fc48bbedb GIT binary patch literal 22916 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 Nkbkh>g=Oo~{{W#u9;5&O literal 0 HcmV?d00001 diff --git a/docs/source/backend.rst b/docs/source/backend.rst index 6b0e074d5c..1cdb1c923e 100644 --- a/docs/source/backend.rst +++ b/docs/source/backend.rst @@ -3,44 +3,113 @@ torchaudio.backend ================== -:mod:`torchaudio.backend` module provides implementations for audio file I/O, using different backend libraries. -To switch backend, use :py:func:`torchaudio.set_audio_backend`. To check the current backend use :py:func:`torchaudio.get_audio_backend`. +Overview +~~~~~~~~ -.. warning:: - Although ``sox`` backend is default for backward compatibility reason, it has a number of issues, therefore it is highly recommended to use ``sox_io`` backend instead. Note, however, that due to the interface refinement, functions defined in ``sox`` backend and those defined in ``sox_io`` backend do not have the same signatures. +:mod:`torchaudio.backend` module provides implementations for audio file I/O functionalities, which are ``torchaudio.info``, ``torchaudio.load``, ``torchaudio.load_wav`` and ``torchaudio.save``. + +There are currently four implementations available. + +* :ref:`"sox_io" ` (default on Linux/macOS) +* :ref:`"sox" ` (deprecated, will be removed in 0.9.0 release) +* :ref:`"soundfile" ` (default on Windows) +* :ref:`"soundfile" (legacy interface) ` (deprecated, will be removed in 0.9.0 release) + +The use of ``"sox"`` backend is strongly discouraged as it cannot correctly handle formats other than 16-bit integer WAV. See `#726 `_ for the detail. .. note:: - Instead of calling functions in :mod:`torchaudio.backend` directly, please use ``torchaudio.info``, ``torhcaudio.load``, ``torchaudio.load_wav`` and ``torchaudio.save`` with proper backend set with :func:`torchaudio.get_audio_backend`. + Instead of calling functions in ``torchaudio.backend`` directly, please use ``torchaudio.info``, ``torchaudio.load``, ``torchaudio.load_wav`` and ``torchaudio.save`` with proper backend set with :func:`torchaudio.set_audio_backend`. + +Availability +------------ -There are currently three implementations available. +``"sox"`` and ``"sox_io"`` backends require C++ extension module, which is included in Linux/macOS binary distributions. These backends are not available on Windows. - * :ref:`sox` - * :ref:`sox_io` - * :ref:`soundfile` +``"soundfile"`` backend requires ``SoundFile``. Please refer to `the SoundFile documentation `_ for the installation. -``sox`` backend is the original backend which is built on ``libsox``. This module is currently default but is known to have number of issues, such as wrong handling of WAV files other than 16-bit signed integer. Users are encouraged to use ``sox_io`` backend. This backend requires C++ extension module and is not available on Windows system. +Changes in default backend and deprecation +------------------------------------------ -``sox_io`` backend is the new backend which is built on ``libsox`` and bound to Python with ``Torchscript``. This module addresses all the known issues ``sox`` backend has. Function calls to this backend can be Torchscriptable. This backend requires C++ extension module and is not available on Windows system. +Backend module is going through a major overhaul. The following table summarizes the timeline for the deprecations and removals. -``soundfile`` backend is built on ``PySoundFile``. You need to install ``PySoundFile`` separately. + +--------------------+-----------------------+------------------------+ + | **Backend** | **0.8.0** | **0.9.0** | + +====================+=======================+========================+ + | ``"sox_io"`` | Default on Linx/macOS | Default on Linux/macOS | + +--------------------+-----------------------+------------------------+ + | ``"sox"`` | Available | Removed | + | (deprecated) | | | + +--------------------+-----------------------+------------------------+ + | ``"soundfile"`` | Default on Windows | Default on Windows | + +--------------------+-----------------------+------------------------+ + | ``"soundfile"`` | Available | Removed | + | (legacy interface, | | | + | deprecated) | | | + +--------------------+-----------------------+------------------------+ + +* The ``"sox"`` and ``"soundfile" (legacy interface)`` backends are deprecated and will be removed in 0.9.0 release. Common Data Structure ~~~~~~~~~~~~~~~~~~~~~ -Structures used to exchange data between Python interface and ``libsox``. They are used by :ref:`sox` and :ref:`soundfile` but not by :ref:`sox_io`. +Structures used to report the metadata of audio files. + +AudioMetaData +------------- + +.. autoclass:: torchaudio.backend.common.AudioMetaData + +SignalInfo (Deprecated) +----------------------- .. autoclass:: torchaudio.backend.common.SignalInfo -.. autoclass:: torchaudio.backend.common.EncodingInfo +EncodingInfo (Deprecated) +------------------------- + +.. autoclass:: torchaudio.backend.common.EncodingInfo + +.. _sox_io_backend: + +Sox IO Backend +~~~~~~~~~~~~~~ + +The ``"sox_io"`` backend is available and default on Linux/macOS and not available on Windows. + +I/O functions of this backend support `TorchScript `_. + +You can switch from another backend to the ``sox_io`` backend with the following; + +.. code:: + + torchaudio.set_audio_backend("sox_io") + +info +---- + +.. autofunction:: torchaudio.backend.sox_io_backend.info + +load +---- + +.. autofunction:: torchaudio.backend.sox_io_backend.load + +.. autofunction:: torchaudio.backend.sox_io_backend.load_wav + + +save +---- + +.. autofunction:: torchaudio.backend.sox_io_backend.save .. _sox_backend: -Sox Backend -~~~~~~~~~~~ +Sox Backend (Deprecated) +~~~~~~~~~~~~~~~~~~~~~~~~ -``sox`` backend is available on ``torchaudio`` installation with C++ extension. It is currently not available on Windows system. +The ``"sox"`` backend is available on Linux/macOS and not available on Windows. This backend is deprecated and will be removed in ``0.9.0`` release. -It is currently default backend when it's available. You can switch from another backend to ``sox`` backend with the following; +You can switch from another backend to ``sox`` backend with the following; .. code:: @@ -71,61 +140,61 @@ others :members: :exclude-members: info, load, load_wav, save -.. _sox_io_backend: +.. _soundfile_backend: -Sox IO Backend -~~~~~~~~~~~~~~ +Soundfile Backend +~~~~~~~~~~~~~~~~~ -``sox_io`` backend is available on ``torchaudio`` installation with C++ extension. It is currently not available on Windows system. +The ``"soundfile"`` backend is available when `SoundFile `_ is installed. This backend is the default on Windows. -This new backend is recommended over ``sox`` backend. You can switch from another backend to ``sox_io`` backend with the following; +You can switch from another backend to the ``"soundfile"`` backend with the following; .. code:: - torchaudio.set_audio_backend("sox_io") + torchaudio.set_audio_backend("soundfile") -The function call to this backend can be Torchsript-able. You can apply :func:`torch.jit.script` and dump the object to file, then call it from C++ application. +.. note:: + If you are switching from `"soundfile" (legacy interface) ` backend, set ``torchaudio.USE_SOUNDFILE_LEGACY_INTERFACE`` flag **before** switching the backend. info ----- - -.. autoclass:: torchaudio.backend.sox_io_backend.AudioMetaData +^^^^ -.. autofunction:: torchaudio.backend.sox_io_backend.info +.. autofunction:: torchaudio.backend._soundfile_backend.info load ----- +^^^^ -.. autofunction:: torchaudio.backend.sox_io_backend.load +.. autofunction:: torchaudio.backend._soundfile_backend.load -.. autofunction:: torchaudio.backend.sox_io_backend.load_wav +.. autofunction:: torchaudio.backend._soundfile_backend.load_wav save ----- +^^^^ -.. autofunction:: torchaudio.backend.sox_io_backend.save +.. autofunction:: torchaudio.backend._soundfile_backend.save -.. _soundfile_backend: +.. _soundfile_legacy_backend: -Soundfile Backend -~~~~~~~~~~~~~~~~~ +Legacy Interface (Deprecated) +----------------------------- -``soundfile`` backend is available when ``PySoundFile`` is installed. This backend works on ``torchaudio`` installation without C++ extension. (i.e. Windows) +``"soundfile"`` backend with legacy interface is made available for backward compatibility reason, however this interface is deprecated and will be removed in the ``0.9.0`` release. -You can switch from another backend to ``soundfile`` backend with the following; +To switch to this backend/interface, set ``torchaudio.USE_SOUNDFILE_LEGACY_INTERFACE`` flag **before** switching the backend. .. code:: - torchaudio.set_audio_backend("soundfile") + torchaudio.USE_SOUNDFILE_LEGACY_INTERFACE = True + torchaudio.set_audio_backend("soundfile") # The legacy interface info ----- +^^^^ .. autofunction:: torchaudio.backend.soundfile_backend.info load ----- +^^^^ .. autofunction:: torchaudio.backend.soundfile_backend.load @@ -133,6 +202,6 @@ load save ----- +^^^^ .. autofunction:: torchaudio.backend.soundfile_backend.save diff --git a/docs/source/datasets.rst b/docs/source/datasets.rst index b3f1b3c725..2ceb93a440 100644 --- a/docs/source/datasets.rst +++ b/docs/source/datasets.rst @@ -29,82 +29,85 @@ CMUARCTIC ~~~~~~~~~ .. autoclass:: CMUARCTIC - :members: __getitem__ - :special-members: + :members: + :special-members: __getitem__ COMMONVOICE ~~~~~~~~~~~ .. autoclass:: COMMONVOICE - :members: __getitem__ - :special-members: + :members: + :special-members: __getitem__ GTZAN ~~~~~ .. autoclass:: GTZAN - :members: __getitem__ - :special-members: + :members: + :special-members: __getitem__ LIBRISPEECH ~~~~~~~~~~~ .. autoclass:: LIBRISPEECH - :members: __getitem__ - :special-members: + :members: + :special-members: __getitem__ LIBRITTS ~~~~~~~~ .. autoclass:: LIBRITTS - :members: __getitem__ - :special-members: + :members: + :special-members: __getitem__ LJSPEECH ~~~~~~~~ .. autoclass:: LJSPEECH - :members: __getitem__ - :special-members: + :members: + :special-members: __getitem__ SPEECHCOMMANDS ~~~~~~~~~~~~~~ .. autoclass:: SPEECHCOMMANDS - :members: __getitem__ - :special-members: + :members: + :special-members: __getitem__ TEDLIUM ~~~~~~~~~~~~~~ .. autoclass:: TEDLIUM - :members: __getitem__ - :special-members: get_phoneme_dict + :members: + :special-members: __getitem__ + VCTK ~~~~ .. autoclass:: VCTK - :members: __getitem__ - :special-members: + :members: + :special-members: __getitem__ VCTK_092 ~~~~~~~~ .. autoclass:: VCTK_092 + :members: + :special-members: __getitem__ YESNO ~~~~~ .. autoclass:: YESNO - :members: __getitem__ - :special-members: + :members: + :special-members: __getitem__ diff --git a/docs/source/index.rst b/docs/source/index.rst index 8146e545c3..596a636b1b 100644 --- a/docs/source/index.rst +++ b/docs/source/index.rst @@ -1,5 +1,27 @@ torchaudio ========== +This library is part of the `PyTorch +`_ project. PyTorch is an open source +machine learning framework. + +Features described in this documentation are classified by release status: + + *Stable:* These features will be maintained long-term and there should generally + be no major performance limitations or gaps in documentation. + We also expect to maintain backwards compatibility (although + breaking changes can happen and notice will be given one release ahead + of time). + + *Beta:* Features are tagged as Beta because the API may change based on + user feedback, because the performance needs to improve, or because + coverage across operators is not yet complete. For Beta features, we are + committing to seeing the feature through to the Stable classification. + We are not, however, committing to backwards compatibility. + + *Prototype:* These features are typically not available as part of + binary distributions like PyPI or Conda, except sometimes behind run-time + flags, and are at an early stage for feedback and testing. + The :mod:`torchaudio` package consists of I/O, popular datasets and common audio transformations. @@ -17,3 +39,16 @@ The :mod:`torchaudio` package consists of I/O, popular datasets and common audio compliance.kaldi kaldi_io utils + + +.. toctree:: + :maxdepth: 1 + :caption: PyTorch Libraries + + PyTorch + torchaudio + torchtext + torchvision + TorchElastic + TorchServe + PyTorch on XLA Devices diff --git a/docs/source/models.rst b/docs/source/models.rst index 44eb74444a..ea86d8b73b 100644 --- a/docs/source/models.rst +++ b/docs/source/models.rst @@ -9,6 +9,14 @@ torchaudio.models The models subpackage contains definitions of models for addressing common audio tasks. +:hidden:`ConvTasNet` +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +.. autoclass:: ConvTasNet + + .. automethod:: forward + + :hidden:`Wav2Letter` ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ diff --git a/docs/source/sox_effects.rst b/docs/source/sox_effects.rst index 0aa34e7908..6eee11d8c7 100644 --- a/docs/source/sox_effects.rst +++ b/docs/source/sox_effects.rst @@ -5,10 +5,6 @@ torchaudio.sox_effects .. currentmodule:: torchaudio.sox_effects -.. warning:: - - The :py:class:`SoxEffect` and :py:class:`SoxEffectsChain` classes are deprecated. Please migrate to :func:`apply_effects_tensor` and :func:`apply_effects_file`. - Resource initialization / shutdown ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ @@ -35,18 +31,3 @@ Applying effects on file ------------------------ .. autofunction:: apply_effects_file - -Legacy -~~~~~~ - -SoxEffect ---------- - -.. autoclass:: SoxEffect - :members: - -SoxEffectsChain ---------------- - -.. autoclass:: SoxEffectsChain - :members: append_effect_to_chain, sox_build_flow_effects, clear_chain, set_input_file diff --git a/examples/pipeline_wav2letter/README.md b/examples/pipeline_wav2letter/README.md new file mode 100644 index 0000000000..8117d19c91 --- /dev/null +++ b/examples/pipeline_wav2letter/README.md @@ -0,0 +1,45 @@ +This is an example pipeline for speech recognition using a greedy or Viterbi CTC decoder, along with the Wav2Letter model trained on LibriSpeech, see [Wav2Letter: an End-to-End ConvNet-based Speech Recognition System](https://arxiv.org/pdf/1609.03193.pdf). Wav2Letter and LibriSpeech are available in torchaudio. + +### Usage + +More information about each command line parameters is available with the `--help` option. An example can be invoked as follows. +``` +python main.py \ + --reduce-lr-valid \ + --dataset-train train-clean-100 train-clean-360 train-other-500 \ + --dataset-valid dev-clean \ + --batch-size 128 \ + --learning-rate .6 \ + --momentum .8 \ + --weight-decay .00001 \ + --clip-grad 0. \ + --gamma .99 \ + --hop-length 160 \ + --n-hidden-channels 2000 \ + --win-length 400 \ + --n-bins 13 \ + --normalize \ + --optimizer adadelta \ + --scheduler reduceonplateau \ + --epochs 30 +``` +With these default parameters, we get a character error rate of 13.8% on dev-clean after 30 epochs. + +### Output + +The information reported at each iteration and epoch (e.g. loss, character error rate, word error rate) is printed to standard output in the form of one json per line, e.g. +```python +{"name": "train", "epoch": 0, "cer over target length": 1.0, "cumulative cer": 23317.0, "total chars": 23317.0, "cer": 0.0, "cumulative cer over target length": 0.0, "wer over target length": 1.0, "cumulative wer": 4446.0, "total words": 4446.0, "wer": 0.0, "cumulative wer over target length": 0.0, "lr": 0.6, "batch size": 128, "n_channel": 13, "n_time": 2453, "dataset length": 128.0, "iteration": 1.0, "loss": 8.712121963500977, "cumulative loss": 8.712121963500977, "average loss": 8.712121963500977, "iteration time": 41.46276903152466, "epoch time": 41.46276903152466} +{"name": "train", "epoch": 0, "cer over target length": 1.0, "cumulative cer": 46005.0, "total chars": 46005.0, "cer": 0.0, "cumulative cer over target length": 0.0, "wer over target length": 1.0, "cumulative wer": 8762.0, "total words": 8762.0, "wer": 0.0, "cumulative wer over target length": 0.0, "lr": 0.6, "batch size": 128, "n_channel": 13, "n_time": 1703, "dataset length": 256.0, "iteration": 2.0, "loss": 8.918599128723145, "cumulative loss": 17.63072109222412, "average loss": 8.81536054611206, "iteration time": 1.2905676364898682, "epoch time": 42.753336668014526} +{"name": "train", "epoch": 0, "cer over target length": 1.0, "cumulative cer": 70030.0, "total chars": 70030.0, "cer": 0.0, "cumulative cer over target length": 0.0, "wer over target length": 1.0, "cumulative wer": 13348.0, "total words": 13348.0, "wer": 0.0, "cumulative wer over target length": 0.0, "lr": 0.6, "batch size": 128, "n_channel": 13, "n_time": 1713, "dataset length": 384.0, "iteration": 3.0, "loss": 8.550191879272461, "cumulative loss": 26.180912971496582, "average loss": 8.726970990498861, "iteration time": 1.2109291553497314, "epoch time": 43.96426582336426} +``` +One way to import the output in python with pandas is by saving the standard output to a file, and then using `pandas.read_json(filename, lines=True)`. + +## Structure of pipeline + +* `main.py` -- the entry point +* `ctc_decoders.py` -- the greedy CTC decoder +* `datasets.py` -- the function to split and process librispeech, a collate factory function +* `languagemodels.py` -- a class to encode and decode strings +* `metrics.py` -- the levenshtein edit distance +* `utils.py` -- functions to log metrics, save checkpoint, and count parameters diff --git a/examples/pipeline_wav2letter/ctc_decoders.py b/examples/pipeline_wav2letter/ctc_decoders.py new file mode 100644 index 0000000000..b4f155d6fa --- /dev/null +++ b/examples/pipeline_wav2letter/ctc_decoders.py @@ -0,0 +1,15 @@ +from torch import topk + + +class GreedyDecoder: + def __call__(self, outputs): + """Greedy Decoder. Returns highest probability of class labels for each timestep + + Args: + outputs (torch.Tensor): shape (input length, batch size, number of classes (including blank)) + + Returns: + torch.Tensor: class labels per time step. + """ + _, indices = topk(outputs, k=1, dim=-1) + return indices[..., 0] diff --git a/examples/pipeline_wav2letter/datasets.py b/examples/pipeline_wav2letter/datasets.py new file mode 100644 index 0000000000..79b05b2c5b --- /dev/null +++ b/examples/pipeline_wav2letter/datasets.py @@ -0,0 +1,113 @@ +import torch +from torchaudio.datasets import LIBRISPEECH + + +class MapMemoryCache(torch.utils.data.Dataset): + """ + Wrap a dataset so that, whenever a new item is returned, it is saved to memory. + """ + + def __init__(self, dataset): + self.dataset = dataset + self._cache = [None] * len(dataset) + + def __getitem__(self, n): + if self._cache[n] is not None: + return self._cache[n] + + item = self.dataset[n] + self._cache[n] = item + + return item + + def __len__(self): + return len(self.dataset) + + +class Processed(torch.utils.data.Dataset): + def __init__(self, dataset, transforms, encode): + self.dataset = dataset + self.transforms = transforms + self.encode = encode + + def __getitem__(self, key): + item = self.dataset[key] + return self.process_datapoint(item) + + def __len__(self): + return len(self.dataset) + + def process_datapoint(self, item): + transformed = item[0] + target = item[2].lower() + + transformed = self.transforms(transformed) + transformed = transformed[0, ...].transpose(0, -1) + + target = self.encode(target) + target = torch.tensor(target, dtype=torch.long, device=transformed.device) + + return transformed, target + + +def split_process_librispeech( + datasets, transforms, language_model, root, folder_in_archive, +): + def create(tags, cache=True): + + if isinstance(tags, str): + tags = [tags] + if isinstance(transforms, list): + transform_list = transforms + else: + transform_list = [transforms] + + data = torch.utils.data.ConcatDataset( + [ + Processed( + LIBRISPEECH( + root, tag, folder_in_archive=folder_in_archive, download=False, + ), + transform, + language_model.encode, + ) + for tag, transform in zip(tags, transform_list) + ] + ) + + data = MapMemoryCache(data) + return data + + # For performance, we cache all datasets + return tuple(create(dataset) for dataset in datasets) + + +def collate_factory(model_length_function, transforms=None): + + if transforms is None: + transforms = torch.nn.Sequential() + + def collate_fn(batch): + + tensors = [transforms(b[0]) for b in batch if b] + + tensors_lengths = torch.tensor( + [model_length_function(t) for t in tensors], + dtype=torch.long, + device=tensors[0].device, + ) + + tensors = torch.nn.utils.rnn.pad_sequence(tensors, batch_first=True) + tensors = tensors.transpose(1, -1) + + targets = [b[1] for b in batch if b] + target_lengths = torch.tensor( + [target.shape[0] for target in targets], + dtype=torch.long, + device=tensors.device, + ) + targets = torch.nn.utils.rnn.pad_sequence(targets, batch_first=True) + + return tensors, targets, tensors_lengths, target_lengths + + return collate_fn diff --git a/examples/pipeline_wav2letter/languagemodels.py b/examples/pipeline_wav2letter/languagemodels.py new file mode 100644 index 0000000000..eee018ae69 --- /dev/null +++ b/examples/pipeline_wav2letter/languagemodels.py @@ -0,0 +1,38 @@ +import collections +import itertools + + +class LanguageModel: + def __init__(self, labels, char_blank, char_space): + + self.char_space = char_space + self.char_blank = char_blank + + labels = [l for l in labels] + self.length = len(labels) + enumerated = list(enumerate(labels)) + flipped = [(sub[1], sub[0]) for sub in enumerated] + + d1 = collections.OrderedDict(enumerated) + d2 = collections.OrderedDict(flipped) + self.mapping = {**d1, **d2} + + def encode(self, iterable): + if isinstance(iterable, list): + return [self.encode(i) for i in iterable] + else: + return [self.mapping[i] + self.mapping[self.char_blank] for i in iterable] + + def decode(self, tensor): + if len(tensor) > 0 and isinstance(tensor[0], list): + return [self.decode(t) for t in tensor] + else: + # not idempotent, since clean string + x = (self.mapping[i] for i in tensor) + x = "".join(i for i, _ in itertools.groupby(x)) + x = x.replace(self.char_blank, "") + # x = x.strip() + return x + + def __len__(self): + return self.length diff --git a/examples/pipeline_wav2letter/main.py b/examples/pipeline_wav2letter/main.py new file mode 100644 index 0000000000..8f52ec6c3c --- /dev/null +++ b/examples/pipeline_wav2letter/main.py @@ -0,0 +1,668 @@ +import argparse +import logging +import os +import string +from datetime import datetime +from time import time + +import torch +import torchaudio +from torch.optim import SGD, Adadelta, Adam, AdamW +from torch.optim.lr_scheduler import ExponentialLR, ReduceLROnPlateau +from torch.utils.data import DataLoader +from torchaudio.datasets.utils import bg_iterator +from torchaudio.models.wav2letter import Wav2Letter + +from ctc_decoders import GreedyDecoder +from datasets import collate_factory, split_process_librispeech +from languagemodels import LanguageModel +from metrics import levenshtein_distance +from transforms import Normalize, UnsqueezeFirst +from utils import MetricLogger, count_parameters, save_checkpoint + + +def parse_args(): + parser = argparse.ArgumentParser() + + parser.add_argument( + "--type", + metavar="T", + default="mfcc", + choices=["waveform", "mfcc"], + help="input type for model", + ) + parser.add_argument( + "--freq-mask", + default=0, + type=int, + metavar="N", + help="maximal width of frequency mask", + ) + parser.add_argument( + "--win-length", + default=400, + type=int, + metavar="N", + help="width of spectrogram window", + ) + parser.add_argument( + "--hop-length", + default=160, + type=int, + metavar="N", + help="width of spectrogram window", + ) + parser.add_argument( + "--time-mask", + default=0, + type=int, + metavar="N", + help="maximal width of time mask", + ) + parser.add_argument( + "--workers", + default=0, + type=int, + metavar="N", + help="number of data loading workers", + ) + parser.add_argument( + "--checkpoint", + default="", + type=str, + metavar="PATH", + help="path to latest checkpoint", + ) + parser.add_argument( + "--epochs", + default=200, + type=int, + metavar="N", + help="number of total epochs to run", + ) + parser.add_argument( + "--start-epoch", default=0, type=int, metavar="N", help="manual epoch number" + ) + parser.add_argument( + "--print-freq", + default=10, + type=int, + metavar="N", + help="print frequency in epochs", + ) + parser.add_argument( + "--reduce-lr-valid", + action="store_true", + help="reduce learning rate based on validation loss", + ) + parser.add_argument( + "--normalize", action="store_true", help="normalize model input" + ) + parser.add_argument( + "--progress-bar", action="store_true", help="use progress bar while training" + ) + parser.add_argument( + "--decoder", + metavar="D", + default="greedy", + choices=["greedy"], + help="decoder to use", + ) + parser.add_argument( + "--batch-size", default=128, type=int, metavar="N", help="mini-batch size" + ) + parser.add_argument( + "--n-bins", + default=13, + type=int, + metavar="N", + help="number of bins in transforms", + ) + parser.add_argument( + "--optimizer", + metavar="OPT", + default="adadelta", + choices=["sgd", "adadelta", "adam", "adamw"], + help="optimizer to use", + ) + parser.add_argument( + "--scheduler", + metavar="S", + default="reduceonplateau", + choices=["exponential", "reduceonplateau"], + help="optimizer to use", + ) + parser.add_argument( + "--learning-rate", + default=0.6, + type=float, + metavar="LR", + help="initial learning rate", + ) + parser.add_argument( + "--gamma", + default=0.99, + type=float, + metavar="GAMMA", + help="learning rate exponential decay constant", + ) + parser.add_argument( + "--momentum", default=0.8, type=float, metavar="M", help="momentum" + ) + parser.add_argument( + "--weight-decay", default=1e-5, type=float, metavar="W", help="weight decay" + ) + parser.add_argument("--eps", metavar="EPS", type=float, default=1e-8) + parser.add_argument("--rho", metavar="RHO", type=float, default=0.95) + parser.add_argument("--clip-grad", metavar="NORM", type=float, default=0.0) + parser.add_argument( + "--dataset-root", + type=str, + help="specify dataset root folder", + ) + parser.add_argument( + "--dataset-folder-in-archive", + type=str, + help="specify dataset folder in archive", + ) + parser.add_argument( + "--dataset-train", + default=["train-clean-100"], + nargs="+", + type=str, + help="select which part of librispeech to train with", + ) + parser.add_argument( + "--dataset-valid", + default=["dev-clean"], + nargs="+", + type=str, + help="select which part of librispeech to validate with", + ) + parser.add_argument( + "--distributed", action="store_true", help="enable DistributedDataParallel" + ) + parser.add_argument("--seed", type=int, default=0, help="random seed") + parser.add_argument( + "--world-size", type=int, default=8, help="the world size to initiate DPP" + ) + parser.add_argument("--jit", action="store_true", help="if used, model is jitted") + + args = parser.parse_args() + logging.info(args) + return args + + +def setup_distributed(rank, world_size): + os.environ["MASTER_ADDR"] = "localhost" + os.environ["MASTER_PORT"] = "12355" + + # initialize the process group + torch.distributed.init_process_group("nccl", rank=rank, world_size=world_size) + + +def model_length_function(tensor): + if tensor.shape[1] == 1: + # waveform mode + return int(tensor.shape[0]) // 160 // 2 + 1 + return int(tensor.shape[0]) // 2 + 1 + + +def compute_error_rates(outputs, targets, decoder, language_model, metric): + output = outputs.transpose(0, 1).to("cpu") + output = decoder(output) + + # Compute CER + + output = language_model.decode(output.tolist()) + target = language_model.decode(targets.tolist()) + + print_length = 20 + for i in range(2): + # Print a few examples + output_print = output[i].ljust(print_length)[:print_length] + target_print = target[i].ljust(print_length)[:print_length] + logging.info("Target: %s Output: %s", target_print, output_print) + + cers = [levenshtein_distance(t, o) for t, o in zip(target, output)] + cers = sum(cers) + n = sum(len(t) for t in target) + metric["cer over target length"] = cers / n + metric["cumulative cer"] += cers + metric["total chars"] += n + metric["cumulative cer over target length"] = metric["cer"] / metric["total chars"] + + # Compute WER + + output = [o.split(language_model.char_space) for o in output] + target = [t.split(language_model.char_space) for t in target] + + wers = [levenshtein_distance(t, o) for t, o in zip(target, output)] + wers = sum(wers) + n = sum(len(t) for t in target) + metric["wer over target length"] = wers / n + metric["cumulative wer"] += wers + metric["total words"] += n + metric["cumulative wer over target length"] = metric["wer"] / metric["total words"] + + +def train_one_epoch( + model, + criterion, + optimizer, + scheduler, + data_loader, + decoder, + language_model, + device, + epoch, + clip_grad, + disable_logger=False, + reduce_lr_on_plateau=False, +): + + model.train() + + metric = MetricLogger("train", disable=disable_logger) + metric["epoch"] = epoch + + for inputs, targets, tensors_lengths, target_lengths in bg_iterator( + data_loader, maxsize=2 + ): + + start = time() + inputs = inputs.to(device, non_blocking=True) + targets = targets.to(device, non_blocking=True) + + # keep batch first for data parallel + outputs = model(inputs).transpose(-1, -2).transpose(0, 1) + + # CTC + # outputs: input length, batch size, number of classes (including blank) + # targets: batch size, max target length + # input_lengths: batch size + # target_lengths: batch size + + loss = criterion(outputs, targets, tensors_lengths, target_lengths) + + optimizer.zero_grad() + loss.backward() + + if clip_grad > 0: + metric["gradient"] = torch.nn.utils.clip_grad_norm_( + model.parameters(), clip_grad + ) + + optimizer.step() + + compute_error_rates(outputs, targets, decoder, language_model, metric) + + try: + metric["lr"] = scheduler.get_last_lr()[0] + except AttributeError: + metric["lr"] = optimizer.param_groups[0]["lr"] + + metric["batch size"] = len(inputs) + metric["n_channel"] = inputs.shape[1] + metric["n_time"] = inputs.shape[-1] + metric["dataset length"] += metric["batch size"] + metric["iteration"] += 1 + metric["loss"] = loss.item() + metric["cumulative loss"] += metric["loss"] + metric["average loss"] = metric["cumulative loss"] / metric["iteration"] + metric["iteration time"] = time() - start + metric["epoch time"] += metric["iteration time"] + metric() + + if reduce_lr_on_plateau and isinstance(scheduler, ReduceLROnPlateau): + scheduler.step(metric["average loss"]) + elif not isinstance(scheduler, ReduceLROnPlateau): + scheduler.step() + + +def evaluate( + model, + criterion, + data_loader, + decoder, + language_model, + device, + epoch, + disable_logger=False, +): + + with torch.no_grad(): + + model.eval() + start = time() + metric = MetricLogger("validation", disable=disable_logger) + metric["epoch"] = epoch + + for inputs, targets, tensors_lengths, target_lengths in bg_iterator( + data_loader, maxsize=2 + ): + + inputs = inputs.to(device, non_blocking=True) + targets = targets.to(device, non_blocking=True) + + # keep batch first for data parallel + outputs = model(inputs).transpose(-1, -2).transpose(0, 1) + + # CTC + # outputs: input length, batch size, number of classes (including blank) + # targets: batch size, max target length + # input_lengths: batch size + # target_lengths: batch size + + metric["cumulative loss"] += criterion( + outputs, targets, tensors_lengths, target_lengths + ).item() + + metric["dataset length"] += len(inputs) + metric["iteration"] += 1 + + compute_error_rates(outputs, targets, decoder, language_model, metric) + + metric["average loss"] = metric["cumulative loss"] / metric["iteration"] + metric["validation time"] = time() - start + metric() + + return metric["average loss"] + + +def main(rank, args): + + # Distributed setup + + if args.distributed: + setup_distributed(rank, args.world_size) + + not_main_rank = args.distributed and rank != 0 + + logging.info("Start time: %s", datetime.now()) + + # Explicitly set seed to make sure models created in separate processes + # start from same random weights and biases + torch.manual_seed(args.seed) + + # Empty CUDA cache + torch.cuda.empty_cache() + + # Change backend for flac files + torchaudio.set_audio_backend("soundfile") + + # Transforms + + melkwargs = { + "n_fft": args.win_length, + "n_mels": args.n_bins, + "hop_length": args.hop_length, + } + + sample_rate_original = 16000 + + if args.type == "mfcc": + transforms = torch.nn.Sequential( + torchaudio.transforms.MFCC( + sample_rate=sample_rate_original, + n_mfcc=args.n_bins, + melkwargs=melkwargs, + ), + ) + num_features = args.n_bins + elif args.type == "waveform": + transforms = torch.nn.Sequential(UnsqueezeFirst()) + num_features = 1 + else: + raise ValueError("Model type not supported") + + if args.normalize: + transforms = torch.nn.Sequential(transforms, Normalize()) + + augmentations = torch.nn.Sequential() + if args.freq_mask: + augmentations = torch.nn.Sequential( + augmentations, + torchaudio.transforms.FrequencyMasking(freq_mask_param=args.freq_mask), + ) + if args.time_mask: + augmentations = torch.nn.Sequential( + augmentations, + torchaudio.transforms.TimeMasking(time_mask_param=args.time_mask), + ) + + # Text preprocessing + + char_blank = "*" + char_space = " " + char_apostrophe = "'" + labels = char_blank + char_space + char_apostrophe + string.ascii_lowercase + language_model = LanguageModel(labels, char_blank, char_space) + + # Dataset + + training, validation = split_process_librispeech( + [args.dataset_train, args.dataset_valid], + [transforms, transforms], + language_model, + root=args.dataset_root, + folder_in_archive=args.dataset_folder_in_archive, + ) + + # Decoder + + if args.decoder == "greedy": + decoder = GreedyDecoder() + else: + raise ValueError("Selected decoder not supported") + + # Model + + model = Wav2Letter( + num_classes=language_model.length, + input_type=args.type, + num_features=num_features, + ) + + if args.jit: + model = torch.jit.script(model) + + if args.distributed: + n = torch.cuda.device_count() // args.world_size + devices = list(range(rank * n, (rank + 1) * n)) + model = model.to(devices[0]) + model = torch.nn.parallel.DistributedDataParallel(model, device_ids=devices) + else: + devices = ["cuda" if torch.cuda.is_available() else "cpu"] + model = model.to(devices[0], non_blocking=True) + model = torch.nn.DataParallel(model) + + n = count_parameters(model) + logging.info("Number of parameters: %s", n) + + # Optimizer + + if args.optimizer == "adadelta": + optimizer = Adadelta( + model.parameters(), + lr=args.learning_rate, + weight_decay=args.weight_decay, + eps=args.eps, + rho=args.rho, + ) + elif args.optimizer == "sgd": + optimizer = SGD( + model.parameters(), + lr=args.learning_rate, + momentum=args.momentum, + weight_decay=args.weight_decay, + ) + elif args.optimizer == "adam": + optimizer = Adam( + model.parameters(), + lr=args.learning_rate, + momentum=args.momentum, + weight_decay=args.weight_decay, + ) + elif args.optimizer == "adamw": + optimizer = AdamW( + model.parameters(), + lr=args.learning_rate, + momentum=args.momentum, + weight_decay=args.weight_decay, + ) + else: + raise ValueError("Selected optimizer not supported") + + if args.scheduler == "exponential": + scheduler = ExponentialLR(optimizer, gamma=args.gamma) + elif args.scheduler == "reduceonplateau": + scheduler = ReduceLROnPlateau(optimizer, patience=10, threshold=1e-3) + else: + raise ValueError("Selected scheduler not supported") + + criterion = torch.nn.CTCLoss( + blank=language_model.mapping[char_blank], zero_infinity=False + ) + + # Data Loader + + collate_fn_train = collate_factory(model_length_function, augmentations) + collate_fn_valid = collate_factory(model_length_function) + + loader_training_params = { + "num_workers": args.workers, + "pin_memory": True, + "shuffle": True, + "drop_last": True, + } + loader_validation_params = loader_training_params.copy() + loader_validation_params["shuffle"] = False + + loader_training = DataLoader( + training, + batch_size=args.batch_size, + collate_fn=collate_fn_train, + **loader_training_params, + ) + loader_validation = DataLoader( + validation, + batch_size=args.batch_size, + collate_fn=collate_fn_valid, + **loader_validation_params, + ) + + # Setup checkpoint + + best_loss = 1.0 + + load_checkpoint = args.checkpoint and os.path.isfile(args.checkpoint) + + if args.distributed: + torch.distributed.barrier() + + if load_checkpoint: + logging.info("Checkpoint: loading %s", args.checkpoint) + checkpoint = torch.load(args.checkpoint) + + args.start_epoch = checkpoint["epoch"] + best_loss = checkpoint["best_loss"] + + model.load_state_dict(checkpoint["state_dict"]) + optimizer.load_state_dict(checkpoint["optimizer"]) + scheduler.load_state_dict(checkpoint["scheduler"]) + + logging.info( + "Checkpoint: loaded '%s' at epoch %s", args.checkpoint, checkpoint["epoch"] + ) + else: + logging.info("Checkpoint: not found") + + save_checkpoint( + { + "epoch": args.start_epoch, + "state_dict": model.state_dict(), + "best_loss": best_loss, + "optimizer": optimizer.state_dict(), + "scheduler": scheduler.state_dict(), + }, + False, + args.checkpoint, + not_main_rank, + ) + + if args.distributed: + torch.distributed.barrier() + + torch.autograd.set_detect_anomaly(False) + + for epoch in range(args.start_epoch, args.epochs): + + logging.info("Epoch: %s", epoch) + + train_one_epoch( + model, + criterion, + optimizer, + scheduler, + loader_training, + decoder, + language_model, + devices[0], + epoch, + args.clip_grad, + not_main_rank, + not args.reduce_lr_valid, + ) + + if not (epoch + 1) % args.print_freq or epoch == args.epochs - 1: + + loss = evaluate( + model, + criterion, + loader_validation, + decoder, + language_model, + devices[0], + epoch, + not_main_rank, + ) + + is_best = loss < best_loss + best_loss = min(loss, best_loss) + save_checkpoint( + { + "epoch": epoch + 1, + "state_dict": model.state_dict(), + "best_loss": best_loss, + "optimizer": optimizer.state_dict(), + "scheduler": scheduler.state_dict(), + }, + is_best, + args.checkpoint, + not_main_rank, + ) + + if args.reduce_lr_valid and isinstance(scheduler, ReduceLROnPlateau): + scheduler.step(loss) + + logging.info("End time: %s", datetime.now()) + + if args.distributed: + torch.distributed.destroy_process_group() + + +def spawn_main(main, args): + if args.distributed: + torch.multiprocessing.spawn( + main, args=(args,), nprocs=args.world_size, join=True + ) + else: + main(0, args) + + +if __name__ == "__main__": + + logging.basicConfig(level=logging.INFO) + args = parse_args() + spawn_main(main, args) diff --git a/examples/pipeline_wav2letter/metrics.py b/examples/pipeline_wav2letter/metrics.py new file mode 100644 index 0000000000..cba6595016 --- /dev/null +++ b/examples/pipeline_wav2letter/metrics.py @@ -0,0 +1,38 @@ +from typing import List, Union + + +def levenshtein_distance(r: Union[str, List[str]], h: Union[str, List[str]]): + """ + Calculate the Levenshtein distance between two lists or strings. + """ + + # Initialisation + dold = list(range(len(h) + 1)) + dnew = list(0 for _ in range(len(h) + 1)) + + # Computation + for i in range(1, len(r) + 1): + dnew[0] = i + for j in range(1, len(h) + 1): + if r[i - 1] == h[j - 1]: + dnew[j] = dold[j - 1] + else: + substitution = dold[j - 1] + 1 + insertion = dnew[j - 1] + 1 + deletion = dold[j] + 1 + dnew[j] = min(substitution, insertion, deletion) + + dnew, dold = dold, dnew + + return dold[-1] + + +if __name__ == "__main__": + assert levenshtein_distance("abc", "abc") == 0 + assert levenshtein_distance("aaa", "aba") == 1 + assert levenshtein_distance("aba", "aaa") == 1 + assert levenshtein_distance("aa", "aaa") == 1 + assert levenshtein_distance("aaa", "aa") == 1 + assert levenshtein_distance("abc", "bcd") == 2 + assert levenshtein_distance(["hello", "world"], ["hello", "world", "!"]) == 1 + assert levenshtein_distance(["hello", "world"], ["world", "hello", "!"]) == 2 diff --git a/examples/pipeline_wav2letter/transforms.py b/examples/pipeline_wav2letter/transforms.py new file mode 100644 index 0000000000..f1d9115c87 --- /dev/null +++ b/examples/pipeline_wav2letter/transforms.py @@ -0,0 +1,11 @@ +import torch + + +class Normalize(torch.nn.Module): + def forward(self, tensor): + return (tensor - tensor.mean(-1, keepdim=True)) / tensor.std(-1, keepdim=True) + + +class UnsqueezeFirst(torch.nn.Module): + def forward(self, tensor): + return tensor.unsqueeze(0) diff --git a/examples/pipeline_wav2letter/utils.py b/examples/pipeline_wav2letter/utils.py new file mode 100644 index 0000000000..7cd07a2a80 --- /dev/null +++ b/examples/pipeline_wav2letter/utils.py @@ -0,0 +1,55 @@ +import json +import logging +import os +import shutil +from collections import defaultdict + +import torch + + +class MetricLogger(defaultdict): + def __init__(self, name, print_freq=1, disable=False): + super().__init__(lambda: 0.0) + self.disable = disable + self.print_freq = print_freq + self._iter = 0 + self["name"] = name + + def __str__(self): + return json.dumps(self) + + def __call__(self): + self._iter = (self._iter + 1) % self.print_freq + if not self.disable and not self._iter: + print(self, flush=True) + + +def save_checkpoint(state, is_best, filename, disable): + """ + Save the model to a temporary file first, + then copy it to filename, in case the signal interrupts + the torch.save() process. + """ + + if disable: + return + + if filename == "": + return + + tempfile = filename + ".temp" + + # Remove tempfile in case interuption during the copying from tempfile to filename + if os.path.isfile(tempfile): + os.remove(tempfile) + + torch.save(state, tempfile) + if os.path.isfile(tempfile): + os.rename(tempfile, filename) + if is_best: + shutil.copyfile(filename, "model_best.pth.tar") + logging.warning("Checkpoint: saved") + + +def count_parameters(model): + return sum(p.numel() for p in model.parameters() if p.requires_grad) diff --git a/examples/source_separation/README.md b/examples/source_separation/README.md new file mode 100644 index 0000000000..eeeac93d16 --- /dev/null +++ b/examples/source_separation/README.md @@ -0,0 +1,168 @@ +# Source Separation Example + +This directory contains reference implementations for source separations. For the detail of each model, please checkout the followings. + +- [Conv-TasNet](./conv_tasnet/README.md) + +## Usage + +### Overview + +To training a model, you can use [`train.py`](./train.py). This script takes the form of +`train.py [parameters for distributed training] -- [parameters for model/training]` + + ``` + python train.py \ + [--worker-id WORKER_ID] \ + [--device-id DEVICE_ID] \ + [--num-workers NUM_WORKERS] \ + [--sync-protocol SYNC_PROTOCOL] \ + -- \ + + + # For the detail of the parameter values, use; + python train.py --help + + # For the detail of the model parameters, use; + python train.py -- --help + ``` + +If you would like to just try out the traing script, then try it without any parameters +for distributed training. `train.py -- --sample-rate 8000 --batch-size --dataset-dir --save-dir ` + +This script runs training in Distributed Data Parallel (DDP) framework and has two major +operation modes. This behavior depends on if `--worker-id` argument is given or not. + +1. (`--worker-id` is not given) Launchs training worker subprocesses that performs the actual training. +2. (`--worker-id` is given) Performs the training as a part of distributed training. + +When launching the script without any distributed trainig parameters (operation mode 1), +this script will check the number of GPUs available on the local system and spawns the same +number of training subprocesses (as operaiton mode 2). You can reduce the number of GPUs with +`--num-workers`. If there is no GPU available, only one subprocess is launched and providing +`--num-workers` larger than 1 results in error. + +When launching the script as a worker process of a distributed training, you need to configure +the coordination of the workers. + +- `--num-workers` is the number of training processes being launched. +- `--worker-id` is the process rank (must be unique across all the processes). +- `--device-id` is the GPU device ID (should be unique within node). +- `--sync-protocl` is how each worker process communicate and synchronize. + If the training is carried out on a single node, then the default `"env://"` should do. + If the training processes span across multiple nodes, then you need to provide a protocol that + can communicate over the network. If you know where the master node is located, you can use + `"env://"` in combination with `MASTER_ADDR` and `MASER_PORT` environment variables. If you do + not know where the master node is located beforehand, you can use `"file://..."` protocol to + indicate where the file to which all the worker process have access is located. For other + protocols, please refer to the official documentation. + +### Distributed Training Notes + +
Quick overview on DDP (distributed data parallel) + +DDP is single-program multiple-data training paradigm. +With DDP, the model is replicated on every process, +and every model replica will be fed with a different set of input data samples. + +- **Process**: Worker process (as in Linux process). There are `P` processes per a Node. +- **Node**: A machine. There are `N` machines, each of which holds `P` processes. +- **World**: network of nodes, composed of `N` nodes and `N * P` processes. +- **Rank**: Grobal process ID (unique across nodes) `[0, N * P)` +- **Local Rank**: Local process ID (unique only within a node) `[0, P)` + +``` + Node 0 Node 1 Node N-1 +โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ” โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ” +โ”‚โ•”โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•— โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”โ”‚โ”‚โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ” โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”โ”‚ โ”‚โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ” โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”โ”‚ +โ”‚โ•‘ Process โ•Ÿโ”€โ”ค GPU: 0 โ”‚โ”‚โ”‚โ”‚ Process โ”œโ”€โ”ค GPU: 0 โ”‚โ”‚ โ”‚โ”‚ Process โ”œโ”€โ”ค GPU: 0 โ”‚โ”‚ +โ”‚โ•‘ Rank: 0 โ•‘ โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜โ”‚โ”‚โ”‚ Rank:P โ”‚ โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜โ”‚ โ”‚โ”‚ Rank:NP-P โ”‚ โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜โ”‚ +โ”‚โ•šโ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ• โ”‚โ”‚โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜ โ”‚ โ”‚โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜ โ”‚ +โ”‚โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ” โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”โ”‚โ”‚โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ” โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”โ”‚ โ”‚โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ” โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”โ”‚ +โ”‚โ”‚ Process โ”œโ”€โ”ค GPU: 1 โ”‚โ”‚โ”‚โ”‚ Process โ”œโ”€โ”ค GPU: 1 โ”‚โ”‚ โ”‚โ”‚ Process โ”œโ”€โ”ค GPU: 1 โ”‚โ”‚ +โ”‚โ”‚ Rank: 1 โ”‚ โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜โ”‚โ”‚โ”‚ Rank:P+1 โ”‚ โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜โ”‚ โ”‚โ”‚ Rank:NP-P+1 โ”‚ โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜โ”‚ +โ”‚โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜ โ”‚โ”‚โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜ โ”‚ ... โ”‚โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜ โ”‚ +โ”‚ โ”‚โ”‚ โ”‚ โ”‚ โ”‚ +โ”‚ ... โ”‚โ”‚ ... โ”‚ โ”‚ ... โ”‚ +โ”‚ โ”‚โ”‚ โ”‚ โ”‚ โ”‚ +โ”‚โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ” โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”โ”‚โ”‚โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ” โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”โ”‚ โ”‚โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ” โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”โ”‚ +โ”‚โ”‚ Process โ”œโ”€โ”ค GPU:P-1 โ”‚โ”‚โ”‚โ”‚ Process โ”œโ”€โ”ค GPU:P-1 โ”‚โ”‚ โ”‚โ”‚ Process โ”œโ”€โ”ค GPU:P-1 โ”‚โ”‚ +โ”‚โ”‚ Rank:P-1 โ”‚ โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜โ”‚โ”‚โ”‚ Rank:2P-1 โ”‚ โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜โ”‚ โ”‚โ”‚ Rank:NP-1 โ”‚ โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜โ”‚ +โ”‚โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜ โ”‚โ”‚โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜ โ”‚ โ”‚โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜ โ”‚ +โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜ โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜ +``` + +
+ +### SLURM + +When launched as SLURM job, the follwoing environment variables correspond to + +- **SLURM_PROCID*: `--worker-id` (Rank) +- **SLURM_NTASKS** (or legacy **SLURM_NPPROCS**): the number of total processes (`--num-workers` == world size) +- **SLURM_LOCALID**: Local Rank (to be mapped with GPU index*) + +* Even when GPU resource is allocated with `--gpus-per-task=1`, if there are muptiple +tasks allocated on the same node, (thus multiple GPUs of the node are allocated to the job) +each task can see all the GPUs allocated for the tasks. Therefore we need to use +SLURM_LOCALID to tell each task to which GPU it should be using. + +
Example scripts for running the training on SLURM cluster + +- **launch_job.sh** + +```bash +#!/bin/bash + +#SBATCH --job-name=source_separation + +#SBATCH --output=/checkpoint/%u/jobs/%x/%j.out + +#SBATCH --error=/checkpoint/%u/jobs/%x/%j.err + +#SBATCH --nodes=1 + +#SBATCH --ntasks-per-node=8 + +#SBATCH --cpus-per-task=8 + +#SBATCH --mem-per-cpu=16G + +#SBATCH --gpus-per-task=1 + +#srun env +srun wrapper.sh $@ +``` + +- **wrapper.sh** + +```bash +#!/bin/bash +num_speakers=2 +this_dir="$( cd "$( dirname "${BASH_SOURCE[0]}" )" >/dev/null 2>&1 && pwd )" +save_dir="/checkpoint/${USER}/jobs/${SLURM_JOB_NAME}/${SLURM_JOB_ID}" +dataset_dir="/dataset/wsj0-mix/${num_speakers}speakers/wav8k/min" + +if [ "${SLURM_JOB_NUM_NODES}" -gt 1 ]; then + protocol="file:///checkpoint/${USER}/jobs/source_separation/${SLURM_JOB_ID}/sync" +else + protocol="env://" +fi + +mkdir -p "${save_dir}" + +python -u \ + "${this_dir}/train.py" \ + --worker-id "${SLURM_PROCID}" \ + --num-workers "${SLURM_NTASKS}" \ + --device-id "${SLURM_LOCALID}" \ + --sync-protocol "${protocol}" \ + -- \ + --num-speakers "${num_speakers}" \ + --sample-rate 8000 \ + --dataset-dir "${dataset_dir}" \ + --save-dir "${save_dir}" \ + --batch-size $((16 / SLURM_NTASKS)) +``` + +
diff --git a/examples/source_separation/conv_tasnet/README.md b/examples/source_separation/conv_tasnet/README.md new file mode 100644 index 0000000000..fd401a6b60 --- /dev/null +++ b/examples/source_separation/conv_tasnet/README.md @@ -0,0 +1,52 @@ +# Conv-TasNet + +This is a reference implementation of Conv-TasNet. + +> Luo, Yi, and Nima Mesgarani. "Conv-TasNet: Surpassing Ideal Time-Frequency Magnitude Masking for Speech Separation." IEEE/ACM Transactions on Audio, Speech, and Language Processing 27.8 (2019): 1256-1266. Crossref. Web. + +This implementation is based on [arXiv:1809.07454v3](https://arxiv.org/abs/1809.07454v3) and [the reference implementation](https://github.com/naplab/Conv-TasNet) provided by the authors. + +For the usage, please checkout the [source separation README](../README.md). + +## (Default) Training Configurations + +The default training/model configurations follow the best non-causal implementation from the paper. (causal configuration is not implemented.) + + - Sample rate: 8000 Hz + - Batch size: total 16 over distributed training workers + - Epochs: 100 + - Initial learning rate: 1e-3 + - Gradient clipping: maximum L2 norm of 5.0 + - Optimizer: Adam + - Learning rate scheduling: Halved after 3 epochs of no improvement in validation accuracy. + - Objective function: SI-SNRi + - Reported metrics: SI-SNRi, SDRi + - Sample audio length: 4 seconds (randomized position) + - Encoder/Decoder feature dimension (N): 512 + - Encoder/Decoder convolution kernel size (L): 16 + - TCN bottleneck/output feature dimension (B): 128 + - TCN hidden feature dimension (H): 512 + - TCN skip connection feature dimension (Sc): 128 + - TCN convolution kernel size (P): 3 + - The number of TCN convolution block layers (X): 8 + - The number of TCN convolution blocks (R): 3 + +## Evaluation + +The following is the evaluation result of training the model on WSJ0-2mix and WSJ0-3mix datasets. + +### wsj0-mix 2speakers + +| | SI-SNRi (dB) | SDRi (dB) | Epoch | +|:------------------:|-------------:|----------:|------:| +| Reference | 15.3 | 15.6 | | +| Validation dataset | 13.1 | 13.1 | 100 | +| Evaluation dataset | 11.0 | 11.0 | 100 | + +### wsj0-mix 3speakers + +| | SI-SNRi (dB) | SDRi (dB) | Epoch | +|:------------------:|-------------:|----------:|------:| +| Reference | 12.7 | 13.1 | | +| Validation dataset | 11.4 | 11.4 | 100 | +| Evaluation dataset | 8.9 | 8.9 | 100 | diff --git a/examples/source_separation/conv_tasnet/__init__.py b/examples/source_separation/conv_tasnet/__init__.py new file mode 100644 index 0000000000..d5818fc320 --- /dev/null +++ b/examples/source_separation/conv_tasnet/__init__.py @@ -0,0 +1,4 @@ +from . import ( + train, + trainer, +) diff --git a/examples/source_separation/conv_tasnet/train.py b/examples/source_separation/conv_tasnet/train.py new file mode 100644 index 0000000000..028f124245 --- /dev/null +++ b/examples/source_separation/conv_tasnet/train.py @@ -0,0 +1,332 @@ +#!/usr/bin/env python3 +"""Train Conv-TasNet""" +import time +import pathlib +import argparse + +import torch +import torchaudio +import torchaudio.models + +import conv_tasnet +from utils import dist_utils +from utils.dataset import utils as dataset_utils + +_LG = dist_utils.getLogger(__name__) + + +def _parse_args(args): + parser = argparse.ArgumentParser(description=__doc__,) + parser.add_argument( + "--debug", + action="store_true", + help="Enable debug behavior. Each epoch will end with just one batch.") + group = parser.add_argument_group("Model Options") + group.add_argument( + "--num-speakers", required=True, type=int, help="The number of speakers." + ) + group = parser.add_argument_group("Dataset Options") + group.add_argument( + "--sample-rate", + required=True, + type=int, + help="Sample rate of audio files in the given dataset.", + ) + group.add_argument( + "--dataset", + default="wsj0mix", + choices=["wsj0mix"], + help='Dataset type. (default: "wsj0mix")', + ) + group.add_argument( + "--dataset-dir", + required=True, + type=pathlib.Path, + help=( + "Directory where dataset is found. " + 'If the dataset type is "wsj9mix", then this is the directory where ' + '"cv", "tt" and "tr" subdirectories are found.' + ), + ) + group = parser.add_argument_group("Save Options") + group.add_argument( + "--save-dir", + required=True, + type=pathlib.Path, + help=( + "Directory where the checkpoints and logs are saved. " + "Though, only the worker 0 saves checkpoint data, " + "all the worker processes must have access to the directory." + ), + ) + group = parser.add_argument_group("Dataloader Options") + group.add_argument( + "--batch-size", + type=int, + help=f"Batch size. (default: 16 // world_size)", + ) + group = parser.add_argument_group("Training Options") + group.add_argument( + "--epochs", + metavar="NUM_EPOCHS", + default=100, + type=int, + help="The number of epochs to train. (default: 100)", + ) + group.add_argument( + "--learning-rate", + default=1e-3, + type=float, + help="Initial learning rate. (default: 1e-3)", + ) + group.add_argument( + "--grad-clip", + metavar="CLIP_VALUE", + default=5.0, + type=float, + help="Gradient clip value (l2 norm). (default: 5.0)", + ) + group.add_argument( + "--resume", + metavar="CHECKPOINT_PATH", + help="Previous checkpoint file from which the training is resumed.", + ) + + args = parser.parse_args(args) + + # Delaing the default value initialization until parse_args is done because + # if `--help` is given, distributed training is not enabled. + if args.batch_size is None: + args.batch_size = 16 // torch.distributed.get_world_size() + + return args + + +def _get_model( + num_sources, + enc_kernel_size=16, + enc_num_feats=512, + msk_kernel_size=3, + msk_num_feats=128, + msk_num_hidden_feats=512, + msk_num_layers=8, + msk_num_stacks=3, +): + model = torchaudio.models.ConvTasNet( + num_sources=num_sources, + enc_kernel_size=enc_kernel_size, + enc_num_feats=enc_num_feats, + msk_kernel_size=msk_kernel_size, + msk_num_feats=msk_num_feats, + msk_num_hidden_feats=msk_num_hidden_feats, + msk_num_layers=msk_num_layers, + msk_num_stacks=msk_num_stacks, + ) + _LG.info_on_master("Model Configuration:") + _LG.info_on_master(" - N: %d", enc_num_feats) + _LG.info_on_master(" - L: %d", enc_kernel_size) + _LG.info_on_master(" - B: %d", msk_num_feats) + _LG.info_on_master(" - H: %d", msk_num_hidden_feats) + _LG.info_on_master(" - Sc: %d", msk_num_feats) + _LG.info_on_master(" - P: %d", msk_kernel_size) + _LG.info_on_master(" - X: %d", msk_num_layers) + _LG.info_on_master(" - R: %d", msk_num_stacks) + _LG.info_on_master( + " - Receptive Field: %s [samples]", model.mask_generator.receptive_field, + ) + return model + + +def _get_dataloader(dataset_type, dataset_dir, num_speakers, sample_rate, batch_size): + train_dataset, valid_dataset, eval_dataset = dataset_utils.get_dataset( + dataset_type, dataset_dir, num_speakers, sample_rate, + ) + train_collate_fn = dataset_utils.get_collate_fn( + dataset_type, mode='train', sample_rate=sample_rate, duration=4 + ) + + test_collate_fn = dataset_utils.get_collate_fn(dataset_type, mode='test') + + train_loader = torch.utils.data.DataLoader( + train_dataset, + batch_size=batch_size, + sampler=torch.utils.data.distributed.DistributedSampler(train_dataset), + collate_fn=train_collate_fn, + pin_memory=True, + ) + valid_loader = torch.utils.data.DataLoader( + valid_dataset, + batch_size=batch_size, + sampler=torch.utils.data.distributed.DistributedSampler(valid_dataset), + collate_fn=test_collate_fn, + pin_memory=True, + ) + eval_loader = torch.utils.data.DataLoader( + eval_dataset, + batch_size=batch_size, + sampler=torch.utils.data.distributed.DistributedSampler(eval_dataset), + collate_fn=test_collate_fn, + pin_memory=True, + ) + return train_loader, valid_loader, eval_loader + + +def _write_header(log_path, args): + rows = [ + [f"# torch: {torch.__version__}", ], + [f"# torchaudio: {torchaudio.__version__}", ] + ] + rows.append(["# arguments"]) + for key, item in vars(args).items(): + rows.append([f"# {key}: {item}"]) + + dist_utils.write_csv_on_master(log_path, *rows) + + +def train(args): + args = _parse_args(args) + _LG.info("%s", args) + + args.save_dir.mkdir(parents=True, exist_ok=True) + if "sox_io" in torchaudio.list_audio_backends(): + torchaudio.set_audio_backend("sox_io") + + start_epoch = 1 + if args.resume: + checkpoint = torch.load(args.resume) + if args.sample_rate != checkpoint["sample_rate"]: + raise ValueError( + "The provided sample rate ({args.sample_rate}) does not match " + "the sample rate from the check point ({checkpoint['sample_rate']})." + ) + if args.num_speakers != checkpoint["num_speakers"]: + raise ValueError( + "The provided #of speakers ({args.num_speakers}) does not match " + "the #of speakers from the check point ({checkpoint['num_speakers']}.)" + ) + start_epoch = checkpoint["epoch"] + + device = torch.device("cuda" if torch.cuda.is_available() else "cpu") + _LG.info("Using: %s", device) + + model = _get_model(num_sources=args.num_speakers) + model.to(device) + + model = torch.nn.parallel.DistributedDataParallel( + model, device_ids=[device] if torch.cuda.is_available() else None + ) + optimizer = torch.optim.Adam(model.parameters(), lr=args.learning_rate) + + if args.resume: + _LG.info("Loading parameters from the checkpoint...") + model.module.load_state_dict(checkpoint["model"]) + optimizer.load_state_dict(checkpoint["optimizer"]) + else: + dist_utils.synchronize_params( + str(args.save_dir / f"tmp.pt"), device, model, optimizer + ) + + lr_scheduler = torch.optim.lr_scheduler.ReduceLROnPlateau( + optimizer, mode="max", factor=0.5, patience=3 + ) + + train_loader, valid_loader, eval_loader = _get_dataloader( + args.dataset, + args.dataset_dir, + args.num_speakers, + args.sample_rate, + args.batch_size, + ) + + num_train_samples = len(train_loader.dataset) + num_valid_samples = len(valid_loader.dataset) + num_eval_samples = len(eval_loader.dataset) + + _LG.info_on_master("Datasets:") + _LG.info_on_master(" - Train: %s", num_train_samples) + _LG.info_on_master(" - Valid: %s", num_valid_samples) + _LG.info_on_master(" - Eval: %s", num_eval_samples) + + trainer = conv_tasnet.trainer.Trainer( + model, + optimizer, + train_loader, + valid_loader, + eval_loader, + args.grad_clip, + device, + debug=args.debug, + ) + + log_path = args.save_dir / f"log.csv" + _write_header(log_path, args) + dist_utils.write_csv_on_master( + log_path, + [ + "epoch", + "learning_rate", + "valid_si_snri", + "valid_sdri", + "eval_si_snri", + "eval_sdri", + ], + ) + + _LG.info_on_master("Running %s epochs", args.epochs) + for epoch in range(start_epoch, start_epoch + args.epochs): + _LG.info_on_master("=" * 70) + _LG.info_on_master("Epoch: %s", epoch) + _LG.info_on_master("Learning rate: %s", optimizer.param_groups[0]["lr"]) + _LG.info_on_master("=" * 70) + + t0 = time.monotonic() + trainer.train_one_epoch() + train_sps = num_train_samples / (time.monotonic() - t0) + + _LG.info_on_master("-" * 70) + + t0 = time.monotonic() + valid_metric = trainer.validate() + valid_sps = num_valid_samples / (time.monotonic() - t0) + _LG.info_on_master("Valid: %s", valid_metric) + + _LG.info_on_master("-" * 70) + + t0 = time.monotonic() + eval_metric = trainer.evaluate() + eval_sps = num_eval_samples / (time.monotonic() - t0) + _LG.info_on_master(" Eval: %s", eval_metric) + + _LG.info_on_master("-" * 70) + + _LG.info_on_master("Train: Speed: %6.2f [samples/sec]", train_sps) + _LG.info_on_master("Valid: Speed: %6.2f [samples/sec]", valid_sps) + _LG.info_on_master(" Eval: Speed: %6.2f [samples/sec]", eval_sps) + + _LG.info_on_master("-" * 70) + + dist_utils.write_csv_on_master( + log_path, + [ + epoch, + optimizer.param_groups[0]["lr"], + valid_metric.si_snri, + valid_metric.sdri, + eval_metric.si_snri, + eval_metric.sdri, + ], + ) + + lr_scheduler.step(valid_metric.si_snri) + + save_path = args.save_dir / f"epoch_{epoch}.pt" + dist_utils.save_on_master( + save_path, + { + "model": model.module.state_dict(), + "optimizer": optimizer.state_dict(), + "num_speakers": args.num_speakers, + "sample_rate": args.sample_rate, + "epoch": epoch, + }, + ) diff --git a/examples/source_separation/conv_tasnet/trainer.py b/examples/source_separation/conv_tasnet/trainer.py new file mode 100644 index 0000000000..af4e715305 --- /dev/null +++ b/examples/source_separation/conv_tasnet/trainer.py @@ -0,0 +1,165 @@ +import time +from typing import Tuple +from collections import namedtuple + +import torch +import torch.distributed as dist + +from utils import dist_utils, metrics + +_LG = dist_utils.getLogger(__name__) + +Metric = namedtuple("SNR", ["si_snri", "sdri"]) +Metric.__str__ = ( + lambda self: f"SI-SNRi: {self.si_snri:10.3e}, SDRi: {self.sdri:10.3e}" +) + + +def si_sdr_improvement( + estimate: torch.Tensor, + reference: torch.Tensor, + mix: torch.Tensor, + mask: torch.Tensor +) -> Tuple[torch.Tensor, torch.Tensor]: + """Compute the improvement of scale-invariant SDR. (SI-SNRi) and bare SDR (SDRi). + + Args: + estimate (torch.Tensor): Estimated source signals. + Shape: [batch, speakers, time frame] + reference (torch.Tensor): Reference (original) source signals. + Shape: [batch, speakers, time frame] + mix (torch.Tensor): Mixed souce signals, from which the setimated signals were generated. + Shape: [batch, speakers == 1, time frame] + mask (torch.Tensor): Mask to indicate padded value (0) or valid value (1). + Shape: [batch, 1, time frame] + + + Returns: + torch.Tensor: Improved SI-SDR. Shape: [batch, ] + torch.Tensor: Absolute SI-SDR. Shape: [batch, ] + + References: + - Conv-TasNet: Surpassing Ideal Time--Frequency Magnitude Masking for Speech Separation + Luo, Yi and Mesgarani, Nima + https://arxiv.org/abs/1809.07454 + """ + with torch.no_grad(): + sdri = metrics.sdri(estimate, reference, mix, mask=mask) + + estimate = estimate - estimate.mean(axis=2, keepdim=True) + reference = reference - reference.mean(axis=2, keepdim=True) + mix = mix - mix.mean(axis=2, keepdim=True) + + si_sdri = metrics.sdri(estimate, reference, mix, mask=mask) + return si_sdri, sdri + + +class OccasionalLogger: + """Simple helper class to log once in a while or when progress is quick enough""" + + def __init__(self, time_interval=180, progress_interval=0.1): + self.time_interval = time_interval + self.progress_interval = progress_interval + + self.last_time = 0.0 + self.last_progress = 0.0 + + def log(self, metric, progress, force=False): + now = time.monotonic() + if ( + force + or now > self.last_time + self.time_interval + or progress > self.last_progress + self.progress_interval + ): + self.last_time = now + self.last_progress = progress + _LG.info_on_master("train: %s [%3d%%]", metric, 100 * progress) + + +class Trainer: + def __init__( + self, + model, + optimizer, + train_loader, + valid_loader, + eval_loader, + grad_clip, + device, + *, + debug, + ): + self.model = model + self.optimizer = optimizer + self.train_loader = train_loader + self.valid_loader = valid_loader + self.eval_loader = eval_loader + self.grad_clip = grad_clip + self.device = device + self.debug = debug + + def train_one_epoch(self): + self.model.train() + logger = OccasionalLogger() + + num_batches = len(self.train_loader) + for i, batch in enumerate(self.train_loader, start=1): + mix = batch.mix.to(self.device) + src = batch.src.to(self.device) + mask = batch.mask.to(self.device) + + estimate = self.model(mix) + + si_snri, sdri = si_sdr_improvement(estimate, src, mix, mask) + si_snri = si_snri.mean() + sdri = sdri.mean() + + loss = -si_snri + self.optimizer.zero_grad() + loss.backward() + torch.nn.utils.clip_grad_norm_( + self.model.parameters(), self.grad_clip, norm_type=2.0 + ) + self.optimizer.step() + + metric = Metric(si_snri.item(), sdri.item()) + logger.log(metric, progress=i / num_batches, force=i == num_batches) + + if self.debug: + break + + def evaluate(self): + with torch.no_grad(): + return self._test(self.eval_loader) + + def validate(self): + with torch.no_grad(): + return self._test(self.valid_loader) + + def _test(self, loader): + self.model.eval() + + total_si_snri = torch.zeros(1, dtype=torch.float32, device=self.device) + total_sdri = torch.zeros(1, dtype=torch.float32, device=self.device) + + for batch in loader: + mix = batch.mix.to(self.device) + src = batch.src.to(self.device) + mask = batch.mask.to(self.device) + + estimate = self.model(mix) + + si_snri, sdri = si_sdr_improvement(estimate, src, mix, mask) + + total_si_snri += si_snri.sum() + total_sdri += sdri.sum() + + if self.debug: + break + + dist.all_reduce(total_si_snri, dist.ReduceOp.SUM) + dist.all_reduce(total_sdri, dist.ReduceOp.SUM) + + num_samples = len(loader.dataset) + metric = Metric(total_si_snri.item() / num_samples, total_sdri.item() / num_samples) + return metric diff --git a/examples/source_separation/train.py b/examples/source_separation/train.py new file mode 100644 index 0000000000..a969d33fb8 --- /dev/null +++ b/examples/source_separation/train.py @@ -0,0 +1,176 @@ +#!/usr/bin/env python3 +"""Launch souce separation training. + +This script runs training in Distributed Data Parallel (DDP) framework and has two major +operation modes. This behavior depends on if `--worker-id` argument is given or not. + +1. (`--worker-id` is not given) Launchs worker subprocesses that performs the actual training. +2. (`--worker-id` is given) Performs the training as a part of distributed training. + +When launching the script without any distributed trainig parameters (operation mode 1), +this script will check the number of GPUs available on the local system and spawns the same +number of training subprocesses (as operaiton mode 2). You can reduce the number of GPUs with +`--num-workers`. If there is no GPU available, only one subprocess is launched. + +When launching the script as a worker process of a distributed training, you need to configure +the coordination of the workers. +""" +import sys +import logging +import argparse +import subprocess + +import torch + +from utils import dist_utils + +_LG = dist_utils.getLogger(__name__) + + +def _parse_args(args=None): + max_world_size = torch.cuda.device_count() or 1 + + parser = argparse.ArgumentParser( + description=__doc__, + ) + parser.add_argument("--debug", action="store_true", help="Enable debug log") + group = parser.add_argument_group("Distributed Training") + group.add_argument( + "--worker-id", + type=int, + help=( + "If not provided, the launched process serves as a master process of " + "single-node, multi-worker training and spawns the worker subprocesses. " + "If provided, the launched process serves as a worker process, which " + "performs the actual training. The valid value is [0, --num-workers)." + ), + ) + group.add_argument( + "--device-id", + type=int, + help="The CUDA device ID. Allowed only when --worker-id is provided.", + ) + group.add_argument( + "--num-workers", + type=int, + default=max_world_size, + help=( + "The size of distributed trainig workers. " + "If launching a training as single-node, multi-worker training, " + "(i.e. --worker-id is not provided) then this value should not exceed " + "the number of available GPUs. " + "If launching the training process as a multi-node, multi-gpu training, " + "(i.e. --worker-id is provided) then the value has to match " + f"the number of workers across nodes. (default: {max_world_size})" + ), + ) + group.add_argument( + "--sync-protocol", + type=str, + default="env://", + help=( + "Synchronization protocol for distributed training. " + "This value is passed as `init_method` argument of " + "`torch.distributed.init_process_group` function." + 'If you are using `"env://"`, you can additionally configure ' + 'environment variables "MASTER_ADDR" and "MASTER_PORT". ' + 'If you are using `"file://..."`, then the process has to have ' + "the access to the designated file. " + "See the documentation for `torch.distributed` for the detail. " + 'If you are running the training in a single node, `"env://"` ' + "should do. If you are running the training in multiple nodes, " + "you need to provide the file location where all the nodes have " + 'access, using `"file://..."` protocol. (default: "env://")' + ), + ) + group.add_argument( + "--random-seed", + type=int, + help="Set random seed value. (default: None)", + ) + parser.add_argument( + "rest", nargs=argparse.REMAINDER, help="Model-specific arguments." + ) + namespace = parser.parse_args(args) + if namespace.worker_id is None: + if namespace.device_id is not None: + raise ValueError( + "`--device-id` cannot be provided when runing as master process." + ) + if namespace.num_workers > max_world_size: + raise ValueError( + "--num-workers ({num_workers}) cannot exceed {device_count}." + ) + if namespace.rest[:1] == ["--"]: + namespace.rest = namespace.rest[1:] + return namespace + + +def _main(cli_args): + args = _parse_args(cli_args) + + if any(arg in ["--help", "-h"] for arg in args.rest): + _run_training(args.rest) + + _init_logger(args.worker_id, args.debug) + if args.worker_id is None: + _run_training_subprocesses(args.num_workers, cli_args) + else: + dist_utils.setup_distributed( + world_size=args.num_workers, + rank=args.worker_id, + local_rank=args.device_id, + backend='nccl' if torch.cuda.is_available() else 'gloo', + init_method=args.sync_protocol, + ) + if args.random_seed is not None: + torch.manual_seed(args.random_seed) + if torch.cuda.is_available(): + torch.cuda.set_device(args.device_id) + _LG.info("CUDA device set to %s", args.device_id) + _run_training(args.rest) + + +def _run_training_subprocesses(num_workers, original_args): + workers = [] + _LG.info("Spawning %s workers", num_workers) + for i in range(num_workers): + worker_arg = ["--worker-id", f"{i}", "--num-workers", f"{num_workers}"] + device_arg = ["--device-id", f"{i}"] if torch.cuda.is_available() else [] + command = ( + [sys.executable, "-u", sys.argv[0]] + + worker_arg + + device_arg + + original_args + ) + _LG.info("Launching worker %s: `%s`", i, " ".join(command)) + worker = subprocess.Popen(command) + workers.append(worker) + + num_failed = 0 + for worker in workers: + worker.wait() + if worker.returncode != 0: + num_failed += 1 + sys.exit(num_failed) + + +def _run_training(args): + import conv_tasnet.train + + conv_tasnet.train.train(args) + + +def _init_logger(rank=None, debug=False): + worker_fmt = "[master]" if rank is None else f"[worker {rank:2d}]" + message_fmt = ( + "%(levelname)5s: %(funcName)10s: %(message)s" if debug else "%(message)s" + ) + logging.basicConfig( + level=logging.DEBUG if debug else logging.INFO, + format=f"%(asctime)s: {worker_fmt} {message_fmt}", + ) + + +if __name__ == "__main__": + _main(sys.argv[1:]) diff --git a/examples/source_separation/utils/__init__.py b/examples/source_separation/utils/__init__.py new file mode 100644 index 0000000000..28d451cde3 --- /dev/null +++ b/examples/source_separation/utils/__init__.py @@ -0,0 +1,5 @@ +from . import ( + dataset, + dist_utils, + metrics, +) diff --git a/examples/source_separation/utils/dataset/__init__.py b/examples/source_separation/utils/dataset/__init__.py new file mode 100644 index 0000000000..1a5e0b10c9 --- /dev/null +++ b/examples/source_separation/utils/dataset/__init__.py @@ -0,0 +1 @@ +from . import utils, wsj0mix diff --git a/examples/source_separation/utils/dataset/utils.py b/examples/source_separation/utils/dataset/utils.py new file mode 100644 index 0000000000..5b4b9cf2cc --- /dev/null +++ b/examples/source_separation/utils/dataset/utils.py @@ -0,0 +1,83 @@ +from typing import List +from functools import partial +from collections import namedtuple + +import torch + +from . import wsj0mix + +Batch = namedtuple("Batch", ["mix", "src", "mask"]) + + +def get_dataset(dataset_type, root_dir, num_speakers, sample_rate): + if dataset_type == "wsj0mix": + train = wsj0mix.WSJ0Mix(root_dir / "tr", num_speakers, sample_rate) + validation = wsj0mix.WSJ0Mix(root_dir / "cv", num_speakers, sample_rate) + evaluation = wsj0mix.WSJ0Mix(root_dir / "tt", num_speakers, sample_rate) + else: + raise ValueError(f"Unexpected dataset: {dataset_type}") + return train, validation, evaluation + + +def _fix_num_frames(sample: wsj0mix.SampleType, target_num_frames: int, random_start=False): + """Ensure waveform has exact number of frames by slicing or padding""" + mix = sample[1] # [1, num_frames] + src = torch.cat(sample[2], 0) # [num_sources, num_frames] + + num_channels, num_frames = src.shape + if num_frames >= target_num_frames: + if random_start and num_frames > target_num_frames: + start_frame = torch.randint(num_frames - target_num_frames, [1]) + mix = mix[:, start_frame:] + src = src[:, start_frame:] + mix = mix[:, :target_num_frames] + src = src[:, :target_num_frames] + mask = torch.ones_like(mix) + else: + num_padding = target_num_frames - num_frames + pad = torch.zeros([1, num_padding], dtype=mix.dtype, device=mix.device) + mix = torch.cat([mix, pad], 1) + src = torch.cat([src, pad.expand(num_channels, -1)], 1) + mask = torch.ones_like(mix) + mask[..., num_frames:] = 0 + return mix, src, mask + + + +def collate_fn_wsj0mix_train(samples: List[wsj0mix.SampleType], sample_rate, duration): + target_num_frames = int(duration * sample_rate) + + mixes, srcs, masks = [], [], [] + for sample in samples: + mix, src, mask = _fix_num_frames(sample, target_num_frames, random_start=True) + + mixes.append(mix) + srcs.append(src) + masks.append(mask) + + return Batch(torch.stack(mixes, 0), torch.stack(srcs, 0), torch.stack(masks, 0)) + + +def collate_fn_wsj0mix_test(samples: List[wsj0mix.SampleType]): + max_num_frames = max(s[1].shape[-1] for s in samples) + + mixes, srcs, masks = [], [], [] + for sample in samples: + mix, src, mask = _fix_num_frames(sample, max_num_frames, random_start=False) + + mixes.append(mix) + srcs.append(src) + masks.append(mask) + + return Batch(torch.stack(mixes, 0), torch.stack(srcs, 0), torch.stack(masks, 0)) + + +def get_collate_fn(dataset_type, mode, sample_rate=None, duration=4): + assert mode in ["train", "test"] + if dataset_type == "wsj0mix": + if mode == 'train': + if sample_rate is None: + raise ValueError("sample_rate is not given.") + return partial(collate_fn_wsj0mix_train, sample_rate=sample_rate, duration=duration) + return collate_fn_wsj0mix_test + raise ValueError(f"Unexpected dataset: {dataset_type}") diff --git a/examples/source_separation/utils/dataset/wsj0mix.py b/examples/source_separation/utils/dataset/wsj0mix.py new file mode 100644 index 0000000000..efd9268971 --- /dev/null +++ b/examples/source_separation/utils/dataset/wsj0mix.py @@ -0,0 +1,70 @@ +from pathlib import Path +from typing import Union, Tuple, List + +import torch +from torch.utils.data import Dataset + +import torchaudio + +SampleType = Tuple[int, torch.Tensor, List[torch.Tensor]] + + +class WSJ0Mix(Dataset): + """Create a Dataset for wsj0-mix. + + Args: + root (str or Path): Path to the directory where the dataset is found. + num_speakers (int): The number of speakers, which determines the directories + to traverse. The Dataset will traverse ``s1`` to ``sN`` directories to collect + N source audios. + sample_rate (int): Expected sample rate of audio files. If any of the audio has a + different sample rate, raises ``ValueError``. + audio_ext (str): The extension of audio files to find. (default: ".wav") + """ + def __init__( + self, + root: Union[str, Path], + num_speakers: int, + sample_rate: int, + audio_ext: str = ".wav", + ): + self.root = Path(root) + self.sample_rate = sample_rate + self.mix_dir = (self.root / "mix").resolve() + self.src_dirs = [(self.root / f"s{i+1}").resolve() for i in range(num_speakers)] + + self.files = [p.name for p in self.mix_dir.glob(f"*{audio_ext}")] + self.files.sort() + + def _load_audio(self, path) -> torch.Tensor: + waveform, sample_rate = torchaudio.load(path) + if sample_rate != self.sample_rate: + raise ValueError( + f"The dataset contains audio file of sample rate {sample_rate}. " + "Where the requested sample rate is {self.sample_rate}." + ) + return waveform + + def _load_sample(self, filename) -> SampleType: + mixed = self._load_audio(str(self.mix_dir / filename)) + srcs = [] + for i, dir_ in enumerate(self.src_dirs): + src = self._load_audio(str(dir_ / filename)) + if mixed.shape != src.shape: + raise ValueError( + f"Different waveform shapes. mixed: {mixed.shape}, src[{i}]: {src.shape}" + ) + srcs.append(src) + return self.sample_rate, mixed, srcs + + def __len__(self) -> int: + return len(self.files) + + def __getitem__(self, key: int) -> SampleType: + """Load the n-th sample from the dataset. + Args: + n (int): The index of the sample to be loaded + Returns: + tuple: ``(sample_rate, mix_waveform, list_of_source_waveforms)`` + """ + return self._load_sample(self.files[key]) diff --git a/examples/source_separation/utils/dist_utils.py b/examples/source_separation/utils/dist_utils.py new file mode 100644 index 0000000000..380358b87b --- /dev/null +++ b/examples/source_separation/utils/dist_utils.py @@ -0,0 +1,86 @@ +import os +import csv +import types +import logging + +import torch +import torch.distributed as dist + + +def _info_on_master(self, *args, **kwargs): + if dist.get_rank() == 0: + self.info(*args, **kwargs) + + +def getLogger(name): + """Get logging.Logger module with additional ``info_on_master`` method.""" + logger = logging.getLogger(name) + logger.info_on_master = types.MethodType(_info_on_master, logger) + return logger + + +_LG = getLogger(__name__) + + +def setup_distributed( + world_size, rank, local_rank, backend="nccl", init_method="env://" +): + """Perform env setup and initialization for distributed training""" + if init_method == "env://": + _set_env_vars(world_size, rank, local_rank) + if world_size > 1 and "OMP_NUM_THREADS" not in os.environ: + _LG.info("Setting OMP_NUM_THREADS == 1") + os.environ["OMP_NUM_THREADS"] = "1" + params = { + "backend": backend, + "init_method": init_method, + "world_size": world_size, + "rank": rank, + } + _LG.info("Initializing distributed process group with %s", params) + dist.init_process_group(**params) + _LG.info("Initialized distributed process group.") + + +def _set_env_vars(world_size, rank, local_rank): + for key, default in [("MASTER_ADDR", "127.0.0.1"), ("MASTER_PORT", "29500")]: + if key not in os.environ: + os.environ[key] = default + + os.environ["WORLD_SIZE"] = str(world_size) + os.environ["RANK"] = str(rank) + os.environ["LOCAL_RANK"] = str(local_rank) + + +def save_on_master(path, obj): + if dist.get_rank() == 0: + _LG.info("Saving %s", path) + torch.save(obj, path) + + +def write_csv_on_master(path, *rows): + if dist.get_rank() == 0: + with open(path, "a", newline="") as fileobj: + writer = csv.writer(fileobj) + for row in rows: + writer.writerow(row) + + +def synchronize_params(path, device, *modules): + if dist.get_world_size() < 2: + return + rank = dist.get_rank() + if rank == 0: + _LG.info("[Parameter Sync]: Saving parameters to a temp file...") + torch.save({f"{i}": m.state_dict() for i, m in enumerate(modules)}, path) + dist.barrier() + if rank != 0: + _LG.info("[Parameter Sync]: Loading parameters...") + data = torch.load(path, map_location=device) + for i, m in enumerate(modules): + m.load_state_dict(data[f"{i}"]) + dist.barrier() + if rank == 0: + _LG.info("[Parameter Sync]: Removing the temp file...") + os.remove(path) + _LG.info_on_master("[Parameter Sync]: Complete.") diff --git a/examples/source_separation/utils/metrics.py b/examples/source_separation/utils/metrics.py new file mode 100644 index 0000000000..238851b4e9 --- /dev/null +++ b/examples/source_separation/utils/metrics.py @@ -0,0 +1,204 @@ +import math +from typing import Optional +from itertools import permutations + +import torch + + +def sdr( + estimate: torch.Tensor, + reference: torch.Tensor, + mask: Optional[torch.Tensor] = None, + epsilon: float = 1e-8 +) -> torch.Tensor: + """Computes source-to-distortion ratio. + + 1. scale the reference signal with power(s_est * s_ref) / powr(s_ref * s_ref) + 2. compute SNR between adjusted estimate and reference. + + Args: + estimate (torch.Tensor): Estimtaed signal. + Shape: [batch, speakers (can be 1), time frame] + reference (torch.Tensor): Reference signal. + Shape: [batch, speakers, time frame] + mask (Optional[torch.Tensor]): Binary mask to indicate padded value (0) or valid value (1). + Shape: [batch, 1, time frame] + epsilon (float): constant value used to stabilize division. + + Returns: + torch.Tensor: scale-invariant source-to-distortion ratio. + Shape: [batch, speaker] + + References: + - Single-channel multi-speaker separation using deep clustering + Y. Isik, J. Le Roux, Z. Chen, S. Watanabe, and J. R. Hershey, + - Conv-TasNet: Surpassing Ideal Time--Frequency Magnitude Masking for Speech Separation + Luo, Yi and Mesgarani, Nima + https://arxiv.org/abs/1809.07454 + + Notes: + This function is tested to produce the exact same result as + https://github.com/naplab/Conv-TasNet/blob/e66d82a8f956a69749ec8a4ae382217faa097c5c/utility/sdr.py#L34-L56 + """ + reference_pow = reference.pow(2).mean(axis=2, keepdim=True) + mix_pow = (estimate * reference).mean(axis=2, keepdim=True) + scale = mix_pow / (reference_pow + epsilon) + + reference = scale * reference + error = estimate - reference + + reference_pow = reference.pow(2) + error_pow = error.pow(2) + + if mask is None: + reference_pow = reference_pow.mean(axis=2) + error_pow = error_pow.mean(axis=2) + else: + denom = mask.sum(axis=2) + reference_pow = (mask * reference_pow).sum(axis=2) / denom + error_pow = (mask * error_pow).sum(axis=2) / denom + + return 10 * torch.log10(reference_pow) - 10 * torch.log10(error_pow) + + +class PIT(torch.nn.Module): + """Applies utterance-level speaker permutation + + Computes the maxium possible value of the given utility function + over the permutations of the speakers. + + Args: + utility_func (function): + Function that computes the utility (opposite of loss) with signature of + (extimate: torch.Tensor, reference: torch.Tensor) -> torch.Tensor + where input Tensors are shape of [batch, speakers, frame] and + the output Tensor is shape of [batch, speakers]. + + References: + - Multi-talker Speech Separation with Utterance-level Permutation Invariant Training of + Deep Recurrent Neural Networks + Morten Kolbรฆk, Dong Yu, Zheng-Hua Tan and Jesper Jensen + https://arxiv.org/abs/1703.06284 + """ + + def __init__(self, utility_func): + super().__init__() + self.utility_func = utility_func + + def forward( + self, + estimate: torch.Tensor, + reference: torch.Tensor, + mask: Optional[torch.Tensor] = None, + epsilon: float = 1e-8 + ) -> torch.Tensor: + """Compute utterance-level PIT Loss + + Args: + estimate (torch.Tensor): Estimated source signals. + Shape: [bacth, speakers, time frame] + reference (torch.Tensor): Reference (original) source signals. + Shape: [batch, speakers, time frame] + mask (Optional[torch.Tensor]): Binary mask to indicate padded value (0) or valid value (1). + Shape: [batch, 1, time frame] + epsilon (float): constant value used to stabilize division. + + Returns: + torch.Tensor: Maximum criterion over the speaker permutation. + Shape: [batch, ] + """ + assert estimate.shape == reference.shape + + batch_size, num_speakers = reference.shape[:2] + num_permute = math.factorial(num_speakers) + + util_mat = torch.zeros( + batch_size, num_permute, dtype=estimate.dtype, device=estimate.device + ) + for i, idx in enumerate(permutations(range(num_speakers))): + util = self.utility_func(estimate, reference[:, idx, :], mask=mask, epsilon=epsilon) + util_mat[:, i] = util.mean(dim=1) # take the average over speaker dimension + return util_mat.max(dim=1).values + + +_sdr_pit = PIT(utility_func=sdr) + + +def sdr_pit( + estimate: torch.Tensor, + reference: torch.Tensor, + mask: Optional[torch.Tensor] = None, + epsilon: float = 1e-8): + """Computes scale-invariant source-to-distortion ratio. + + 1. adjust both estimate and reference to have 0-mean + 2. scale the reference signal with power(s_est * s_ref) / powr(s_ref * s_ref) + 3. compute SNR between adjusted estimate and reference. + + Args: + estimate (torch.Tensor): Estimtaed signal. + Shape: [batch, speakers (can be 1), time frame] + reference (torch.Tensor): Reference signal. + Shape: [batch, speakers, time frame] + mask (Optional[torch.Tensor]): Binary mask to indicate padded value (0) or valid value (1). + Shape: [batch, 1, time frame] + epsilon (float): constant value used to stabilize division. + + Returns: + torch.Tensor: scale-invariant source-to-distortion ratio. + Shape: [batch, speaker] + + References: + - Single-channel multi-speaker separation using deep clustering + Y. Isik, J. Le Roux, Z. Chen, S. Watanabe, and J. R. Hershey, + - Conv-TasNet: Surpassing Ideal Time--Frequency Magnitude Masking for Speech Separation + Luo, Yi and Mesgarani, Nima + https://arxiv.org/abs/1809.07454 + + Notes: + This function is tested to produce the exact same result as the reference implementation, + *when the inputs have 0-mean* + https://github.com/naplab/Conv-TasNet/blob/e66d82a8f956a69749ec8a4ae382217faa097c5c/utility/sdr.py#L107-L153 + """ + return _sdr_pit(estimate, reference, mask, epsilon) + + +def sdri( + estimate: torch.Tensor, + reference: torch.Tensor, + mix: torch.Tensor, + mask: Optional[torch.Tensor] = None, + epsilon: float = 1e-8, +) -> torch.Tensor: + """Compute the improvement of SDR (SDRi). + + This function compute how much SDR is improved if the estimation is changed from + the original mixture signal to the actual estimated source signals. That is, + ``SDR(estimate, reference) - SDR(mix, reference)``. + + For computing ``SDR(estimate, reference)``, PIT (permutation invariant training) is applied, + so that best combination of sources between the reference signals and the esimate signals + are picked. + + Args: + estimate (torch.Tensor): Estimated source signals. + Shape: [batch, speakers, time frame] + reference (torch.Tensor): Reference (original) source signals. + Shape: [batch, speakers, time frame] + mix (torch.Tensor): Mixed souce signals, from which the setimated signals were generated. + Shape: [batch, speakers == 1, time frame] + mask (Optional[torch.Tensor]): Binary mask to indicate padded value (0) or valid value (1). + Shape: [batch, 1, time frame] + epsilon (float): constant value used to stabilize division. + + Returns: + torch.Tensor: Improved SDR. Shape: [batch, ] + + References: + - Conv-TasNet: Surpassing Ideal Time--Frequency Magnitude Masking for Speech Separation + Luo, Yi and Mesgarani, Nima + https://arxiv.org/abs/1809.07454 + """ + sdr_ = sdr_pit(estimate, reference, mask=mask, epsilon=epsilon) # [batch, ] + base_sdr = sdr(mix, reference, mask=mask, epsilon=epsilon) # [batch, speaker] + return (sdr_.unsqueeze(1) - base_sdr).mean(dim=1) diff --git a/packaging/build_conda.sh b/packaging/build_conda.sh index 628eaf0bf8..488d0fe871 100755 --- a/packaging/build_conda.sh +++ b/packaging/build_conda.sh @@ -6,7 +6,7 @@ script_dir="$( cd "$( dirname "${BASH_SOURCE[0]}" )" >/dev/null 2>&1 && pwd )" export BUILD_TYPE="conda" export NO_CUDA_PACKAGE=1 -setup_env 0.7.0 +setup_env 0.8.0 export SOURCE_ROOT_DIR="$PWD" setup_conda_pytorch_constraint conda build $CONDA_CHANNEL_FLAGS --no-anaconda-upload --python "$PYTHON_VERSION" packaging/torchaudio diff --git a/packaging/build_wheel.sh b/packaging/build_wheel.sh index 3b25c00cd2..ad45a08d59 100755 --- a/packaging/build_wheel.sh +++ b/packaging/build_wheel.sh @@ -6,7 +6,7 @@ script_dir="$( cd "$( dirname "${BASH_SOURCE[0]}" )" >/dev/null 2>&1 && pwd )" export BUILD_TYPE="wheel" export NO_CUDA_PACKAGE=1 -setup_env 0.7.0 +setup_env 0.8.0 setup_wheel_python pip_install numpy future setup_pip_pytorch_version diff --git a/packaging/pkg_helpers.bash b/packaging/pkg_helpers.bash index 57b23b93d3..3316f789e2 100644 --- a/packaging/pkg_helpers.bash +++ b/packaging/pkg_helpers.bash @@ -171,8 +171,7 @@ setup_pip_pytorch_version() { else pip_install "torch==$PYTORCH_VERSION$PYTORCH_VERSION_SUFFIX" \ -f https://download.pytorch.org/whl/torch_stable.html \ - -f https://download.pytorch.org/whl/test/torch_test.html \ - -f https://download.pytorch.org/whl/nightly/torch_nightly.html + -f "https://download.pytorch.org/whl/${UPLOAD_CHANNEL}/torch_${UPLOAD_CHANNEL}.html" fi } @@ -185,7 +184,7 @@ setup_conda_pytorch_constraint() { export CONDA_CHANNEL_FLAGS="-c pytorch-nightly" export PYTORCH_VERSION="$(conda search --json 'pytorch[channel=pytorch-nightly]' | python -c "import sys, json, re; print(re.sub(r'\\+.*$', '', json.load(sys.stdin)['pytorch'][-1]['version']))")" else - export CONDA_CHANNEL_FLAGS="-c pytorch -c pytorch-test -c pytorch-nightly" + export CONDA_CHANNEL_FLAGS="-c pytorch -c pytorch-${UPLOAD_CHANNEL}" fi if [[ "$CU_VERSION" == cpu ]]; then export CONDA_PYTORCH_BUILD_CONSTRAINT="- pytorch==$PYTORCH_VERSION${PYTORCH_VERSION_SUFFIX}" diff --git a/setup.py b/setup.py index 0773b23107..4ced5fc8fd 100644 --- a/setup.py +++ b/setup.py @@ -12,7 +12,7 @@ # Creating the version file -version = '0.7.0a0' +version = '0.8.0a0' sha = 'Unknown' try: diff --git a/test/torchaudio_unittest/backend_test.py b/test/torchaudio_unittest/backend_test.py index d7a2078a31..3f355be0cb 100644 --- a/test/torchaudio_unittest/backend_test.py +++ b/test/torchaudio_unittest/backend_test.py @@ -38,6 +38,18 @@ class TestBackendSwitch_SoXIO(BackendSwitchMixin, common_utils.TorchaudioTestCas @common_utils.skipIfNoModule('soundfile') -class TestBackendSwitch_soundfile(BackendSwitchMixin, common_utils.TorchaudioTestCase): +class TestBackendSwitch_soundfile_legacy(BackendSwitchMixin, common_utils.TorchaudioTestCase): backend = 'soundfile' backend_module = torchaudio.backend.soundfile_backend + + def setUp(self): + torchaudio.USE_SOUNDFILE_LEGACY_INTERFACE = True + + def tearDown(self): + torchaudio.USE_SOUNDFILE_LEGACY_INTERFACE = None + + +@common_utils.skipIfNoModule('soundfile') +class TestBackendSwitch_soundfile(BackendSwitchMixin, common_utils.TorchaudioTestCase): + backend = 'soundfile' + backend_module = torchaudio.backend._soundfile_backend diff --git a/test/torchaudio_unittest/common_utils/backend_utils.py b/test/torchaudio_unittest/common_utils/backend_utils.py index 7702a3d6f3..7e519c80eb 100644 --- a/test/torchaudio_unittest/common_utils/backend_utils.py +++ b/test/torchaudio_unittest/common_utils/backend_utils.py @@ -6,11 +6,15 @@ def set_audio_backend(backend): """Allow additional backend value, 'default'""" backends = torchaudio.list_audio_backends() - if backend == 'default': + if backend == 'soundfile-new': + be = 'soundfile' + torchaudio.USE_SOUNDFILE_LEGACY_INTERFACE = False + elif backend == 'default': if 'sox_io' in backends: be = 'sox_io' elif 'soundfile' in backends: be = 'soundfile' + torchaudio.USE_SOUNDFILE_LEGACY_INTERFACE = True else: raise unittest.SkipTest('No default backend available') else: diff --git a/test/torchaudio_unittest/common_utils/wav_utils.py b/test/torchaudio_unittest/common_utils/wav_utils.py index bc122ec6cb..b4b7944805 100644 --- a/test/torchaudio_unittest/common_utils/wav_utils.py +++ b/test/torchaudio_unittest/common_utils/wav_utils.py @@ -52,12 +52,18 @@ def get_wav_data( if dtype == 'uint8': base = torch.linspace(0, 255, num_frames, dtype=dtype_) - if dtype == 'float32': + elif dtype == 'int8': + base = torch.linspace(-128, 127, num_frames, dtype=dtype_) + elif dtype == 'float32': base = torch.linspace(-1., 1., num_frames, dtype=dtype_) - if dtype == 'int32': + elif dtype == 'float64': + base = torch.linspace(-1., 1., num_frames, dtype=dtype_) + elif dtype == 'int32': base = torch.linspace(-2147483648, 2147483647, num_frames, dtype=dtype_) - if dtype == 'int16': + elif dtype == 'int16': base = torch.linspace(-32768, 32767, num_frames, dtype=dtype_) + else: + raise NotImplementedError(f'Unsupported dtype {dtype}') data = base.repeat([num_channels, 1]) if not channels_first: data = data.transpose(1, 0) diff --git a/test/torchaudio_unittest/dataloader_test.py b/test/torchaudio_unittest/dataloader_test.py deleted file mode 100644 index 8f1d7e6fb3..0000000000 --- a/test/torchaudio_unittest/dataloader_test.py +++ /dev/null @@ -1,39 +0,0 @@ -import unittest - -import torchaudio -from torch.utils.data import Dataset, DataLoader - -from torchaudio_unittest import common_utils - - -class TORCHAUDIODS(Dataset): - def __init__(self): - sound_files = ["sinewave.wav", "steam-train-whistle-daniel_simon.mp3"] - self.data = [common_utils.get_asset_path(fn) for fn in sound_files] - self.si, self.ei = torchaudio.info(common_utils.get_asset_path("sinewave.wav")) - self.si.precision = 16 - self.E = torchaudio.sox_effects.SoxEffectsChain() - self.E.append_effect_to_chain("rate", [self.si.rate]) # resample to 16000hz - self.E.append_effect_to_chain("channels", [self.si.channels]) # mono signal - self.E.append_effect_to_chain("trim", [0, "16000s"]) # first 16000 samples of audio - - def __getitem__(self, index): - fn = self.data[index] - self.E.set_input_file(fn) - x, sr = self.E.sox_build_flow_effects() - return x - - def __len__(self): - return len(self.data) - - -class Test_DataLoader(common_utils.TorchaudioTestCase): - backend = 'sox' - - @common_utils.skipIfNoSoxBackend - def test_1(self): - expected_size = (2, 1, 16000) - ds = TORCHAUDIODS() - dl = DataLoader(ds, batch_size=2) - for x in dl: - self.assertTrue(x.size() == expected_size) diff --git a/test/torchaudio_unittest/datasets/speechcommands_test.py b/test/torchaudio_unittest/datasets/speechcommands_test.py index 7df1ea2007..5a331bdeca 100644 --- a/test/torchaudio_unittest/datasets/speechcommands_test.py +++ b/test/torchaudio_unittest/datasets/speechcommands_test.py @@ -53,9 +53,12 @@ class TestSpeechCommands(TempDirMixin, TorchaudioTestCase): root_dir = None samples = [] + train_samples = [] + valid_samples = [] + test_samples = [] @classmethod - def setUp(cls): + def setUpClass(cls): cls.root_dir = cls.get_base_temp_dir() dataset_dir = os.path.join( cls.root_dir, speechcommands.FOLDER_IN_ARCHIVE, speechcommands.URL @@ -63,37 +66,47 @@ def setUp(cls): os.makedirs(dataset_dir, exist_ok=True) sample_rate = 16000 # 16kHz sample rate seed = 0 - for label in LABELS: - path = os.path.join(dataset_dir, label) - os.makedirs(path, exist_ok=True) - for j in range(2): - # generate hash ID for speaker - speaker = "{:08x}".format(j) - - for utterance in range(3): - filename = f"{speaker}{speechcommands.HASH_DIVIDER}{utterance}.wav" - file_path = os.path.join(path, filename) - seed += 1 - data = get_whitenoise( - sample_rate=sample_rate, - duration=0.01, - n_channels=1, - dtype="int16", - seed=seed, - ) - save_wav(file_path, data, sample_rate) - sample = ( - normalize_wav(data), - sample_rate, - label, - speaker, - utterance, - ) - cls.samples.append(sample) + valid_file = os.path.join(dataset_dir, "validation_list.txt") + test_file = os.path.join(dataset_dir, "testing_list.txt") + with open(valid_file, "w") as valid, open(test_file, "w") as test: + for label in LABELS: + path = os.path.join(dataset_dir, label) + os.makedirs(path, exist_ok=True) + for j in range(6): + # generate hash ID for speaker + speaker = "{:08x}".format(j) + + for utterance in range(3): + filename = f"{speaker}{speechcommands.HASH_DIVIDER}{utterance}.wav" + file_path = os.path.join(path, filename) + seed += 1 + data = get_whitenoise( + sample_rate=sample_rate, + duration=0.01, + n_channels=1, + dtype="int16", + seed=seed, + ) + save_wav(file_path, data, sample_rate) + sample = ( + normalize_wav(data), + sample_rate, + label, + speaker, + utterance, + ) + cls.samples.append(sample) + if j < 2: + cls.train_samples.append(sample) + elif j < 4: + valid.write(f'{label}/{filename}\n') + cls.valid_samples.append(sample) + elif j < 6: + test.write(f'{label}/{filename}\n') + cls.test_samples.append(sample) def testSpeechCommands(self): dataset = speechcommands.SPEECHCOMMANDS(self.root_dir) - print(dataset._path) num_samples = 0 for i, (data, sample_rate, label, speaker_id, utterance_number) in enumerate( @@ -107,3 +120,75 @@ def testSpeechCommands(self): num_samples += 1 assert num_samples == len(self.samples) + + def testSpeechCommandsNone(self): + dataset = speechcommands.SPEECHCOMMANDS(self.root_dir, subset=None) + + num_samples = 0 + for i, (data, sample_rate, label, speaker_id, utterance_number) in enumerate( + dataset + ): + self.assertEqual(data, self.samples[i][0], atol=5e-5, rtol=1e-8) + assert sample_rate == self.samples[i][1] + assert label == self.samples[i][2] + assert speaker_id == self.samples[i][3] + assert utterance_number == self.samples[i][4] + num_samples += 1 + + assert num_samples == len(self.samples) + + def testSpeechCommandsSubsetTrain(self): + dataset = speechcommands.SPEECHCOMMANDS(self.root_dir, subset="training") + + num_samples = 0 + for i, (data, sample_rate, label, speaker_id, utterance_number) in enumerate( + dataset + ): + self.assertEqual(data, self.train_samples[i][0], atol=5e-5, rtol=1e-8) + assert sample_rate == self.train_samples[i][1] + assert label == self.train_samples[i][2] + assert speaker_id == self.train_samples[i][3] + assert utterance_number == self.train_samples[i][4] + num_samples += 1 + + assert num_samples == len(self.train_samples) + + def testSpeechCommandsSubsetValid(self): + dataset = speechcommands.SPEECHCOMMANDS(self.root_dir, subset="validation") + + num_samples = 0 + for i, (data, sample_rate, label, speaker_id, utterance_number) in enumerate( + dataset + ): + self.assertEqual(data, self.valid_samples[i][0], atol=5e-5, rtol=1e-8) + assert sample_rate == self.valid_samples[i][1] + assert label == self.valid_samples[i][2] + assert speaker_id == self.valid_samples[i][3] + assert utterance_number == self.valid_samples[i][4] + num_samples += 1 + + assert num_samples == len(self.valid_samples) + + def testSpeechCommandsSubsetTest(self): + dataset = speechcommands.SPEECHCOMMANDS(self.root_dir, subset="testing") + + num_samples = 0 + for i, (data, sample_rate, label, speaker_id, utterance_number) in enumerate( + dataset + ): + self.assertEqual(data, self.test_samples[i][0], atol=5e-5, rtol=1e-8) + assert sample_rate == self.test_samples[i][1] + assert label == self.test_samples[i][2] + assert speaker_id == self.test_samples[i][3] + assert utterance_number == self.test_samples[i][4] + num_samples += 1 + + assert num_samples == len(self.test_samples) + + def testSpeechCommandsSum(self): + dataset_all = speechcommands.SPEECHCOMMANDS(self.root_dir) + dataset_train = speechcommands.SPEECHCOMMANDS(self.root_dir, subset="training") + dataset_valid = speechcommands.SPEECHCOMMANDS(self.root_dir, subset="validation") + dataset_test = speechcommands.SPEECHCOMMANDS(self.root_dir, subset="testing") + + assert len(dataset_train) + len(dataset_valid) + len(dataset_test) == len(dataset_all) diff --git a/test/torchaudio_unittest/datasets/tedlium_test.py b/test/torchaudio_unittest/datasets/tedlium_test.py index c19984cac2..f5becb53ab 100644 --- a/test/torchaudio_unittest/datasets/tedlium_test.py +++ b/test/torchaudio_unittest/datasets/tedlium_test.py @@ -1,8 +1,11 @@ import os +import platform +import unittest from torchaudio.datasets import tedlium from torchaudio_unittest.common_utils import ( + TestBaseMixin, TempDirMixin, TorchaudioTestCase, get_whitenoise, @@ -30,9 +33,7 @@ ] -class TestTedlium(TempDirMixin, TorchaudioTestCase): - backend = "default" - +class Tedlium(TempDirMixin): root_dir = None samples = {} @@ -151,3 +152,19 @@ def test_tedlium_release3(self): phoneme_dict = dataset.phoneme_dict phoenemes = [f"{key} {' '.join(value)}" for key, value in phoneme_dict.items()] assert phoenemes == PHONEME + + +class TestTedliumSoundfile(Tedlium, TorchaudioTestCase): + backend = "soundfile" + + +class TestTedliumSoundfileNew(Tedlium, TorchaudioTestCase): + backend = "soundfile-new" + + +if platform.system() != "Windows": + class TestTedliumSox(Tedlium, TorchaudioTestCase): + backend = "sox" + + class TestTedliumSoxIO(Tedlium, TorchaudioTestCase): + backend = "sox_io" diff --git a/test/torchaudio_unittest/example/__init__.py b/test/torchaudio_unittest/example/__init__.py new file mode 100644 index 0000000000..9e4fa81989 --- /dev/null +++ b/test/torchaudio_unittest/example/__init__.py @@ -0,0 +1,8 @@ +import os +import sys + + +sys.path.append( + os.path.join( + os.path.dirname(__file__), + '..', '..', '..', 'examples')) diff --git a/test/torchaudio_unittest/example/souce_sepration/__init__.py b/test/torchaudio_unittest/example/souce_sepration/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/test/torchaudio_unittest/example/souce_sepration/metrics_test.py b/test/torchaudio_unittest/example/souce_sepration/metrics_test.py new file mode 100644 index 0000000000..b7793b07ba --- /dev/null +++ b/test/torchaudio_unittest/example/souce_sepration/metrics_test.py @@ -0,0 +1,39 @@ +from itertools import product + +import torch +from torch.testing._internal.common_utils import TestCase +from parameterized import parameterized + +from . import sdr_reference +from source_separation.utils import metrics + + +class TestSDR(TestCase): + @parameterized.expand([(1, ), (2, ), (32, )]) + def test_sdr(self, batch_size): + """sdr produces the same result as the reference implementation""" + num_frames = 256 + + estimation = torch.rand(batch_size, num_frames) + origin = torch.rand(batch_size, num_frames) + + sdr_ref = sdr_reference.calc_sdr_torch(estimation, origin) + sdr = metrics.sdr(estimation.unsqueeze(1), origin.unsqueeze(1)).squeeze(1) + + self.assertEqual(sdr, sdr_ref) + + @parameterized.expand(list(product([1, 2, 32], [2, 3, 4, 5]))) + def test_sdr_pit(self, batch_size, num_sources): + """sdr_pit produces the same result as the reference implementation""" + num_frames = 256 + + estimation = torch.randn(batch_size, num_sources, num_frames) + origin = torch.randn(batch_size, num_sources, num_frames) + + estimation -= estimation.mean(axis=2, keepdim=True) + origin -= origin.mean(axis=2, keepdim=True) + + batch_sdr_ref = sdr_reference.batch_SDR_torch(estimation, origin) + batch_sdr = metrics.sdr_pit(estimation, origin) + + self.assertEqual(batch_sdr, batch_sdr_ref) diff --git a/test/torchaudio_unittest/example/souce_sepration/sdr_reference.py b/test/torchaudio_unittest/example/souce_sepration/sdr_reference.py new file mode 100644 index 0000000000..7652fab0e6 --- /dev/null +++ b/test/torchaudio_unittest/example/souce_sepration/sdr_reference.py @@ -0,0 +1,98 @@ +"""Reference Implementation of SDR and PIT SDR. + +This module was taken from the following implementation + +https://github.com/naplab/Conv-TasNet/blob/e66d82a8f956a69749ec8a4ae382217faa097c5c/utility/sdr.py + +which was made available by Yi Luo under the following liscence, + +Creative Commons Attribution-NonCommercial-ShareAlike 3.0 United States License. + +The module was modified in the following manner; + - Remove the functions other than `calc_sdr_torch` and `batch_SDR_torch`, + - Remove the import statements required only for the removed functions. + - Add `# flake8: noqa` so as not to report any format issue on this module. + +The implementation of the retained functions and their formats are kept as-is. +""" + +# flake8: noqa + +import numpy as np +from itertools import permutations + +import torch + + +def calc_sdr_torch(estimation, origin, mask=None): + """ + batch-wise SDR caculation for one audio file on pytorch Variables. + estimation: (batch, nsample) + origin: (batch, nsample) + mask: optional, (batch, nsample), binary + """ + + if mask is not None: + origin = origin * mask + estimation = estimation * mask + + origin_power = torch.pow(origin, 2).sum(1, keepdim=True) + 1e-8 # (batch, 1) + + scale = torch.sum(origin*estimation, 1, keepdim=True) / origin_power # (batch, 1) + + est_true = scale * origin # (batch, nsample) + est_res = estimation - est_true # (batch, nsample) + + true_power = torch.pow(est_true, 2).sum(1) + res_power = torch.pow(est_res, 2).sum(1) + + return 10*torch.log10(true_power) - 10*torch.log10(res_power) # (batch, 1) + + +def batch_SDR_torch(estimation, origin, mask=None): + """ + batch-wise SDR caculation for multiple audio files. + estimation: (batch, nsource, nsample) + origin: (batch, nsource, nsample) + mask: optional, (batch, nsample), binary + """ + + batch_size_est, nsource_est, nsample_est = estimation.size() + batch_size_ori, nsource_ori, nsample_ori = origin.size() + + assert batch_size_est == batch_size_ori, "Estimation and original sources should have same shape." + assert nsource_est == nsource_ori, "Estimation and original sources should have same shape." + assert nsample_est == nsample_ori, "Estimation and original sources should have same shape." + + assert nsource_est < nsample_est, "Axis 1 should be the number of sources, and axis 2 should be the signal." + + batch_size = batch_size_est + nsource = nsource_est + nsample = nsample_est + + # zero mean signals + estimation = estimation - torch.mean(estimation, 2, keepdim=True).expand_as(estimation) + origin = origin - torch.mean(origin, 2, keepdim=True).expand_as(estimation) + + # possible permutations + perm = list(set(permutations(np.arange(nsource)))) + + # pair-wise SDR + SDR = torch.zeros((batch_size, nsource, nsource)).type(estimation.type()) + for i in range(nsource): + for j in range(nsource): + SDR[:,i,j] = calc_sdr_torch(estimation[:,i], origin[:,j], mask) + + # choose the best permutation + SDR_max = [] + SDR_perm = [] + for permute in perm: + sdr = [] + for idx in range(len(permute)): + sdr.append(SDR[:,idx,permute[idx]].view(batch_size,-1)) + sdr = torch.sum(torch.cat(sdr, 1), 1) + SDR_perm.append(sdr.view(batch_size, 1)) + SDR_perm = torch.cat(SDR_perm, 1) + SDR_max, _ = torch.max(SDR_perm, dim=1) + + return SDR_max / nsource diff --git a/test/torchaudio_unittest/example/souce_sepration/wsj0mix_test.py b/test/torchaudio_unittest/example/souce_sepration/wsj0mix_test.py new file mode 100644 index 0000000000..46927b182f --- /dev/null +++ b/test/torchaudio_unittest/example/souce_sepration/wsj0mix_test.py @@ -0,0 +1,111 @@ +import os + +from torchaudio_unittest.common_utils import ( + TempDirMixin, + TorchaudioTestCase, + get_whitenoise, + save_wav, + normalize_wav, +) + +from source_separation.utils.dataset import wsj0mix + + +_FILENAMES = [ + "012c0207_1.9952_01cc0202_-1.9952.wav", + "01co0302_1.63_014c020q_-1.63.wav", + "01do0316_0.24011_205a0104_-0.24011.wav", + "01lc020x_1.1301_027o030r_-1.1301.wav", + "01mc0202_0.34056_205o0106_-0.34056.wav", + "01nc020t_0.53821_018o030w_-0.53821.wav", + "01po030f_2.2136_40ko031a_-2.2136.wav", + "01ra010o_2.4098_403a010f_-2.4098.wav", + "01xo030b_0.22377_016o031a_-0.22377.wav", + "02ac020x_0.68566_01ec020b_-0.68566.wav", + "20co010m_0.82801_019c0212_-0.82801.wav", + "20da010u_1.2483_017c0211_-1.2483.wav", + "20oo010d_1.0631_01ic020s_-1.0631.wav", + "20sc0107_2.0222_20fo010h_-2.0222.wav", + "20tc010f_0.051456_404a0110_-0.051456.wav", + "407c0214_1.1712_02ca0113_-1.1712.wav", + "40ao030w_2.4697_20vc010a_-2.4697.wav", + "40pa0101_1.1087_40ea0107_-1.1087.wav", +] + + +def _mock_dataset(root_dir, num_speaker): + dirnames = ["mix"] + [f"s{i+1}" for i in range(num_speaker)] + for dirname in dirnames: + os.makedirs(os.path.join(root_dir, dirname), exist_ok=True) + + seed = 0 + sample_rate = 8000 + expected = [] + for filename in _FILENAMES: + mix = None + src = [] + for dirname in dirnames: + waveform = get_whitenoise( + sample_rate=8000, duration=1, n_channels=1, dtype="int16", seed=seed + ) + seed += 1 + + path = os.path.join(root_dir, dirname, filename) + save_wav(path, waveform, sample_rate) + waveform = normalize_wav(waveform) + + if dirname == "mix": + mix = waveform + else: + src.append(waveform) + expected.append((sample_rate, mix, src)) + return expected + + +class TestWSJ0Mix2(TempDirMixin, TorchaudioTestCase): + backend = "default" + root_dir = None + expected = None + + @classmethod + def setUpClass(cls): + cls.root_dir = cls.get_base_temp_dir() + cls.expected = _mock_dataset(cls.root_dir, 2) + + def test_wsj0mix(self): + dataset = wsj0mix.WSJ0Mix(self.root_dir, num_speakers=2, sample_rate=8000) + + n_ite = 0 + for i, sample in enumerate(dataset): + (_, sample_mix, sample_src) = sample + (_, expected_mix, expected_src) = self.expected[i] + self.assertEqual(sample_mix, expected_mix, atol=5e-5, rtol=1e-8) + self.assertEqual(sample_src[0], expected_src[0], atol=5e-5, rtol=1e-8) + self.assertEqual(sample_src[1], expected_src[1], atol=5e-5, rtol=1e-8) + n_ite += 1 + assert n_ite == len(self.expected) + + +class TestWSJ0Mix3(TempDirMixin, TorchaudioTestCase): + backend = "default" + root_dir = None + expected = None + + @classmethod + def setUpClass(cls): + cls.root_dir = cls.get_base_temp_dir() + cls.expected = _mock_dataset(cls.root_dir, 3) + + def test_wsj0mix(self): + dataset = wsj0mix.WSJ0Mix(self.root_dir, num_speakers=3, sample_rate=8000) + + n_ite = 0 + for i, sample in enumerate(dataset): + (_, sample_mix, sample_src) = sample + (_, expected_mix, expected_src) = self.expected[i] + self.assertEqual(sample_mix, expected_mix, atol=5e-5, rtol=1e-8) + self.assertEqual(sample_src[0], expected_src[0], atol=5e-5, rtol=1e-8) + self.assertEqual(sample_src[1], expected_src[1], atol=5e-5, rtol=1e-8) + self.assertEqual(sample_src[2], expected_src[2], atol=5e-5, rtol=1e-8) + n_ite += 1 + assert n_ite == len(self.expected) diff --git a/test/torchaudio_unittest/io_test.py b/test/torchaudio_unittest/io_test.py index e30f4c3fd3..3dbc419bde 100644 --- a/test/torchaudio_unittest/io_test.py +++ b/test/torchaudio_unittest/io_test.py @@ -45,6 +45,9 @@ class Test_LoadSave(unittest.TestCase): test_filepath_wav = os.path.join(test_dirpath, "assets", "steam-train-whistle-daniel_simon.wav") + def setUp(self): + torchaudio.USE_SOUNDFILE_LEGACY_INTERFACE = True + def test_1_save(self): for backend in BACKENDS_MP3: with self.subTest(): diff --git a/test/torchaudio_unittest/models_test.py b/test/torchaudio_unittest/models_test.py index f9e96edd27..484ec6c10c 100644 --- a/test/torchaudio_unittest/models_test.py +++ b/test/torchaudio_unittest/models_test.py @@ -1,6 +1,10 @@ -import torch -from torchaudio.models import Wav2Letter, MelResNet, UpsampleNetwork, WaveRNN +import itertools +from collections import namedtuple +import torch +from parameterized import parameterized +from torchaudio.models import ConvTasNet, Wav2Letter, WaveRNN +from torchaudio.models.wavernn import MelResNet, UpsampleNetwork from torchaudio_unittest import common_utils @@ -115,3 +119,58 @@ def test_waveform(self): out = model(x, mels) assert out.size() == (n_batch, 1, hop_length * (n_time - kernel_size + 1), n_classes) + + +_ConvTasNetParams = namedtuple( + '_ConvTasNetParams', + [ + 'enc_num_feats', + 'enc_kernel_size', + 'msk_num_feats', + 'msk_num_hidden_feats', + 'msk_kernel_size', + 'msk_num_layers', + 'msk_num_stacks', + ] +) + + +class TestConvTasNet(common_utils.TorchaudioTestCase): + @parameterized.expand(list(itertools.product( + [2, 3], + [ + _ConvTasNetParams(128, 40, 128, 256, 3, 7, 2), + _ConvTasNetParams(256, 40, 128, 256, 3, 7, 2), + _ConvTasNetParams(512, 40, 128, 256, 3, 7, 2), + _ConvTasNetParams(512, 40, 128, 256, 3, 7, 2), + _ConvTasNetParams(512, 40, 128, 512, 3, 7, 2), + _ConvTasNetParams(512, 40, 128, 512, 3, 7, 2), + _ConvTasNetParams(512, 40, 256, 256, 3, 7, 2), + _ConvTasNetParams(512, 40, 256, 512, 3, 7, 2), + _ConvTasNetParams(512, 40, 256, 512, 3, 7, 2), + _ConvTasNetParams(512, 40, 128, 512, 3, 6, 4), + _ConvTasNetParams(512, 40, 128, 512, 3, 4, 6), + _ConvTasNetParams(512, 40, 128, 512, 3, 8, 3), + _ConvTasNetParams(512, 32, 128, 512, 3, 8, 3), + _ConvTasNetParams(512, 16, 128, 512, 3, 8, 3), + ], + ))) + def test_paper_configuration(self, num_sources, model_params): + """ConvTasNet model works on the valid configurations in the paper""" + batch_size = 32 + num_frames = 8000 + + model = ConvTasNet( + num_sources=num_sources, + enc_kernel_size=model_params.enc_kernel_size, + enc_num_feats=model_params.enc_num_feats, + msk_kernel_size=model_params.msk_kernel_size, + msk_num_feats=model_params.msk_num_feats, + msk_num_hidden_feats=model_params.msk_num_hidden_feats, + msk_num_layers=model_params.msk_num_layers, + msk_num_stacks=model_params.msk_num_stacks, + ) + tensor = torch.rand(batch_size, 1, num_frames) + output = model(tensor) + + assert output.shape == (batch_size, num_sources, num_frames) diff --git a/test/torchaudio_unittest/soundfile_backend/__init__.py b/test/torchaudio_unittest/soundfile_backend/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/test/torchaudio_unittest/soundfile_backend/common.py b/test/torchaudio_unittest/soundfile_backend/common.py new file mode 100644 index 0000000000..4da0873fa1 --- /dev/null +++ b/test/torchaudio_unittest/soundfile_backend/common.py @@ -0,0 +1,34 @@ +import itertools +from unittest import skipIf + +from parameterized import parameterized +from torchaudio._internal.module_utils import is_module_available + + +def name_func(func, _, params): + return f'{func.__name__}_{"_".join(str(arg) for arg in params.args)}' + + +def dtype2subtype(dtype): + return { + "float64": "DOUBLE", + "float32": "FLOAT", + "int32": "PCM_32", + "int16": "PCM_16", + "uint8": "PCM_U8", + "int8": "PCM_S8", + }[dtype] + + +def skipIfFormatNotSupported(fmt): + fmts = [] + if is_module_available("soundfile"): + import soundfile + + fmts = soundfile.available_formats() + return skipIf(fmt not in fmts, f'"{fmt}" is not supported by sondfile') + return skipIf(True, '"soundfile" not available.') + + +def parameterize(*params): + return parameterized.expand(list(itertools.product(*params)), name_func=name_func) diff --git a/test/torchaudio_unittest/soundfile_backend/info_test.py b/test/torchaudio_unittest/soundfile_backend/info_test.py new file mode 100644 index 0000000000..71acb20689 --- /dev/null +++ b/test/torchaudio_unittest/soundfile_backend/info_test.py @@ -0,0 +1,95 @@ +import torch +from torchaudio.backend import _soundfile_backend as soundfile_backend +from torchaudio._internal import module_utils as _mod_utils + +from torchaudio_unittest.common_utils import ( + TempDirMixin, + PytorchTestCase, + skipIfNoModule, + get_wav_data, + save_wav, +) +from .common import skipIfFormatNotSupported, parameterize + +if _mod_utils.is_module_available("soundfile"): + import soundfile + + +@skipIfNoModule("soundfile") +class TestInfo(TempDirMixin, PytorchTestCase): + @parameterize( + ["float32", "int32", "int16", "uint8"], [8000, 16000], [1, 2], + ) + def test_wav(self, dtype, sample_rate, num_channels): + """`soundfile_backend.info` can check wav file correctly""" + duration = 1 + path = self.get_temp_path("data.wav") + data = get_wav_data( + dtype, num_channels, normalize=False, num_frames=duration * sample_rate + ) + save_wav(path, data, sample_rate) + info = soundfile_backend.info(path) + assert info.sample_rate == sample_rate + assert info.num_frames == sample_rate * duration + assert info.num_channels == num_channels + + @parameterize( + ["float32", "int32", "int16", "uint8"], [8000, 16000], [4, 8, 16, 32], + ) + def test_wav_multiple_channels(self, dtype, sample_rate, num_channels): + """`soundfile_backend.info` can check wav file with channels more than 2 correctly""" + duration = 1 + path = self.get_temp_path("data.wav") + data = get_wav_data( + dtype, num_channels, normalize=False, num_frames=duration * sample_rate + ) + save_wav(path, data, sample_rate) + info = soundfile_backend.info(path) + assert info.sample_rate == sample_rate + assert info.num_frames == sample_rate * duration + assert info.num_channels == num_channels + + @parameterize([8000, 16000], [1, 2]) + @skipIfFormatNotSupported("FLAC") + def test_flac(self, sample_rate, num_channels): + """`soundfile_backend.info` can check flac file correctly""" + duration = 1 + num_frames = sample_rate * duration + data = torch.randn(num_frames, num_channels).numpy() + path = self.get_temp_path("data.flac") + soundfile.write(path, data, sample_rate) + + info = soundfile_backend.info(path) + assert info.sample_rate == sample_rate + assert info.num_frames == num_frames + assert info.num_channels == num_channels + + @parameterize([8000, 16000], [1, 2]) + @skipIfFormatNotSupported("OGG") + def test_ogg(self, sample_rate, num_channels): + """`soundfile_backend.info` can check ogg file correctly""" + duration = 1 + num_frames = sample_rate * duration + data = torch.randn(num_frames, num_channels).numpy() + path = self.get_temp_path("data.ogg") + soundfile.write(path, data, sample_rate) + + info = soundfile_backend.info(path) + assert info.sample_rate == sample_rate + assert info.num_frames == sample_rate * duration + assert info.num_channels == num_channels + + @parameterize([8000, 16000], [1, 2]) + @skipIfFormatNotSupported("NIST") + def test_sphere(self, sample_rate, num_channels): + """`soundfile_backend.info` can check sph file correctly""" + duration = 1 + num_frames = sample_rate * duration + data = torch.randn(num_frames, num_channels).numpy() + path = self.get_temp_path("data.nist") + soundfile.write(path, data, sample_rate) + + info = soundfile_backend.info(path) + assert info.sample_rate == sample_rate + assert info.num_frames == sample_rate * duration + assert info.num_channels == num_channels diff --git a/test/torchaudio_unittest/soundfile_backend/load_test.py b/test/torchaudio_unittest/soundfile_backend/load_test.py new file mode 100644 index 0000000000..8860263eed --- /dev/null +++ b/test/torchaudio_unittest/soundfile_backend/load_test.py @@ -0,0 +1,265 @@ +import itertools +from unittest.mock import patch + +import torch +from torchaudio._internal import module_utils as _mod_utils +from torchaudio.backend import _soundfile_backend as soundfile_backend +from parameterized import parameterized + +from torchaudio_unittest.common_utils import ( + TempDirMixin, + PytorchTestCase, + skipIfNoModule, + get_wav_data, + normalize_wav, + load_wav, + save_wav, +) +from .common import ( + parameterize, + dtype2subtype, + skipIfFormatNotSupported, +) + +if _mod_utils.is_module_available("soundfile"): + import soundfile + + +def _get_mock_path( + ext: str, dtype: str, sample_rate: int, num_channels: int, num_frames: int, +): + return f"{dtype}_{sample_rate}_{num_channels}_{num_frames}.{ext}" + + +def _get_mock_params(path: str): + filename, ext = path.split(".") + parts = filename.split("_") + return { + "ext": ext, + "dtype": parts[0], + "sample_rate": int(parts[1]), + "num_channels": int(parts[2]), + "num_frames": int(parts[3]), + } + + +class SoundFileMock: + def __init__(self, path, mode): + assert mode == "r" + self.path = path + self._params = _get_mock_params(path) + self._start = None + + @property + def samplerate(self): + return self._params["sample_rate"] + + @property + def format(self): + if self._params["ext"] == "wav": + return "WAV" + if self._params["ext"] == "flac": + return "FLAC" + if self._params["ext"] == "ogg": + return "OGG" + if self._params["ext"] in ["sph", "nis", "nist"]: + return "NIST" + + @property + def subtype(self): + if self._params["ext"] == "ogg": + return "VORBIS" + return dtype2subtype(self._params["dtype"]) + + def _prepare_read(self, start, stop, frames): + assert stop is None + self._start = start + return frames + + def read(self, frames, dtype, always_2d): + assert always_2d + data = get_wav_data( + dtype, + self._params["num_channels"], + normalize=False, + num_frames=self._params["num_frames"], + channels_first=False, + ).numpy() + return data[self._start:self._start + frames] + + def __enter__(self): + return self + + def __exit__(self, *args, **kwargs): + pass + + +class MockedLoadTest(PytorchTestCase): + def assert_dtype( + self, ext, dtype, sample_rate, num_channels, normalize, channels_first + ): + """When format is WAV or NIST, normalize=False will return the native dtype Tensor, otherwise float32""" + num_frames = 3 * sample_rate + path = _get_mock_path(ext, dtype, sample_rate, num_channels, num_frames) + expected_dtype = ( + torch.float32 + if normalize or ext not in ["wav", "nist"] + else getattr(torch, dtype) + ) + with patch("soundfile.SoundFile", SoundFileMock): + found, sr = soundfile_backend.load( + path, normalize=normalize, channels_first=channels_first + ) + assert found.dtype == expected_dtype + assert sample_rate == sr + + @parameterize( + ["uint8", "int16", "int32", "float32", "float64"], + [8000, 16000], + [1, 2], + [True, False], + [True, False], + ) + def test_wav(self, dtype, sample_rate, num_channels, normalize, channels_first): + """Returns native dtype when normalize=False else float32""" + self.assert_dtype( + "wav", dtype, sample_rate, num_channels, normalize, channels_first + ) + + @parameterize( + ["int8", "int16", "int32"], [8000, 16000], [1, 2], [True, False], [True, False], + ) + def test_sphere(self, dtype, sample_rate, num_channels, normalize, channels_first): + """Returns float32 always""" + self.assert_dtype( + "sph", dtype, sample_rate, num_channels, normalize, channels_first + ) + + @parameterize([8000, 16000], [1, 2], [True, False], [True, False]) + def test_ogg(self, sample_rate, num_channels, normalize, channels_first): + """Returns float32 always""" + self.assert_dtype( + "ogg", "int16", sample_rate, num_channels, normalize, channels_first + ) + + @parameterize([8000, 16000], [1, 2], [True, False], [True, False]) + def test_flac(self, sample_rate, num_channels, normalize, channels_first): + """`soundfile_backend.load` can load ogg format.""" + self.assert_dtype( + "flac", "int16", sample_rate, num_channels, normalize, channels_first + ) + + +class LoadTestBase(TempDirMixin, PytorchTestCase): + def assert_wav( + self, + dtype, + sample_rate, + num_channels, + normalize, + channels_first=True, + duration=1, + ): + """`soundfile_backend.load` can load wav format correctly. + + Wav data loaded with soundfile backend should match those with scipy + """ + path = self.get_temp_path("reference.wav") + num_frames = duration * sample_rate + data = get_wav_data( + dtype, + num_channels, + normalize=normalize, + num_frames=num_frames, + channels_first=channels_first, + ) + save_wav(path, data, sample_rate, channels_first=channels_first) + expected = load_wav(path, normalize=normalize, channels_first=channels_first)[0] + data, sr = soundfile_backend.load( + path, normalize=normalize, channels_first=channels_first + ) + assert sr == sample_rate + self.assertEqual(data, expected) + + def assert_sphere( + self, dtype, sample_rate, num_channels, channels_first=True, duration=1, + ): + """`soundfile_backend.load` can load SPHERE format correctly.""" + path = self.get_temp_path("reference.sph") + num_frames = duration * sample_rate + raw = get_wav_data( + dtype, + num_channels, + num_frames=num_frames, + normalize=False, + channels_first=False, + ) + soundfile.write( + path, raw, sample_rate, subtype=dtype2subtype(dtype), format="NIST" + ) + expected = normalize_wav(raw.t() if channels_first else raw) + data, sr = soundfile_backend.load(path, channels_first=channels_first) + assert sr == sample_rate + self.assertEqual(data, expected, atol=1e-4, rtol=1e-8) + + def assert_flac( + self, dtype, sample_rate, num_channels, channels_first=True, duration=1, + ): + """`soundfile_backend.load` can load FLAC format correctly.""" + path = self.get_temp_path("reference.flac") + num_frames = duration * sample_rate + raw = get_wav_data( + dtype, + num_channels, + num_frames=num_frames, + normalize=False, + channels_first=False, + ) + soundfile.write(path, raw, sample_rate) + expected = normalize_wav(raw.t() if channels_first else raw) + data, sr = soundfile_backend.load(path, channels_first=channels_first) + assert sr == sample_rate + self.assertEqual(data, expected, atol=1e-4, rtol=1e-8) + + +@skipIfNoModule("soundfile") +class TestLoad(LoadTestBase): + """Test the correctness of `soundfile_backend.load` for various formats""" + + @parameterize( + ["float32", "int32", "int16"], + [8000, 16000], + [1, 2], + [False, True], + [False, True], + ) + def test_wav(self, dtype, sample_rate, num_channels, normalize, channels_first): + """`soundfile_backend.load` can load wav format correctly.""" + self.assert_wav(dtype, sample_rate, num_channels, normalize, channels_first) + + @parameterize( + ["int16"], [16000], [2], [False], + ) + def test_wav_large(self, dtype, sample_rate, num_channels, normalize): + """`soundfile_backend.load` can load large wav file correctly.""" + two_hours = 2 * 60 * 60 + self.assert_wav(dtype, sample_rate, num_channels, normalize, duration=two_hours) + + @parameterize(["float32", "int32", "int16"], [4, 8, 16, 32], [False, True]) + def test_multiple_channels(self, dtype, num_channels, channels_first): + """`soundfile_backend.load` can load wav file with more than 2 channels.""" + sample_rate = 8000 + normalize = False + self.assert_wav(dtype, sample_rate, num_channels, normalize, channels_first) + + @parameterize(["int32", "int16"], [8000, 16000], [1, 2], [False, True]) + @skipIfFormatNotSupported("NIST") + def test_sphere(self, dtype, sample_rate, num_channels, channels_first): + """`soundfile_backend.load` can load sphere format correctly.""" + self.assert_sphere(dtype, sample_rate, num_channels, channels_first) + + @parameterize(["int32", "int16"], [8000, 16000], [1, 2], [False, True]) + @skipIfFormatNotSupported("FLAC") + def test_flac(self, dtype, sample_rate, num_channels, channels_first): + """`soundfile_backend.load` can load flac format correctly.""" + self.assert_flac(dtype, sample_rate, num_channels, channels_first) diff --git a/test/torchaudio_unittest/soundfile_backend/save_test.py b/test/torchaudio_unittest/soundfile_backend/save_test.py new file mode 100644 index 0000000000..a99c69b0c8 --- /dev/null +++ b/test/torchaudio_unittest/soundfile_backend/save_test.py @@ -0,0 +1,211 @@ +import itertools +from unittest.mock import patch + +from torchaudio._internal import module_utils as _mod_utils +from torchaudio.backend import _soundfile_backend as soundfile_backend +from parameterized import parameterized + +from torchaudio_unittest.common_utils import ( + TempDirMixin, + PytorchTestCase, + skipIfNoModule, + get_wav_data, + load_wav, +) +from .common import parameterize, dtype2subtype, skipIfFormatNotSupported + +if _mod_utils.is_module_available("soundfile"): + import soundfile + + +class MockedSaveTest(PytorchTestCase): + @parameterize( + ["float32", "int32", "int16", "uint8"], [8000, 16000], [1, 2], [False, True], + ) + @patch("soundfile.write") + def test_wav(self, dtype, sample_rate, num_channels, channels_first, mocked_write): + """soundfile_backend.save passes correct subtype to soundfile.write when WAV""" + filepath = "foo.wav" + input_tensor = get_wav_data( + dtype, + num_channels, + num_frames=3 * sample_rate, + normalize=dtype == "flaot32", + channels_first=channels_first, + ).t() + + soundfile_backend.save( + filepath, input_tensor, sample_rate, channels_first=channels_first + ) + + # on +Py3.8 call_args.kwargs is more descreptive + args = mocked_write.call_args[1] + assert args["file"] == filepath + assert args["samplerate"] == sample_rate + assert args["subtype"] == dtype2subtype(dtype) + assert args["format"] is None + self.assertEqual( + args["data"], input_tensor.t() if channels_first else input_tensor + ) + + @patch("soundfile.write") + def assert_non_wav( + self, fmt, dtype, sample_rate, num_channels, channels_first, mocked_write + ): + """soundfile_backend.save passes correct subtype and format to soundfile.write when SPHERE""" + filepath = f"foo.{fmt}" + input_tensor = get_wav_data( + dtype, + num_channels, + num_frames=3 * sample_rate, + normalize=False, + channels_first=channels_first, + ).t() + expected_data = input_tensor.t() if channels_first else input_tensor + + soundfile_backend.save( + filepath, input_tensor, sample_rate, channels_first=channels_first + ) + + # on +Py3.8 call_args.kwargs is more descreptive + args = mocked_write.call_args[1] + assert args["file"] == filepath + assert args["samplerate"] == sample_rate + assert args["subtype"] is None + if fmt in ["sph", "nist", "nis"]: + assert args["format"] == "NIST" + else: + assert args["format"] is None + self.assertEqual(args["data"], expected_data) + + @parameterize( + ["sph", "nist", "nis"], + ["int32", "int16"], + [8000, 16000], + [1, 2], + [False, True], + ) + def test_sph(self, fmt, dtype, sample_rate, num_channels, channels_first): + """soundfile_backend.save passes default format and subtype (None-s) to + soundfile.write when not WAV""" + self.assert_non_wav(fmt, dtype, sample_rate, num_channels, channels_first) + + @parameterize( + ["int32", "int16"], [8000, 16000], [1, 2], [False, True], + ) + def test_flac(self, dtype, sample_rate, num_channels, channels_first): + """soundfile_backend.save passes default format and subtype (None-s) to + soundfile.write when not WAV""" + self.assert_non_wav("flac", dtype, sample_rate, num_channels, channels_first) + + @parameterize( + ["int32", "int16"], [8000, 16000], [1, 2], [False, True], + ) + def test_ogg(self, dtype, sample_rate, num_channels, channels_first): + """soundfile_backend.save passes default format and subtype (None-s) to + soundfile.write when not WAV""" + self.assert_non_wav("ogg", dtype, sample_rate, num_channels, channels_first) + + +@skipIfNoModule("soundfile") +class SaveTestBase(TempDirMixin, PytorchTestCase): + def assert_wav(self, dtype, sample_rate, num_channels, num_frames): + """`soundfile_backend.save` can save wav format.""" + path = self.get_temp_path("data.wav") + expected = get_wav_data( + dtype, num_channels, num_frames=num_frames, normalize=False + ) + soundfile_backend.save(path, expected, sample_rate) + found, sr = load_wav(path, normalize=False) + assert sample_rate == sr + self.assertEqual(found, expected) + + def _assert_non_wav(self, fmt, dtype, sample_rate, num_channels): + """`soundfile_backend.save` can save non-wav format. + + Due to precision missmatch, and the lack of alternative way to decode the + resulting files without using soundfile, only meta data are validated. + """ + num_frames = sample_rate * 3 + path = self.get_temp_path(f"data.{fmt}") + expected = get_wav_data( + dtype, num_channels, num_frames=num_frames, normalize=False + ) + soundfile_backend.save(path, expected, sample_rate) + sinfo = soundfile.info(path) + assert sinfo.format == fmt.upper() + assert sinfo.frames == num_frames + assert sinfo.channels == num_channels + assert sinfo.samplerate == sample_rate + + def assert_flac(self, dtype, sample_rate, num_channels): + """`soundfile_backend.save` can save flac format.""" + self._assert_non_wav("flac", dtype, sample_rate, num_channels) + + def assert_sphere(self, dtype, sample_rate, num_channels): + """`soundfile_backend.save` can save sph format.""" + self._assert_non_wav("nist", dtype, sample_rate, num_channels) + + def assert_ogg(self, dtype, sample_rate, num_channels): + """`soundfile_backend.save` can save ogg format. + + As we cannot inspect the OGG format (it's lossy), we only check the metadata. + """ + self._assert_non_wav("ogg", dtype, sample_rate, num_channels) + + +@skipIfNoModule("soundfile") +class TestSave(SaveTestBase): + @parameterize( + ["float32", "int32", "int16"], [8000, 16000], [1, 2], + ) + def test_wav(self, dtype, sample_rate, num_channels): + """`soundfile_backend.save` can save wav format.""" + self.assert_wav(dtype, sample_rate, num_channels, num_frames=None) + + @parameterize( + ["float32", "int32", "int16"], [4, 8, 16, 32], + ) + def test_multiple_channels(self, dtype, num_channels): + """`soundfile_backend.save` can save wav with more than 2 channels.""" + sample_rate = 8000 + self.assert_wav(dtype, sample_rate, num_channels, num_frames=None) + + @parameterize( + ["int32", "int16"], [8000, 16000], [1, 2], + ) + @skipIfFormatNotSupported("NIST") + def test_sphere(self, dtype, sample_rate, num_channels): + """`soundfile_backend.save` can save sph format.""" + self.assert_sphere(dtype, sample_rate, num_channels) + + @parameterize( + [8000, 16000], [1, 2], + ) + @skipIfFormatNotSupported("FLAC") + def test_flac(self, sample_rate, num_channels): + """`soundfile_backend.save` can save flac format.""" + self.assert_flac("float32", sample_rate, num_channels) + + @parameterize( + [8000, 16000], [1, 2], + ) + @skipIfFormatNotSupported("OGG") + def test_ogg(self, sample_rate, num_channels): + """`soundfile_backend.save` can save ogg/vorbis format.""" + self.assert_ogg("float32", sample_rate, num_channels) + + +@skipIfNoModule("soundfile") +class TestSaveParams(TempDirMixin, PytorchTestCase): + """Test the correctness of optional parameters of `soundfile_backend.save`""" + + @parameterize([(True,), (False,)]) + def test_channels_first(self, channels_first): + """channels_first swaps axes""" + path = self.get_temp_path("data.wav") + data = get_wav_data("int32", 2, channels_first=channels_first) + soundfile_backend.save(path, data, 8000, channels_first=channels_first) + found = load_wav(path)[0] + expected = data if channels_first else data.transpose(1, 0) + self.assertEqual(found, expected, atol=1e-4, rtol=1e-8) diff --git a/test/torchaudio_unittest/sox_effect/sox_effects_chain_test.py b/test/torchaudio_unittest/sox_effect/sox_effects_chain_test.py deleted file mode 100644 index 765ab62094..0000000000 --- a/test/torchaudio_unittest/sox_effect/sox_effects_chain_test.py +++ /dev/null @@ -1,224 +0,0 @@ -import sys -import math -import unittest - -import torch -import torchaudio - -from .. import common_utils - - -@common_utils.skipIfNoSoxBackend -class Test_SoxEffectsChain(common_utils.TorchaudioTestCase): - backend = 'sox' - - test_filepath = common_utils.get_asset_path("steam-train-whistle-daniel_simon.wav") - - def test_single_channel(self): - fn_sine = common_utils.get_asset_path("sinewave.wav") - E = torchaudio.sox_effects.SoxEffectsChain() - E.set_input_file(fn_sine) - E.append_effect_to_chain("echos", [0.8, 0.7, 40, 0.25, 63, 0.3]) - x, sr = E.sox_build_flow_effects() - # check if effects worked - # print(x.size()) - - def test_rate_channels(self): - target_rate = 16000 - target_channels = 1 - E = torchaudio.sox_effects.SoxEffectsChain() - E.set_input_file(self.test_filepath) - E.append_effect_to_chain("rate", [target_rate]) - E.append_effect_to_chain("channels", [target_channels]) - x, sr = E.sox_build_flow_effects() - # check if effects worked - self.assertEqual(sr, target_rate) - self.assertEqual(x.size(0), target_channels) - - @unittest.skipIf(sys.platform == 'darwin', 'This test is known to fail on macOS') - def test_lowpass_speed(self): - speed = .8 - si, _ = torchaudio.info(self.test_filepath) - E = torchaudio.sox_effects.SoxEffectsChain() - E.set_input_file(self.test_filepath) - E.append_effect_to_chain("lowpass", 100) - E.append_effect_to_chain("speed", speed) - E.append_effect_to_chain("rate", si.rate) - x, sr = E.sox_build_flow_effects() - # check if effects worked, add small tolerance for rounding effects - self.assertEqual(x.size(1), int((si.length / si.channels) / speed), atol=1, rtol=1e-8) - - def test_ulaw_and_siginfo(self): - si_out = torchaudio.sox_signalinfo_t() - ei_out = torchaudio.sox_encodinginfo_t() - si_out.precision = 8 - ei_out.encoding = torchaudio.get_sox_encoding_t(9) - ei_out.bits_per_sample = 8 - si_in, ei_in = torchaudio.info(self.test_filepath) - si_out.rate = 44100 - si_out.channels = 2 - E = torchaudio.sox_effects.SoxEffectsChain(out_siginfo=si_out, out_encinfo=ei_out) - E.set_input_file(self.test_filepath) - x, sr = E.sox_build_flow_effects() - # Note: the output was encoded into ulaw because the - # number of unique values in the output is less than 256. - self.assertLess(x.unique().size(0), 2**8 + 1) - self.assertEqual(x.numel(), si_in.length) - - def test_band_chorus(self): - si_in, ei_in = torchaudio.info(self.test_filepath) - ei_in.encoding = torchaudio.get_sox_encoding_t(1) - E = torchaudio.sox_effects.SoxEffectsChain(out_encinfo=ei_in, out_siginfo=si_in) - E.set_input_file(self.test_filepath) - E.append_effect_to_chain("band", ["-n", "10k", "3.5k"]) - E.append_effect_to_chain("chorus", [.5, .7, 55, 0.4, .25, 2, '-s']) - E.append_effect_to_chain("rate", [si_in.rate]) - E.append_effect_to_chain("channels", [si_in.channels]) - x, sr = E.sox_build_flow_effects() - # The chorus effect will make the output file longer than the input - self.assertEqual(x.size(0), si_in.channels) - self.assertGreaterEqual(x.size(1) * x.size(0), si_in.length) - - def test_synth(self): - si_in, ei_in = torchaudio.info(self.test_filepath) - len_in_seconds = si_in.length / si_in.channels / si_in.rate - ei_in.encoding = torchaudio.get_sox_encoding_t(1) - E = torchaudio.sox_effects.SoxEffectsChain(out_encinfo=ei_in, out_siginfo=si_in) - E.set_input_file(self.test_filepath) - E.append_effect_to_chain("synth", [str(len_in_seconds), "pinknoise", "mix"]) - E.append_effect_to_chain("rate", [44100]) - E.append_effect_to_chain("channels", [2]) - x, sr = E.sox_build_flow_effects() - self.assertEqual(x.size(0), si_in.channels) - self.assertEqual(si_in.length, x.size(0) * x.size(1)) - - def test_gain(self): - E = torchaudio.sox_effects.SoxEffectsChain() - E.set_input_file(self.test_filepath) - E.append_effect_to_chain("gain", ["5"]) - x, sr = E.sox_build_flow_effects() - E.clear_chain() - self.assertTrue(x.abs().max().item(), 1.) - E.set_input_file(self.test_filepath) - E.append_effect_to_chain("gain", ["-e", "-5"]) - x, sr = E.sox_build_flow_effects() - E.clear_chain() - self.assertLess(x.abs().max().item(), 1.) - E.set_input_file(self.test_filepath) - E.append_effect_to_chain("gain", ["-b", "8"]) - x, sr = E.sox_build_flow_effects() - E.clear_chain() - self.assertTrue(x.abs().max().item(), 1.) - E.set_input_file(self.test_filepath) - E.append_effect_to_chain("gain", ["-n", "-10"]) - x, sr = E.sox_build_flow_effects() - E.clear_chain() - self.assertLess(x.abs().max().item(), 1.) - - def test_tempo_or_speed(self): - tempo = .8 - si, _ = torchaudio.info(self.test_filepath) - E = torchaudio.sox_effects.SoxEffectsChain() - E.set_input_file(self.test_filepath) - E.append_effect_to_chain("tempo", ["-s", tempo]) - x, sr = E.sox_build_flow_effects() - # check if effect worked - self.assertAlmostEqual(x.size(1), math.ceil((si.length / si.channels) / tempo), delta=1) - # tempo > 1 - E.clear_chain() - tempo = 1.2 - E.append_effect_to_chain("tempo", ["-s", tempo]) - x, sr = E.sox_build_flow_effects() - # check if effect worked - self.assertAlmostEqual(x.size(1), math.ceil((si.length / si.channels) / tempo), delta=1) - # tempo > 1 - E.clear_chain() - speed = 1.2 - E.append_effect_to_chain("speed", [speed]) - E.append_effect_to_chain("rate", [si.rate]) - x, sr = E.sox_build_flow_effects() - # check if effect worked - self.assertAlmostEqual(x.size(1), math.ceil((si.length / si.channels) / speed), delta=1) - # speed < 1 - E.clear_chain() - speed = 0.8 - E.append_effect_to_chain("speed", [speed]) - E.append_effect_to_chain("rate", [si.rate]) - x, sr = E.sox_build_flow_effects() - # check if effect worked - self.assertAlmostEqual(x.size(1), math.ceil((si.length / si.channels) / speed), delta=1) - - def test_trim(self): - x_orig, _ = torchaudio.load(self.test_filepath) - offset = "10000s" - offset_int = int(offset[:-1]) - num_frames = "20000s" - num_frames_int = int(num_frames[:-1]) - E = torchaudio.sox_effects.SoxEffectsChain() - E.set_input_file(self.test_filepath) - E.append_effect_to_chain("trim", [offset, num_frames]) - x, sr = E.sox_build_flow_effects() - # check if effect worked - self.assertTrue(x.allclose(x_orig[:, offset_int:(offset_int + num_frames_int)], rtol=1e-4, atol=1e-4)) - - def test_silence_contrast(self): - si, _ = torchaudio.info(self.test_filepath) - E = torchaudio.sox_effects.SoxEffectsChain() - E.set_input_file(self.test_filepath) - E.append_effect_to_chain("silence", [1, 100, 1]) - E.append_effect_to_chain("contrast", []) - x, sr = E.sox_build_flow_effects() - # check if effect worked - self.assertLess(x.numel(), si.length) - - def test_reverse(self): - x_orig, _ = torchaudio.load(self.test_filepath) - E = torchaudio.sox_effects.SoxEffectsChain() - E.set_input_file(self.test_filepath) - E.append_effect_to_chain("reverse", "") - x_rev, _ = E.sox_build_flow_effects() - # check if effect worked - rev_idx = torch.LongTensor(range(x_orig.size(1))[::-1]) - self.assertTrue(x_orig.allclose(x_rev[:, rev_idx], rtol=1e-5, atol=2e-5)) - - def test_compand_fade(self): - E = torchaudio.sox_effects.SoxEffectsChain() - E.set_input_file(self.test_filepath) - E.append_effect_to_chain("compand", ["0.3,1", "6:-70,-60,-20", "-5", "-90", "0.2"]) - E.append_effect_to_chain("fade", ["q", "0.25", "0", "0.33"]) - x, _ = E.sox_build_flow_effects() - # check if effect worked - # print(x.size()) - - def test_biquad_delay(self): - si, _ = torchaudio.info(self.test_filepath) - E = torchaudio.sox_effects.SoxEffectsChain() - E.set_input_file(self.test_filepath) - E.append_effect_to_chain("biquad", ["0.25136437", "0.50272873", "0.25136437", - "1.0", "-0.17123075", "0.17668821"]) - E.append_effect_to_chain("delay", ["15000s"]) - x, _ = E.sox_build_flow_effects() - # check if effect worked - self.assertTrue(x.size(1) == (si.length / si.channels) + 15000) - - def test_invalid_effect_name(self): - E = torchaudio.sox_effects.SoxEffectsChain() - E.set_input_file(self.test_filepath) - # there is no effect named "special" - with self.assertRaises(LookupError): - E.append_effect_to_chain("special", [""]) - - def test_unimplemented_effect(self): - E = torchaudio.sox_effects.SoxEffectsChain() - E.set_input_file(self.test_filepath) - # the sox spectrogram function is not implemented in torchaudio - with self.assertRaises(NotImplementedError): - E.append_effect_to_chain("spectrogram", [""]) - - def test_invalid_effect_options(self): - E = torchaudio.sox_effects.SoxEffectsChain() - E.set_input_file(self.test_filepath) - # first two options should be combined to "0.3,1" - E.append_effect_to_chain("compand", ["0.3", "1", "6:-70,-60,-20", "-5", "-90", "0.2"]) - with self.assertRaises(RuntimeError): - E.sox_build_flow_effects() diff --git a/torchaudio/__init__.py b/torchaudio/__init__.py index 9a6a5e3c16..be46d8a0f6 100644 --- a/torchaudio/__init__.py +++ b/torchaudio/__init__.py @@ -8,6 +8,9 @@ sox_effects, transforms ) + +USE_SOUNDFILE_LEGACY_INTERFACE = None + from torchaudio.backend import ( list_audio_backends, get_audio_backend, @@ -21,36 +24,8 @@ SignalInfo, EncodingInfo, ) -from torchaudio.sox_effects import ( - init_sox_effects as _init_sox_effects, - shutdown_sox_effects as _shutdown_sox_effects, -) try: from .version import __version__, git_version # noqa: F401 except ImportError: pass - - -@_mod_utils.deprecated( - "Please remove the function call to initialize_sox. " - "Resource initialization is now automatically handled.") -def initialize_sox(): - """Initialize sox effects. - - This function is deprecated. See :py:func:`torchaudio.sox_effects.init_sox_effects` - """ - _init_sox_effects() - - -@_mod_utils.deprecated( - "Please remove the function call to torchaudio.shutdown_sox. " - "Resource clean up is now automatically handled. " - "In the unlikely event that you need to manually shutdown sox, " - "please use torchaudio.sox_effects.shutdown_sox_effects.") -def shutdown_sox(): - """Shutdown sox effects. - - This function is deprecated. See :py:func:`torchaudio.sox_effects.shutdown_sox_effects` - """ - _shutdown_sox_effects() diff --git a/torchaudio/backend/_soundfile_backend.py b/torchaudio/backend/_soundfile_backend.py new file mode 100644 index 0000000000..83d3cbc3cf --- /dev/null +++ b/torchaudio/backend/_soundfile_backend.py @@ -0,0 +1,223 @@ +"""The new soundfile backend which will become default in 0.8.0 onward""" +from typing import Tuple, Optional +import warnings + +import torch +from torchaudio._internal import module_utils as _mod_utils +from .common import AudioMetaData + + +if _mod_utils.is_module_available("soundfile"): + import soundfile + + +@_mod_utils.requires_module("soundfile") +def info(filepath: str) -> AudioMetaData: + """Get signal information of an audio file. + + Args: + filepath (str or pathlib.Path): Path to audio file. + This functionalso handles ``pathlib.Path`` objects, but is annotated as ``str`` + for the consistency with "sox_io" backend, which has a restriction on type annotation + for TorchScript compiler compatiblity. + + Returns: + AudioMetaData: meta data of the given audio. + """ + sinfo = soundfile.info(filepath) + return AudioMetaData(sinfo.samplerate, sinfo.frames, sinfo.channels) + + +_SUBTYPE2DTYPE = { + "PCM_S8": "int8", + "PCM_U8": "uint8", + "PCM_16": "int16", + "PCM_32": "int32", + "FLOAT": "float32", + "DOUBLE": "float64", +} + + +@_mod_utils.requires_module("soundfile") +def load( + filepath: str, + frame_offset: int = 0, + num_frames: int = -1, + normalize: bool = True, + channels_first: bool = True, +) -> Tuple[torch.Tensor, int]: + """Load audio data from file. + + Note: + The formats this function can handle depend on the soundfile installation. + This function is tested on the following formats; + + * WAV + + * 32-bit floating-point + * 32-bit signed integer + * 16-bit signed integer + * 8-bit unsigned integer + + * FLAC + * OGG/VORBIS + * SPHERE + + By default (``normalize=True``, ``channels_first=True``), this function returns Tensor with + ``float32`` dtype and the shape of ``[channel, time]``. + The samples are normalized to fit in the range of ``[-1.0, 1.0]``. + + When the input format is WAV with integer type, such as 32-bit signed integer, 16-bit + signed integer and 8-bit unsigned integer (24-bit signed integer is not supported), + by providing ``normalize=False``, this function can return integer Tensor, where the samples + are expressed within the whole range of the corresponding dtype, that is, ``int32`` tensor + for 32-bit signed PCM, ``int16`` for 16-bit signed PCM and ``uint8`` for 8-bit unsigned PCM. + + ``normalize`` parameter has no effect on 32-bit floating-point WAV and other formats, such as + ``flac`` and ``mp3``. + For these formats, this function always returns ``float32`` Tensor with values normalized to + ``[-1.0, 1.0]``. + + Args: + filepath (str or pathlib.Path): Path to audio file. + This functionalso handles ``pathlib.Path`` objects, but is annotated as ``str`` + for the consistency with "sox_io" backend, which has a restriction on type annotation + for TorchScript compiler compatiblity. + frame_offset (int): + Number of frames to skip before start reading data. + num_frames (int): + Maximum number of frames to read. ``-1`` reads all the remaining samples, + starting from ``frame_offset``. + This function may return the less number of frames if there is not enough + frames in the given file. + normalize (bool): + When ``True``, this function always return ``float32``, and sample values are + normalized to ``[-1.0, 1.0]``. + If input file is integer WAV, giving ``False`` will change the resulting Tensor type to + integer type. + This argument has no effect for formats other than integer WAV type. + channels_first (bool): + When True, the returned Tensor has dimension ``[channel, time]``. + Otherwise, the returned Tensor's dimension is ``[time, channel]``. + + Returns: + torch.Tensor: + If the input file has integer wav format and normalization is off, then it has + integer type, else ``float32`` type. If ``channels_first=True``, it has + ``[channel, time]`` else ``[time, channel]``. + """ + with soundfile.SoundFile(filepath, "r") as file_: + if file_.format != "WAV" or normalize: + dtype = "float32" + elif file_.subtype not in _SUBTYPE2DTYPE: + raise ValueError(f"Unsupported subtype: {file_.subtype}") + else: + dtype = _SUBTYPE2DTYPE[file_.subtype] + + frames = file_._prepare_read(frame_offset, None, num_frames) + waveform = file_.read(frames, dtype, always_2d=True) + sample_rate = file_.samplerate + + waveform = torch.from_numpy(waveform) + if channels_first: + waveform = waveform.t() + return waveform, sample_rate + + +@_mod_utils.requires_module("soundfile") +def save( + filepath: str, + src: torch.Tensor, + sample_rate: int, + channels_first: bool = True, + compression: Optional[float] = None, +): + """Save audio data to file. + + Note: + The formats this function can handle depend on the soundfile installation. + This function is tested on the following formats; + + * WAV + + * 32-bit floating-point + * 32-bit signed integer + * 16-bit signed integer + * 8-bit unsigned integer + + * FLAC + * OGG/VORBIS + * SPHERE + + Args: + filepath (str or pathlib.Path): Path to audio file. + This functionalso handles ``pathlib.Path`` objects, but is annotated as ``str`` + for the consistency with "sox_io" backend, which has a restriction on type annotation + for TorchScript compiler compatiblity. + tensor (torch.Tensor): Audio data to save. must be 2D tensor. + sample_rate (int): sampling rate + channels_first (bool): + If ``True``, the given tensor is interpreted as ``[channel, time]``, + otherwise ``[time, channel]``. + compression (Optional[float]): + Not used. It is here only for interface compatibility reson with "sox_io" backend. + """ + if src.ndim != 2: + raise ValueError(f"Expected 2D Tensor, got {src.ndim}D.") + if compression is not None: + warnings.warn( + '`save` function of "soundfile" backend does not support "compression" parameter. ' + "The argument is silently ignored." + ) + + ext = str(filepath).split(".")[-1].lower() + if ext != "wav": + subtype = None + elif src.dtype == torch.uint8: + subtype = "PCM_U8" + elif src.dtype == torch.int16: + subtype = "PCM_16" + elif src.dtype == torch.int32: + subtype = "PCM_32" + elif src.dtype == torch.float32: + subtype = "FLOAT" + elif src.dtype == torch.float64: + subtype = "DOUBLE" + else: + raise ValueError(f"Unsupported dtype for WAV: {src.dtype}") + + format_ = None + # sph is a extension used in TED-LIUM but soundfile does not recognize it as NIST format, + # so we extend the extensions manually here + if ext in ["nis", "nist", "sph"]: + format_ = "NIST" + + if channels_first: + src = src.t() + + soundfile.write( + file=filepath, data=src, samplerate=sample_rate, subtype=subtype, format=format_ + ) + + +@_mod_utils.requires_module("soundfile") +@_mod_utils.deprecated('Please use "torchaudio.load".', "0.9.0") +def load_wav( + filepath: str, + frame_offset: int = 0, + num_frames: int = -1, + channels_first: bool = True, +) -> Tuple[torch.Tensor, int]: + """Load wave file. + + This function is defined only for the purpose of compatibility against other backend + for simple usecases, such as ``torchaudio.load_wav(filepath)``. + The implementation is same as :py:func:`load`. + """ + return load( + filepath, + frame_offset, + num_frames, + normalize=False, + channels_first=channels_first, + ) diff --git a/torchaudio/backend/common.py b/torchaudio/backend/common.py index bc61df4746..135a18caee 100644 --- a/torchaudio/backend/common.py +++ b/torchaudio/backend/common.py @@ -1,10 +1,30 @@ from typing import Any, Optional +from torchaudio._internal import module_utils as _mod_utils + +class AudioMetaData: + """Return type of ``torchaudio.info`` function. + + This class is used by :ref:`"sox_io" backend` and + :ref:`"soundfile" backend with the new interface`. + + :ivar int sample_rate: Sample rate + :ivar int num_frames: The number of frames + :ivar int num_channels: The number of channels + """ + def __init__(self, sample_rate: int, num_frames: int, num_channels: int): + self.sample_rate = sample_rate + self.num_frames = num_frames + self.num_channels = num_channels + + +@_mod_utils.deprecated('Please migrate to `AudioMetaData`.', '0.9.0') class SignalInfo: - """Data class returned ``info`` functions. + """One of return types of ``torchaudio.info`` functions. - Used by :ref:`sox backend` and :ref:`soundfile backend` + This class is used by :ref:`"sox" backend (deprecated)` and + :ref:`"soundfile" backend with the legacy interface (deprecated)`. See https://fossies.org/dox/sox-14.4.2/structsox__signalinfo__t.html @@ -25,10 +45,12 @@ def __init__(self, self.length = length +@_mod_utils.deprecated('Please migrate to `AudioMetaData`.', '0.9.0') class EncodingInfo: - """Data class returned ``info`` functions. + """One of return types of ``torchaudio.info`` functions. - Used by :ref:`sox backend` and :ref:`soundfile backend` + This class is used by :ref:`"sox" backend (deprecated)` and + :ref:`"soundfile" backend with the legacy interface (deprecated)`. See https://fossies.org/dox/sox-14.4.2/structsox__encodinginfo__t.html diff --git a/torchaudio/backend/sox_backend.py b/torchaudio/backend/sox_backend.py index 45d75817af..bf167dd195 100644 --- a/torchaudio/backend/sox_backend.py +++ b/torchaudio/backend/sox_backend.py @@ -92,6 +92,9 @@ def info(filepath: str) -> Tuple[SignalInfo, EncodingInfo]: @_mod_utils.requires_module('torchaudio._torchaudio') +@_mod_utils.deprecated( + 'Please migrate to "sox_io" backend. See https://github.com/pytorch/audio/issues/903 for the detail', + '0.9.0') def save_encinfo(filepath: str, src: Tensor, channels_first: bool = True, @@ -163,6 +166,9 @@ def save_encinfo(filepath: str, @_mod_utils.requires_module('torchaudio._torchaudio') +@_mod_utils.deprecated( + 'Please migrate to "sox_io" backend. See https://github.com/pytorch/audio/issues/903 for the detail', + '0.9.0') def sox_signalinfo_t() -> SignalInfo: r"""Create a sox_signalinfo_t object. This object can be used to set the sample rate, number of channels, length, bit precision and headroom multiplier @@ -186,6 +192,9 @@ def sox_signalinfo_t() -> SignalInfo: @_mod_utils.requires_module('torchaudio._torchaudio') +@_mod_utils.deprecated( + 'Please migrate to "sox_io" backend. See https://github.com/pytorch/audio/issues/903 for the detail', + '0.9.0') def sox_encodinginfo_t() -> EncodingInfo: r"""Create a sox_encodinginfo_t object. This object can be used to set the encoding type, bit precision, compression factor, reverse bytes, reverse nibbles, @@ -224,6 +233,9 @@ def sox_encodinginfo_t() -> EncodingInfo: @_mod_utils.requires_module('torchaudio._torchaudio') +@_mod_utils.deprecated( + 'Please migrate to "sox_io" backend. See https://github.com/pytorch/audio/issues/903 for the detail', + '0.9.0') def get_sox_encoding_t(i: int = None) -> EncodingInfo: r"""Get enum of sox_encoding_t for sox encodings. @@ -242,6 +254,9 @@ def get_sox_encoding_t(i: int = None) -> EncodingInfo: @_mod_utils.requires_module('torchaudio._torchaudio') +@_mod_utils.deprecated( + 'Please migrate to "sox_io" backend. See https://github.com/pytorch/audio/issues/903 for the detail', + '0.9.0') def get_sox_option_t(i: int = 2) -> Any: r"""Get enum of sox_option_t for sox encodinginfo options. @@ -259,6 +274,9 @@ def get_sox_option_t(i: int = 2) -> Any: @_mod_utils.requires_module('torchaudio._torchaudio') +@_mod_utils.deprecated( + 'Please migrate to "sox_io" backend. See https://github.com/pytorch/audio/issues/903 for the detail', + '0.9.0') def get_sox_bool(i: int = 0) -> Any: r"""Get enum of sox_bool for sox encodinginfo options. diff --git a/torchaudio/backend/sox_io_backend.py b/torchaudio/backend/sox_io_backend.py index e2823ada00..1e57e92834 100644 --- a/torchaudio/backend/sox_io_backend.py +++ b/torchaudio/backend/sox_io_backend.py @@ -5,18 +5,7 @@ module_utils as _mod_utils, ) - -class AudioMetaData: - """Data class to be returned by :py:func:`~torchaudio.backend.sox_io_backend.info`. - - :ivar int sample_rate: Sample rate - :ivar int num_frames: The number of frames - :ivar int num_channels: The number of channels - """ - def __init__(self, sample_rate: int, num_frames: int, num_channels: int): - self.sample_rate = sample_rate - self.num_frames = num_frames - self.num_channels = num_channels +from .common import AudioMetaData @_mod_utils.requires_module('torchaudio._torchaudio') @@ -25,11 +14,11 @@ def info(filepath: str) -> AudioMetaData: Args: filepath (str or pathlib.Path): - Path to audio file. This function also handles ``pathlib.Path`` objects, but is annotated as - ``str`` for TorchScript compiler compatibility. + Path to audio file. This function also handles ``pathlib.Path`` objects, + but is annotated as ``str`` for TorchScript compatibility. Returns: - AudioMetaData: meta data of the given audio. + AudioMetaData: Metadata of the given audio. """ # Cast to str in case type is `pathlib.Path` filepath = str(filepath) @@ -195,7 +184,6 @@ def load_wav( ) -> Tuple[torch.Tensor, int]: """Load wave file. - This function is defined only for the purpose of compatibility against other backend for simple usecases, such as ``torchaudio.load_wav(filepath)``. The implementation is same as :py:func:`load`. diff --git a/torchaudio/backend/utils.py b/torchaudio/backend/utils.py index 87ec948fba..b888c04c48 100644 --- a/torchaudio/backend/utils.py +++ b/torchaudio/backend/utils.py @@ -9,6 +9,7 @@ sox_backend, sox_io_backend, soundfile_backend, + _soundfile_backend, ) __all__ = [ @@ -41,6 +42,12 @@ def set_audio_backend(backend: Optional[str]): One of ``"sox"``, ``"sox_io"`` or ``"soundfile"`` based on availability of the system. If ``None`` is provided the current backend is unassigned. """ + if torchaudio.USE_SOUNDFILE_LEGACY_INTERFACE is not None: + warnings.warn( + '"torchaudio.USE_SOUNDFILE_LEGACY_INTERFACE" flag is depredated and will be removed in 0.9.0. ' + 'Please remove the use of flag.' + ) + if backend is not None and backend not in list_audio_backends(): raise RuntimeError( f'Backend "{backend}" is not one of ' @@ -50,15 +57,21 @@ def set_audio_backend(backend: Optional[str]): module = no_backend elif backend == 'sox': warnings.warn( - '"sox" backend is being deprecated. ' - 'The default backend will be changed to "sox_io" backend in 0.8.0 and ' - '"sox" backend will be removed in 0.9.0. Please migrate to "sox_io" backend. ' - 'Please refer to https://github.com/pytorch/audio/issues/903 for the detail.') + '"sox" backend is depredated and will be removed in 0.9.0. ' + 'Please use "sox_io" backend.' + ) module = sox_backend elif backend == 'sox_io': module = sox_io_backend elif backend == 'soundfile': - module = soundfile_backend + if torchaudio.USE_SOUNDFILE_LEGACY_INTERFACE: + warnings.warn( + 'The legacy interface of "soundfile" backend is depredated and will be removed in 0.9.0. ' + 'Please migrate to the new interface.' + ) + module = soundfile_backend + else: + module = _soundfile_backend else: raise NotImplementedError(f'Unexpected backend "{backend}"') @@ -69,7 +82,7 @@ def set_audio_backend(backend: Optional[str]): def _init_audio_backend(): backends = list_audio_backends() if 'sox' in backends: - set_audio_backend('sox') + set_audio_backend('sox_io') elif 'soundfile' in backends: set_audio_backend('soundfile') else: @@ -89,6 +102,6 @@ def get_audio_backend() -> Optional[str]: return 'sox' if torchaudio.load == sox_io_backend.load: return 'sox_io' - if torchaudio.load == soundfile_backend.load: + if torchaudio.load in [soundfile_backend.load, _soundfile_backend.load]: return 'soundfile' raise ValueError('Unknown backend.') diff --git a/torchaudio/compliance/kaldi.py b/torchaudio/compliance/kaldi.py index 792f439ccd..1160595992 100644 --- a/torchaudio/compliance/kaldi.py +++ b/torchaudio/compliance/kaldi.py @@ -573,7 +573,7 @@ def fbank(waveform: Tensor, # size (m, padded_window_size // 2 + 1, 2) fft = torch.rfft(strided_input, 1, normalized=False, onesided=True) - power_spectrum = fft.pow(2).sum(2).unsqueeze(1) # size (m, 1, padded_window_size // 2 + 1) + power_spectrum = fft.pow(2).sum(2) # size (m, padded_window_size // 2 + 1) if not use_power: power_spectrum = power_spectrum.pow(0.5) @@ -582,11 +582,11 @@ def fbank(waveform: Tensor, low_freq, high_freq, vtln_low, vtln_high, vtln_warp) mel_energies = mel_energies.to(device=device, dtype=dtype) - # pad right column with zeros and add dimension, size (1, num_mel_bins, padded_window_size // 2 + 1) - mel_energies = torch.nn.functional.pad(mel_energies, (0, 1), mode='constant', value=0).unsqueeze(0) + # pad right column with zeros and add dimension, size (num_mel_bins, padded_window_size // 2 + 1) + mel_energies = torch.nn.functional.pad(mel_energies, (0, 1), mode='constant', value=0) # sum with mel fiterbanks over the power spectrum, size (m, num_mel_bins) - mel_energies = (power_spectrum * mel_energies).sum(dim=2) + mel_energies = torch.mm(power_spectrum, mel_energies.T) if use_log_fbank: # avoid log of zero (which should be prevented anyway by dithering) mel_energies = torch.max(mel_energies, _get_epsilon(device, dtype)).log() diff --git a/torchaudio/csrc/sox.cpp b/torchaudio/csrc/sox.cpp index 0f099946fd..3be7d01314 100644 --- a/torchaudio/csrc/sox.cpp +++ b/torchaudio/csrc/sox.cpp @@ -175,207 +175,10 @@ void write_audio_file( } } -int build_flow_effects(const std::string& file_name, - at::Tensor otensor, - bool ch_first, - sox_signalinfo_t* target_signal, - sox_encodinginfo_t* target_encoding, - const char* file_type, - std::vector pyeffs, - int max_num_eopts) { - - /* This function builds an effects flow and puts the results into a tensor. - It can also be used to re-encode audio using any of the available encoding - options in SoX including sample rate and channel re-encoding. */ - - // open input - sox_format_t* input = sox_open_read(file_name.c_str(), nullptr, nullptr, nullptr); - if (input == nullptr) { - throw std::runtime_error("Error opening audio file"); - } - - // only used if target signal or encoding are null - sox_signalinfo_t empty_signal; - sox_encodinginfo_t empty_encoding; - - // set signalinfo and encodinginfo if blank - if(target_signal == nullptr) { - target_signal = &empty_signal; - target_signal->rate = input->signal.rate; - target_signal->channels = input->signal.channels; - target_signal->length = SOX_UNSPEC; - target_signal->precision = input->signal.precision; -#if SOX_LIB_VERSION_CODE >= 918272 // >= 14.3.0 - target_signal->mult = nullptr; -#endif - } - if(target_encoding == nullptr) { - target_encoding = &empty_encoding; - target_encoding->encoding = SOX_ENCODING_SIGN2; // Sample format - target_encoding->bits_per_sample = input->signal.precision; // Bits per sample - target_encoding->compression = 0.0; // Compression factor - target_encoding->reverse_bytes = sox_option_default; // Should bytes be reversed - target_encoding->reverse_nibbles = sox_option_default; // Should nibbles be reversed - target_encoding->reverse_bits = sox_option_default; // Should bits be reversed (pairs of bits?) - target_encoding->opposite_endian = sox_false; // Reverse endianness - } - - // check for rate or channels effect and change the output signalinfo accordingly - for (SoxEffect se : pyeffs) { - if (se.ename == "rate") { - target_signal->rate = std::stod(se.eopts[0]); - } else if (se.ename == "channels") { - target_signal->channels = std::stoi(se.eopts[0]); - } - } - - // create interm_signal for effects, intermediate steps change this in-place - sox_signalinfo_t interm_signal = input->signal; - -#ifdef __APPLE__ - // According to Mozilla Deepspeech sox_open_memstream_write doesn't work - // with OSX - char tmp_name[] = "/tmp/fileXXXXXX"; - int tmp_fd = mkstemp(tmp_name); - close(tmp_fd); - sox_format_t* output = sox_open_write(tmp_name, target_signal, - target_encoding, "wav", nullptr, nullptr); -#else - // create buffer and buffer_size for output in memwrite - char* buffer; - size_t buffer_size; - // in-memory descriptor (this may not work for OSX) - sox_format_t* output = sox_open_memstream_write(&buffer, - &buffer_size, - target_signal, - target_encoding, - file_type, nullptr); -#endif - if (output == nullptr) { - throw std::runtime_error("Error opening output memstream/temporary file"); - } - // Setup the effects chain to decode/resample - sox_effects_chain_t* chain = - sox_create_effects_chain(&input->encoding, &output->encoding); - - sox_effect_t* e = sox_create_effect(sox_find_effect("input")); - char* io_args[1]; - io_args[0] = (char*)input; - sox_effect_options(e, 1, io_args); - sox_add_effect(chain, e, &interm_signal, &input->signal); - free(e); - - for(SoxEffect tae : pyeffs) { - if(tae.ename == "no_effects") break; - e = sox_create_effect(sox_find_effect(tae.ename.c_str())); - e->global_info->global_info->verbosity = 1; - if(tae.eopts[0] == "") { - sox_effect_options(e, 0, nullptr); - } else { - int num_opts = tae.eopts.size(); - char* sox_args[max_num_eopts]; - for(std::vector::size_type i = 0; i != tae.eopts.size(); i++) { - sox_args[i] = (char*) tae.eopts[i].c_str(); - } - if(sox_effect_options(e, num_opts, sox_args) != SOX_SUCCESS) { -#ifdef __APPLE__ - unlink(tmp_name); -#endif - throw std::runtime_error("invalid effect options, see SoX docs for details"); - } - } - sox_add_effect(chain, e, &interm_signal, &output->signal); - free(e); - } - - e = sox_create_effect(sox_find_effect("output")); - io_args[0] = (char*)output; - sox_effect_options(e, 1, io_args); - sox_add_effect(chain, e, &interm_signal, &output->signal); - free(e); - - // Finally run the effects chain - sox_flow_effects(chain, nullptr, nullptr); - sox_delete_effects_chain(chain); - - // Close sox handles, buffer does not get properly sized until these are closed - sox_close(output); - sox_close(input); - - int sr; - // Read the in-memory audio buffer or temp file that we just wrote. -#ifdef __APPLE__ - /* - Temporary filetype must have a valid header. Wav seems to work here while - raw does not. Certain effects like chorus caused strange behavior on the mac. - */ - // read_audio_file reads the temporary file and returns the sr and otensor - sr = read_audio_file(tmp_name, otensor, ch_first, 0, 0, - target_signal, target_encoding, "wav"); - // delete temporary audio file - unlink(tmp_name); -#else - // Resize output tensor to desired dimensions, different effects result in output->signal.length, - // interm_signal.length and buffer size being inconsistent with the result of the file output. - // We prioritize in the order: output->signal.length > interm_signal.length > buffer_size - // Could be related to: https://sourceforge.net/p/sox/bugs/314/ - int nc, ns; - if (output->signal.length == 0) { - // sometimes interm_signal length is extremely large, but the buffer_size - // is double the length of the output signal - if (interm_signal.length > (buffer_size * 10)) { - ns = buffer_size / 2; - } else { - ns = interm_signal.length; - } - nc = interm_signal.channels; - } else { - nc = output->signal.channels; - ns = output->signal.length; - } - otensor.resize_({ns/nc, nc}); - otensor = otensor.contiguous(); - - input = sox_open_mem_read(buffer, buffer_size, target_signal, target_encoding, file_type); - std::vector samples(buffer_size); - const int64_t samples_read = sox_read(input, samples.data(), buffer_size); - assert(samples_read != nc * ns && samples_read != 0); - AT_DISPATCH_ALL_TYPES(otensor.scalar_type(), "effects_buffer", [&] { - auto* data = otensor.data_ptr(); - std::copy(samples.begin(), samples.begin() + samples_read, data); - }); - // free buffer and close mem_read - sox_close(input); - free(buffer); - - if (ch_first) { - otensor.transpose_(1, 0); - } - sr = target_signal->rate; - -#endif - // return sample rate, output tensor modified in-place - return sr; -} } // namespace audio } // namespace torch PYBIND11_MODULE(_torchaudio, m) { - py::class_(m, "SoxEffect") - .def(py::init<>()) - .def("__repr__", [](const torch::audio::SoxEffect &self) { - std::stringstream ss; - std::string sep; - ss << "SoxEffect (" << self.ename << " ,["; - for(std::string s : self.eopts) { - ss << sep << "\"" << s << "\""; - sep = ", "; - } - ss << "])\n"; - return ss.str(); - }) - .def_readwrite("ename", &torch::audio::SoxEffect::ename) - .def_readwrite("eopts", &torch::audio::SoxEffect::eopts); py::class_(m, "sox_signalinfo_t") .def(py::init<>()) .def("__repr__", [](const sox_signalinfo_t &self) { @@ -468,8 +271,4 @@ PYBIND11_MODULE(_torchaudio, m) { "get_info", &torch::audio::get_info, "Gets information about an audio file"); - m.def( - "build_flow_effects", - &torch::audio::build_flow_effects, - "build effects and flow chain into tensors"); } diff --git a/torchaudio/csrc/sox.h b/torchaudio/csrc/sox.h index 8093f0732e..1344031330 100644 --- a/torchaudio/csrc/sox.h +++ b/torchaudio/csrc/sox.h @@ -44,26 +44,4 @@ void write_audio_file( /// error occurred during reading of the audio data. std::tuple get_info( const std::string& file_name); - -// Struct for build_flow_effects function -struct SoxEffect { - SoxEffect() : ename(""), eopts({""}) { } - std::string ename; - std::vector eopts; -}; - -/// Build a SoX chain, flow the effects, and capture the results in a tensor. -/// An audio file from the given `path` flows through an effects chain given -/// by a list of effects and effect options to an output buffer which is encoded -/// into memory to a target signal type and target signal encoding. The resulting -/// buffer is then placed into a tensor. This function returns the output tensor -/// and the sample rate of the output tensor. -int build_flow_effects(const std::string& file_name, - at::Tensor otensor, - bool ch_first, - sox_signalinfo_t* target_signal, - sox_encodinginfo_t* target_encoding, - const char* file_type, - std::vector pyeffs, - int max_num_eopts); }} // namespace torch::audio diff --git a/torchaudio/datasets/cmuarctic.py b/torchaudio/datasets/cmuarctic.py index 7aa6d541e5..7ea4ca4dae 100644 --- a/torchaudio/datasets/cmuarctic.py +++ b/torchaudio/datasets/cmuarctic.py @@ -76,9 +76,20 @@ def load_cmuarctic_item(line: str, class CMUARCTIC(Dataset): - """ - Create a Dataset for CMU_arctic. Each item is a tuple of the form: - waveform, sample_rate, utterance, utterance_id + """Create a Dataset for CMU_ARCTIC. + + Args: + root (str): Path to the directory where the dataset is found or downloaded. + url (str, optional): + The URL to download the dataset from or the type of the dataset to dowload. + (default: ``"aew"``) + Allowed type values are ``"aew"``, ``"ahw"``, ``"aup"``, ``"awb"``, ``"axb"``, ``"bdl"``, + ``"clb"``, ``"eey"``, ``"fem"``, ``"gka"``, ``"jmk"``, ``"ksp"``, ``"ljm"``, ``"lnh"``, + ``"rms"``, ``"rxr"``, ``"slp"`` or ``"slt"``. + folder_in_archive (str, optional): + The top-level directory of the dataset. (default: ``"ARCTIC"``) + download (bool, optional): + Whether to download the dataset if it is not found at root path. (default: ``False``). """ _file_text = "txt.done.data" @@ -143,6 +154,14 @@ def __init__(self, self._walker = list(walker) def __getitem__(self, n: int) -> Tuple[Tensor, int, str, str]: + """Load the n-th sample from the dataset. + + Args: + n (int): The index of the sample to be loaded + + Returns: + tuple: ``(waveform, sample_rate, utterance, utterance_id)`` + """ line = self._walker[n] return load_cmuarctic_item(line, self._path, self._folder_audio, self._ext_audio) diff --git a/torchaudio/datasets/commonvoice.py b/torchaudio/datasets/commonvoice.py index a11b9dc1c8..825cf3e9ab 100644 --- a/torchaudio/datasets/commonvoice.py +++ b/torchaudio/datasets/commonvoice.py @@ -100,11 +100,28 @@ def load_commonvoice_item(line: List[str], class COMMONVOICE(Dataset): - """ - Create a Dataset for CommonVoice. Each item is a tuple of the form: - (waveform, sample_rate, dictionary) - where dictionary is a dictionary built from the tsv file with the following keys: - client_id, path, sentence, up_votes, down_votes, age, gender, accent. + """Create a Dataset for CommonVoice. + + Args: + root (str): Path to the directory where the dataset is found or downloaded. + tsv (str, optional): The name of the tsv file used to construct the metadata. + (default: ``"train.tsv"``) + url (str, optional): The URL to download the dataset from, or the language of + the dataset to download. (default: ``"english"``). + Allowed language values are ``"tatar"``, ``"english"``, ``"german"``, + ``"french"``, ``"welsh"``, ``"breton"``, ``"chuvash"``, ``"turkish"``, ``"kyrgyz"``, + ``"irish"``, ``"kabyle"``, ``"catalan"``, ``"taiwanese"``, ``"slovenian"``, + ``"italian"``, ``"dutch"``, ``"hakha chin"``, ``"esperanto"``, ``"estonian"``, + ``"persian"``, ``"portuguese"``, ``"basque"``, ``"spanish"``, ``"chinese"``, + ``"mongolian"``, ``"sakha"``, ``"dhivehi"``, ``"kinyarwanda"``, ``"swedish"``, + ``"russian"``, ``"indonesian"``, ``"arabic"``, ``"tamil"``, ``"interlingua"``, + ``"latvian"``, ``"japanese"``, ``"votic"``, ``"abkhaz"``, ``"cantonese"`` and + ``"romansh sursilvan"``. + folder_in_archive (str, optional): The top-level directory of the dataset. + version (str): Version string. (default: ``"cv-corpus-4-2019-12-10"``) + For the other allowed values, Please checkout https://commonvoice.mozilla.org/en/datasets. + download (bool, optional): + Whether to download the dataset if it is not found at root path. (default: ``False``). """ _ext_txt = ".txt" @@ -192,6 +209,16 @@ def __init__(self, self._walker = list(walker) def __getitem__(self, n: int) -> Tuple[Tensor, int, Dict[str, str]]: + """Load the n-th sample from the dataset. + + Args: + n (int): The index of the sample to be loaded + + Returns: + tuple: ``(waveform, sample_rate, dictionary)``, where dictionary is built + from the TSV file with the following keys: ``client_id``, ``path``, ``sentence``, + ``up_votes``, ``down_votes``, ``age``, ``gender`` and ``accent``. + """ line = self._walker[n] return load_commonvoice_item(line, self._header, self._path, self._folder_audio) diff --git a/torchaudio/datasets/gtzan.py b/torchaudio/datasets/gtzan.py index e031801bc1..160898c73d 100644 --- a/torchaudio/datasets/gtzan.py +++ b/torchaudio/datasets/gtzan.py @@ -1,6 +1,6 @@ import os import warnings -from typing import Any, Tuple +from typing import Any, Tuple, Optional import torchaudio from torch import Tensor @@ -998,12 +998,22 @@ def load_gtzan_item(fileid: str, path: str, ext_audio: str) -> Tuple[Tensor, str class GTZAN(Dataset): - """ - Create a Dataset for GTZAN. Each item is a tuple of the form: - waveform, sample_rate, label. + """Create a Dataset for GTZAN. + + Note: + Please see http://marsyas.info/downloads/datasets.html if you are planning to use + this dataset to publish results. - Please see http://marsyas.info/downloads/datasets.html - if you are planning to use this dataset to publish results. + Args: + root (str): Path to the directory where the dataset is found or downloaded. + url (str, optional): The URL to download the dataset from. + (default: ``"http://opihi.cs.uvic.ca/sound/genres.tar.gz"``) + folder_in_archive (str, optional): The top-level directory of the dataset. + download (bool, optional): + Whether to download the dataset if it is not found at root path. (default: ``False``). + subset (str, optional): Which subset of the dataset to use. + One of ``"training"``, ``"validation"``, ``"testing"`` or ``None``. + If ``None``, the entire dataset is used. (default: ``None``). """ _ext_audio = ".wav" @@ -1014,7 +1024,7 @@ def __init__( url: str = URL, folder_in_archive: str = FOLDER_IN_ARCHIVE, download: bool = False, - subset: Any = None, + subset: Optional[str] = None, ) -> None: # super(GTZAN, self).__init__() @@ -1082,6 +1092,14 @@ def __init__( self._walker = filtered_test def __getitem__(self, n: int) -> Tuple[Tensor, int, str]: + """Load the n-th sample from the dataset. + + Args: + n (int): The index of the sample to be loaded + + Returns: + tuple: ``(waveform, sample_rate, label)`` + """ fileid = self._walker[n] item = load_gtzan_item(fileid, self._path, self._ext_audio) waveform, sample_rate, label = item diff --git a/torchaudio/datasets/librispeech.py b/torchaudio/datasets/librispeech.py index 449ab744d3..24da90aa66 100644 --- a/torchaudio/datasets/librispeech.py +++ b/torchaudio/datasets/librispeech.py @@ -67,9 +67,19 @@ def load_librispeech_item(fileid: str, class LIBRISPEECH(Dataset): - """ - Create a Dataset for LibriSpeech. Each item is a tuple of the form: - waveform, sample_rate, utterance, speaker_id, chapter_id, utterance_id + """Create a Dataset for LibriSpeech. + + Args: + root (str): Path to the directory where the dataset is found or downloaded. + url (str, optional): The URL to download the dataset from, + or the type of the dataset to dowload. + Allowed type values are ``"dev-clean"``, ``"dev-other"``, ``"test-clean"``, + ``"test-other"``, ``"train-clean-100"``, ``"train-clean-360"`` and + ``"train-other-500"``. (default: ``"train-clean-100"``) + folder_in_archive (str, optional): + The top-level directory of the dataset. (default: ``"LibriSpeech"``) + download (bool, optional): + Whether to download the dataset if it is not found at root path. (default: ``False``). """ _ext_txt = ".trans.txt" @@ -117,6 +127,14 @@ def __init__(self, self._walker = list(walker) def __getitem__(self, n: int) -> Tuple[Tensor, int, str, int, int, int]: + """Load the n-th sample from the dataset. + + Args: + n (int): The index of the sample to be loaded + + Returns: + tuple: ``(waveform, sample_rate, utterance, speaker_id, chapter_id, utterance_id)`` + """ fileid = self._walker[n] return load_librispeech_item(fileid, self._path, self._ext_audio, self._ext_txt) diff --git a/torchaudio/datasets/libritts.py b/torchaudio/datasets/libritts.py index a37d5528fb..5d4e94cca5 100644 --- a/torchaudio/datasets/libritts.py +++ b/torchaudio/datasets/libritts.py @@ -65,9 +65,19 @@ def load_libritts_item( class LIBRITTS(Dataset): - """ - Create a Dataset for LibriTTS. Each item is a tuple of the form: - waveform, sample_rate, original_text, normalized_text, speaker_id, chapter_id, utterance_id + """Create a Dataset for LibriTTS. + + Args: + root (str): Path to the directory where the dataset is found or downloaded. + url (str, optional): The URL to download the dataset from, + or the type of the dataset to dowload. + Allowed type values are ``"dev-clean"``, ``"dev-other"``, ``"test-clean"``, + ``"test-other"``, ``"train-clean-100"``, ``"train-clean-360"`` and + ``"train-other-500"``. (default: ``"train-clean-100"``) + folder_in_archive (str, optional): + The top-level directory of the dataset. (default: ``"LibriTTS"``) + download (bool, optional): + Whether to download the dataset if it is not found at root path. (default: ``False``). """ _ext_original_txt = ".original.txt" @@ -118,6 +128,15 @@ def __init__( self._walker = list(walker) def __getitem__(self, n: int) -> Tuple[Tensor, int, str, str, int, int, str]: + """Load the n-th sample from the dataset. + + Args: + n (int): The index of the sample to be loaded + + Returns: + tuple: ``(waveform, sample_rate, original_text, normalized_text, speaker_id, + chapter_id, utterance_id)`` + """ fileid = self._walker[n] return load_libritts_item( fileid, diff --git a/torchaudio/datasets/ljspeech.py b/torchaudio/datasets/ljspeech.py index 5e3b6ee7d2..28c3a5dfc8 100644 --- a/torchaudio/datasets/ljspeech.py +++ b/torchaudio/datasets/ljspeech.py @@ -33,9 +33,16 @@ def load_ljspeech_item(line: List[str], path: str, ext_audio: str) -> Tuple[Tens class LJSPEECH(Dataset): - """ - Create a Dataset for LJSpeech-1.1. Each item is a tuple of the form: - waveform, sample_rate, transcript, normalized_transcript + """Create a Dataset for LJSpeech-1.1. + + Args: + root (str): Path to the directory where the dataset is found or downloaded. + url (str, optional): The URL to download the dataset from. + (default: ``"https://data.keithito.com/data/speech/LJSpeech-1.1.tar.bz2"``) + folder_in_archive (str, optional): + The top-level directory of the dataset. (default: ``"wavs"``) + download (bool, optional): + Whether to download the dataset if it is not found at root path. (default: ``False``). """ _ext_audio = ".wav" @@ -68,6 +75,14 @@ def __init__(self, self._walker = list(walker) def __getitem__(self, n: int) -> Tuple[Tensor, int, str, str]: + """Load the n-th sample from the dataset. + + Args: + n (int): The index of the sample to be loaded + + Returns: + tuple: ``(waveform, sample_rate, transcript, normalized_transcript)`` + """ line = self._walker[n] return load_ljspeech_item(line, self._path, self._ext_audio) diff --git a/torchaudio/datasets/speechcommands.py b/torchaudio/datasets/speechcommands.py index 9943d5965b..2bcd2d199f 100644 --- a/torchaudio/datasets/speechcommands.py +++ b/torchaudio/datasets/speechcommands.py @@ -1,5 +1,5 @@ import os -from typing import Tuple +from typing import Tuple, Optional import torchaudio from torch.utils.data import Dataset @@ -22,6 +22,15 @@ } +def _load_list(root, *filenames): + output = [] + for filename in filenames: + filepath = os.path.join(root, filename) + with open(filepath) as fileobj: + output += [os.path.normpath(os.path.join(root, line.strip())) for line in fileobj] + return output + + def load_speechcommands_item(filepath: str, path: str) -> Tuple[Tensor, int, str, str, int]: relpath = os.path.relpath(filepath, path) label, filename = os.path.split(relpath) @@ -36,16 +45,37 @@ def load_speechcommands_item(filepath: str, path: str) -> Tuple[Tensor, int, str class SPEECHCOMMANDS(Dataset): - """ - Create a Dataset for Speech Commands. Each item is a tuple of the form: - waveform, sample_rate, label, speaker_id, utterance_number + """Create a Dataset for Speech Commands. + + Args: + root (str): Path to the directory where the dataset is found or downloaded. + url (str, optional): The URL to download the dataset from, + or the type of the dataset to dowload. + Allowed type values are ``"speech_commands_v0.01"`` and ``"speech_commands_v0.02"`` + (default: ``"speech_commands_v0.02"``) + folder_in_archive (str, optional): + The top-level directory of the dataset. (default: ``"SpeechCommands"``) + download (bool, optional): + Whether to download the dataset if it is not found at root path. (default: ``False``). + subset (Optional[str]): + Select a subset of the dataset [None, "training", "validation", "testing"]. None means + the whole dataset. "validation" and "testing" are defined in "validation_list.txt" and + "testing_list.txt", respectively, and "training" is the rest. (default: ``None``) """ def __init__(self, root: str, url: str = URL, folder_in_archive: str = FOLDER_IN_ARCHIVE, - download: bool = False) -> None: + download: bool = False, + subset: Optional[str] = None, + ) -> None: + + assert subset is None or subset in ["training", "validation", "testing"], ( + "When `subset` not None, it must take a value from " + + "{'training', 'validation', 'testing'}." + ) + if url in [ "speech_commands_v0.01", "speech_commands_v0.02", @@ -70,11 +100,32 @@ def __init__(self, download_url(url, root, hash_value=checksum, hash_type="md5") extract_archive(archive, self._path) - walker = walk_files(self._path, suffix=".wav", prefix=True) - walker = filter(lambda w: HASH_DIVIDER in w and EXCEPT_FOLDER not in w, walker) - self._walker = list(walker) + if subset == "validation": + self._walker = _load_list(self._path, "validation_list.txt") + elif subset == "testing": + self._walker = _load_list(self._path, "testing_list.txt") + elif subset == "training": + excludes = set(_load_list(self._path, "validation_list.txt", "testing_list.txt")) + walker = walk_files(self._path, suffix=".wav", prefix=True) + self._walker = [ + w for w in walker + if HASH_DIVIDER in w + and EXCEPT_FOLDER not in w + and os.path.normpath(w) not in excludes + ] + else: + walker = walk_files(self._path, suffix=".wav", prefix=True) + self._walker = [w for w in walker if HASH_DIVIDER in w and EXCEPT_FOLDER not in w] def __getitem__(self, n: int) -> Tuple[Tensor, int, str, str, int]: + """Load the n-th sample from the dataset. + + Args: + n (int): The index of the sample to be loaded + + Returns: + tuple: ``(waveform, sample_rate, label, speaker_id, utterance_number)`` + """ fileid = self._walker[n] return load_speechcommands_item(fileid, self._path) diff --git a/torchaudio/datasets/tedlium.py b/torchaudio/datasets/tedlium.py index 4ae1ddeb0f..7ac347cd3c 100644 --- a/torchaudio/datasets/tedlium.py +++ b/torchaudio/datasets/tedlium.py @@ -43,44 +43,21 @@ class TEDLIUM(Dataset): """ - Create a Dataset for Tedlium. It supports releases 1,2 and 3, each item is a list containings: - [waveform, sample_rate, transcript, talk_id, speaker_id, identifier]. - - Constructor arguments: + Create a Dataset for Tedlium. It supports releases 1,2 and 3. Args: - root (str): Path containing dataset or target path where its downloaded if needed - release (str, optional): TEDLIUM identifier (release1,release2,release3). Defaults to RELEASE. - subset (str, optional): train/dev/test for releases 1&2, None for release3. Defaults to Train/None - download (bool, optional): Download dataset in case is not founded in root path. Defaults to False. - audio_ext (str, optional): Overwrite audio extension when loading items. Defaults to ".sph". - - Special functions: - - _load_tedlium_item: Loads a TEDLIUM dataset sample given a file name and corresponding sentence name - - _load_audio: Default load function used in TEDLIUM dataset, you can overwrite this function to customize - functionality and load individual sentences from a full ted audio talk file - - get_phoneme_dict: Returns the phoneme dictionary of a TEDLIUM release - + root (str): Path to the directory where the dataset is found or downloaded. + release (str, optional): Release version. + Allowed values are ``"release1"``, ``"release2"`` or ``"release3"``. + (default: ``"release1"``). + subset (str, optional): The subset of dataset to use. Valid options are ``"train"``, ``"dev"``, + and ``"test"`` for releases 1&2, ``None`` for release3. Defaults to ``"train"`` or ``None``. + download (bool, optional): + Whether to download the dataset if it is not found at root path. (default: ``False``). """ - def __init__( self, root: str, release: str = "release1", subset: str = None, download: bool = False, audio_ext=".sph" ) -> None: - """Constructor for TEDLIUM dataset. - - Args: - root (str): Path containing dataset or target path where its downloaded if needed - release (str, optional): TEDLIUM identifier (release1,release2,release3). Defaults to RELEASE. - subset (str, optional): train/dev/test for releases 1&2, None for release3. Defaults to Train/None - download (bool, optional): Download dataset in case is not founded in root path. Defaults to False. - audio_ext (str, optional): Overwrite audio extension when loading items. Defaults to ".sph". - - Raises: - RuntimeError: If release identifier does not match any supported release, - """ self._ext_audio = audio_ext if release in _RELEASE_CONFIGS.keys(): folder_in_archive = _RELEASE_CONFIGS[release]["folder_in_archive"] @@ -140,7 +117,7 @@ def _load_tedlium_item(self, fileid: str, line: int, path: str) -> Tuple[Tensor, path (str): Dataset root path Returns: - Tedlium_item: A namedTuple containing [waveform, sample_rate, transcript, talk_id, speaker_id, identifier] + tuple: ``(waveform, sample_rate, transcript, talk_id, speaker_id, identifier)`` """ transcript_path = os.path.join(path, "stm", fileid) with open(transcript_path + ".stm") as f: @@ -166,19 +143,23 @@ def _load_audio(self, path: str, start_time: float, end_time: float, sample_rate """ start_time = int(float(start_time) * sample_rate) end_time = int(float(end_time) * sample_rate) - if torchaudio.get_audio_backend() == "sox_io": - return torchaudio.load(path, frame_offset=start_time, num_frames=end_time - start_time) - return torchaudio.load(path)[:, start_time:end_time] + + backend = torchaudio.get_audio_backend() + if backend == "sox" or (backend == "soundfile" and torchaudio.USE_SOUNDFILE_LEGACY_INTERFACE): + kwargs = {"offset": start_time, "num_frames": end_time - start_time} + else: + kwargs = {"frame_offset": start_time, "num_frames": end_time - start_time} + + return torchaudio.load(path, **kwargs) def __getitem__(self, n: int) -> Tuple[Tensor, int, str, int, int, int]: - """TEDLIUM dataset custom function overwritting default loadbehaviour - Loads a TEDLIUM sample given a index N. + """Load the n-th sample from the dataset. Args: - n (int): Index of sample to be loaded + n (int): The index of the sample to be loaded Returns: - Tedlium_item: A namedTuple containing [waveform, sample_rate, transcript, talk_id, speaker_id, identifier] + tuple: ``(waveform, sample_rate, transcript, talk_id, speaker_id, identifier)`` """ fileid, line = self._filelist[n] return self._load_tedlium_item(fileid, line, self._path) @@ -193,10 +174,8 @@ def __len__(self) -> int: @property def phoneme_dict(self): - """Returns the phoneme dictionary of a TEDLIUM release. - - Returns: - dictionary: Phoneme dictionary for the current tedlium release + """dict[str, tuple[str]]: Phonemes. Mapping from word to tuple of phonemes. + Note that some words have empty phonemes. """ # Read phoneme dictionary if not self._phoneme_dict: diff --git a/torchaudio/datasets/vctk.py b/torchaudio/datasets/vctk.py index 8fa874c7cf..a8fca59df2 100644 --- a/torchaudio/datasets/vctk.py +++ b/torchaudio/datasets/vctk.py @@ -1,7 +1,6 @@ import os import warnings from typing import Any, Tuple -from collections import namedtuple import torchaudio from torch import Tensor @@ -18,10 +17,6 @@ "https://datashare.is.ed.ac.uk/bitstream/handle/10283/3443/VCTK-Corpus-0.92.zip": "8a6ba2946b36fcbef0212cad601f4bfa" } -Sample = namedtuple( - "Sample", ["waveform", "sample_rate", "utterance", "speaker_id", "utterance_id"] -) - def load_vctk_item(fileid: str, path: str, @@ -54,12 +49,25 @@ def load_vctk_item(fileid: str, class VCTK(Dataset): - """ - Create a Dataset for VCTK. Each item is a tuple of the form: - (waveform, sample_rate, utterance, speaker_id, utterance_id) + """Create a Dataset for VCTK. + + Note: + * **This dataset is no longer publicly available.** Please use :py:class:`VCTK_092` + * Directory ``p315`` is ignored because there is no corresponding text files. + For more information about the dataset visit: https://datashare.is.ed.ac.uk/handle/10283/3443 - Folder `p315` will be ignored due to the non-existent corresponding text files. - For more information about the dataset visit: https://datashare.is.ed.ac.uk/handle/10283/3443 + Args: + root (str): Path to the directory where the dataset is found or downloaded. + url (str, optional): Not used as the dataset is no longer publicly available. + folder_in_archive (str, optional): + The top-level directory of the dataset. (default: ``"VCTK-Corpus"``) + download (bool, optional): + Whether to download the dataset if it is not found at root path. (default: ``False``). + Giving ``download=True`` will result in error as the dataset is no longer + publicly available. + downsample (bool, optional): Not used. + transform (callable, optional): Optional transform applied on waveform. (default: ``None``) + target_transform (callable, optional): Optional transform applied on utterance. (default: ``None``) """ _folder_txt = "txt" @@ -118,6 +126,14 @@ def __init__(self, self._walker = list(walker) def __getitem__(self, n: int) -> Tuple[Tensor, int, str, str, str]: + """Load the n-th sample from the dataset. + + Args: + n (int): The index of the sample to be loaded + + Returns: + tuple: ``(waveform, sample_rate, utterance, speaker_id, utterance_id)`` + """ fileid = self._walker[n] item = load_vctk_item( fileid, @@ -142,17 +158,19 @@ def __len__(self) -> int: return len(self._walker) +SampleType = Tuple[Tensor, int, str, str, str] + + class VCTK_092(Dataset): """Create VCTK 0.92 Dataset - An item is a ``namedtuple`` of (``waveform``, ``sample_rate``, ``utterance``, - ``speaker_id``, ``utterance_id``) - Args: root (str): Root directory where the dataset's top level directory is found. - mic_id (str): Microphone ID. Either ``"mic1"`` or ``"mic2"`` - download (bool, optional): Download the dataset if not found in the given directory. - url (str, optional): URL from which the dataset is downloaded. + mic_id (str): Microphone ID. Either ``"mic1"`` or ``"mic2"``. (default: ``"mic2"``) + download (bool, optional): + Whether to download the dataset if it is not found at root path. (default: ``False``). + url (str, optional): The URL to download the dataset from. + (default: ``"https://datashare.is.ed.ac.uk/bitstream/handle/10283/3443/VCTK-Corpus-0.92.zip"``) audio_ext (str, optional): Custom audio extension if dataset is converted to non-default audio format. Note: @@ -233,7 +251,7 @@ def _load_text(self, file_path) -> str: def _load_audio(self, file_path) -> Tuple[Tensor, int]: return torchaudio.load(file_path) - def _load_sample(self, speaker_id: str, utterance_id: str, mic_id: str) -> Sample: + def _load_sample(self, speaker_id: str, utterance_id: str, mic_id: str) -> SampleType: utterance_path = os.path.join( self._txt_dir, speaker_id, f"{speaker_id}_{utterance_id}.txt" ) @@ -249,9 +267,17 @@ def _load_sample(self, speaker_id: str, utterance_id: str, mic_id: str) -> Sampl # Reading FLAC waveform, sample_rate = self._load_audio(audio_path) - return Sample(waveform, sample_rate, utterance, speaker_id, utterance_id) + return (waveform, sample_rate, utterance, speaker_id, utterance_id) - def __getitem__(self, n: int) -> Sample: + def __getitem__(self, n: int) -> SampleType: + """Load the n-th sample from the dataset. + + Args: + n (int): The index of the sample to be loaded + + Returns: + tuple: ``(waveform, sample_rate, utterance, speaker_id, utterance_id)`` + """ speaker_id, utterance_id = self._sample_ids[n] return self._load_sample(speaker_id, utterance_id, self._mic_id) diff --git a/torchaudio/datasets/yesno.py b/torchaudio/datasets/yesno.py index e45b157c35..5a20539e28 100644 --- a/torchaudio/datasets/yesno.py +++ b/torchaudio/datasets/yesno.py @@ -31,9 +31,18 @@ def load_yesno_item(fileid: str, path: str, ext_audio: str) -> Tuple[Tensor, int class YESNO(Dataset): - """ - Create a Dataset for YesNo. Each item is a tuple of the form: - (waveform, sample_rate, labels) + """Create a Dataset for YesNo. + + Args: + root (str): Path to the directory where the dataset is found or downloaded. + url (str, optional): The URL to download the dataset from. + (default: ``"http://www.openslr.org/resources/1/waves_yesno.tar.gz"``) + folder_in_archive (str, optional): + The top-level directory of the dataset. (default: ``"waves_yesno"``) + download (bool, optional): + Whether to download the dataset if it is not found at root path. (default: ``False``). + transform (callable, optional): Optional transform applied on waveform. (default: ``None``) + target_transform (callable, optional): Optional transform applied on utterance. (default: ``None``) """ _ext_audio = ".wav" @@ -78,6 +87,14 @@ def __init__(self, self._walker = list(walker) def __getitem__(self, n: int) -> Tuple[Tensor, int, List[int]]: + """Load the n-th sample from the dataset. + + Args: + n (int): The index of the sample to be loaded + + Returns: + tuple: ``(waveform, sample_rate, labels)`` + """ fileid = self._walker[n] item = load_yesno_item(fileid, self._path, self._ext_audio) diff --git a/torchaudio/functional.py b/torchaudio/functional.py index a6514c79f2..d8adfe86e6 100644 --- a/torchaudio/functional.py +++ b/torchaudio/functional.py @@ -1268,15 +1268,23 @@ def phaser( delay_pos = 0 mod_pos = 0 - output_waveform = torch.zeros_like(waveform, dtype=dtype, device=device) + output_waveform_pre_gain_list = [] + waveform = waveform * gain_in + delay_buf = delay_buf * decay + waveform_list = [waveform[:, i] for i in range(waveform.size(1))] + delay_buf_list = [delay_buf[:, i] for i in range(delay_buf.size(1))] + mod_buf_list = [mod_buf[i] for i in range(mod_buf.size(0))] for i in range(waveform.shape[-1]): - idx = int((delay_pos + mod_buf[mod_pos]) % delay_buf_len) - temp = (waveform[:, i] * gain_in) + (delay_buf[:, idx] * decay) + idx = int((delay_pos + mod_buf_list[mod_pos]) % delay_buf_len) mod_pos = (mod_pos + 1) % mod_buf_len delay_pos = (delay_pos + 1) % delay_buf_len - delay_buf[:, delay_pos] = temp - output_waveform[:, i] = temp * gain_out + temp = (waveform_list[i]) + (delay_buf_list[idx]) + delay_buf_list[delay_pos] = temp * decay + output_waveform_pre_gain_list.append(temp) + + output_waveform = torch.stack(output_waveform_pre_gain_list, dim=1).to(dtype=dtype, device=device) + output_waveform.mul_(gain_out) return output_waveform.clamp(min=-1, max=1).view(actual_shape) diff --git a/torchaudio/models/__init__.py b/torchaudio/models/__init__.py index 8e05b8b509..55498fd7f6 100644 --- a/torchaudio/models/__init__.py +++ b/torchaudio/models/__init__.py @@ -1,2 +1,3 @@ -from .wav2letter import * -from .wavernn import * +from .wav2letter import Wav2Letter +from .wavernn import WaveRNN +from .conv_tasnet import ConvTasNet diff --git a/torchaudio/models/conv_tasnet.py b/torchaudio/models/conv_tasnet.py new file mode 100644 index 0000000000..eb5f121fae --- /dev/null +++ b/torchaudio/models/conv_tasnet.py @@ -0,0 +1,327 @@ +"""Implements Conv-TasNet with building blocks of it. + +Based on https://github.com/naplab/Conv-TasNet/tree/e66d82a8f956a69749ec8a4ae382217faa097c5c +""" + +from typing import Tuple, Optional + +import torch + + +class ConvBlock(torch.nn.Module): + """1D Convolutional block. + + Args: + io_channels (int): The number of input/output channels, + hidden_channels (int): The number of channels in the internal layers, . + kernel_size (int): The convolution kernel size of the middle layer,

. + padding (int): Padding value of the convolution in the middle layer. + dilation (int): Dilation value of the convolution in the middle layer. + no_redisual (bool): Disable residual block/output. + + Note: + This implementation corresponds to the "non-causal" setting in the paper. + + Reference: + - Conv-TasNet: Surpassing Ideal Time--Frequency Magnitude Masking for Speech Separation + + Luo, Yi and Mesgarani, Nima + + https://arxiv.org/abs/1809.07454 + """ + + def __init__( + self, + io_channels: int, + hidden_channels: int, + kernel_size: int, + padding: int, + dilation: int = 1, + no_residual: bool = False, + ): + super().__init__() + + self.conv_layers = torch.nn.Sequential( + torch.nn.Conv1d( + in_channels=io_channels, out_channels=hidden_channels, kernel_size=1 + ), + torch.nn.PReLU(), + torch.nn.GroupNorm(num_groups=1, num_channels=hidden_channels, eps=1e-08), + torch.nn.Conv1d( + in_channels=hidden_channels, + out_channels=hidden_channels, + kernel_size=kernel_size, + padding=padding, + dilation=dilation, + groups=hidden_channels, + ), + torch.nn.PReLU(), + torch.nn.GroupNorm(num_groups=1, num_channels=hidden_channels, eps=1e-08), + ) + + self.res_out = ( + None + if no_residual + else torch.nn.Conv1d( + in_channels=hidden_channels, out_channels=io_channels, kernel_size=1 + ) + ) + self.skip_out = torch.nn.Conv1d( + in_channels=hidden_channels, out_channels=io_channels, kernel_size=1 + ) + + def forward( + self, input: torch.Tensor + ) -> Tuple[Optional[torch.Tensor], torch.Tensor]: + feature = self.conv_layers(input) + if self.res_out is None: + residual = None + else: + residual = self.res_out(feature) + skip_out = self.skip_out(feature) + return residual, skip_out + + +class MaskGenerator(torch.nn.Module): + """TCN (Temporal Convolution Network) Separation Module + + Generates masks for separation. + + Args: + input_dim (int): Input feature dimension, . + num_sources (int): The number of sources to separate. + kernel_size (int): The convolution kernel size of conv blocks,

. + num_featrs (int): Input/output feature dimenstion of conv blocks, . + num_hidden (int): Intermediate feature dimention of conv blocks, + num_layers (int): The number of conv blocks in one stack, . + num_stacks (int): The number of conv block stacks, . + + Note: + This implementation corresponds to the "non-causal" setting in the paper. + + References: + - Conv-TasNet: Surpassing Ideal Time--Frequency Magnitude Masking for Speech Separation + Luo, Yi and Mesgarani, Nima + https://arxiv.org/abs/1809.07454 + """ + + def __init__( + self, + input_dim: int, + num_sources: int, + kernel_size: int, + num_feats: int, + num_hidden: int, + num_layers: int, + num_stacks: int, + ): + super().__init__() + + self.input_dim = input_dim + self.num_sources = num_sources + + self.input_norm = torch.nn.GroupNorm( + num_groups=1, num_channels=input_dim, eps=1e-8 + ) + self.input_conv = torch.nn.Conv1d( + in_channels=input_dim, out_channels=num_feats, kernel_size=1 + ) + + self.receptive_field = 0 + self.conv_layers = torch.nn.ModuleList([]) + for s in range(num_stacks): + for l in range(num_layers): + multi = 2 ** l + self.conv_layers.append( + ConvBlock( + io_channels=num_feats, + hidden_channels=num_hidden, + kernel_size=kernel_size, + dilation=multi, + padding=multi, + # The last ConvBlock does not need residual + no_residual=(l == (num_layers - 1) and s == (num_stacks - 1)), + ) + ) + self.receptive_field += ( + kernel_size if s == 0 and l == 0 else (kernel_size - 1) * multi + ) + self.output_prelu = torch.nn.PReLU() + self.output_conv = torch.nn.Conv1d( + in_channels=num_feats, out_channels=input_dim * num_sources, kernel_size=1, + ) + + def forward(self, input: torch.Tensor) -> torch.Tensor: + """Generate separation mask. + + Args: + input (torch.Tensor): 3D Tensor with shape [batch, features, frames] + + Returns: + torch.Tensor: shape [batch, num_sources, features, frames] + """ + batch_size = input.shape[0] + feats = self.input_norm(input) + feats = self.input_conv(feats) + output = 0.0 + for layer in self.conv_layers: + residual, skip = layer(feats) + if residual is not None: # the last conv layer does not produce residual + feats = feats + residual + output = output + skip + output = self.output_prelu(output) + output = self.output_conv(output) + output = torch.sigmoid(output) + return output.view(batch_size, self.num_sources, self.input_dim, -1) + + +class ConvTasNet(torch.nn.Module): + """Conv-TasNet: a fully-convolutional time-domain audio separation network + + Args: + num_sources (int): The number of sources to split. + enc_kernel_size (int): The convolution kernel size of the encoder/decoder, . + enc_num_feats (int): The feature dimensions passed to mask generator, . + msk_kernel_size (int): The convolution kernel size of the mask generator,

Click here for the examples on how to install SoX - -OSX (Homebrew): -```bash -brew install sox -``` - -Linux (Ubuntu): -```bash -sudo apt-get install sox libsox-dev libsox-fmt-all -``` - -Anaconda -```bash -conda install -c conda-forge sox -``` - -
- -```bash -# Linux -python setup.py install - -# OSX -MACOSX_DEPLOYMENT_TARGET=10.9 CC=clang CXX=clang++ python setup.py install -``` - -Alternatively, the build process can build libsox and some optional codecs statically and torchaudio can link them, by setting environment variable `BUILD_SOX=1`. +The build process builds libsox and some codecs that torchaudio need to link to. This is achieve by setting the environment variable `BUILD_SOX=1`. The build process will fetch and build libmad, lame, flac, vorbis, opus, and libsox before building extension. This process requires `cmake` and `pkg-config`. ```bash @@ -195,16 +164,16 @@ Conventions With torchaudio being a machine learning library and built on top of PyTorch, torchaudio is standardized around the following naming conventions. Tensors are -assumed to have channels as the first dimension and time as the last +assumed to have "channel" as the first dimension and time as the last dimension (when applicable). This makes it consistent with PyTorch's dimensions. For size names, the prefix `n_` is used (e.g. "a tensor of size (`n_freq`, `n_mel`)") whereas dimension names do not have this prefix (e.g. "a tensor of -dimension (channels, time)") +dimension (channel, time)") -* `waveform`: a tensor of audio samples with dimensions (channels, time) +* `waveform`: a tensor of audio samples with dimensions (channel, time) * `sample_rate`: the rate of audio dimensions (samples per second) -* `specgram`: a tensor of spectrogram with dimensions (channels, freq, time) -* `mel_specgram`: a mel spectrogram with dimensions (channels, mel, time) +* `specgram`: a tensor of spectrogram with dimensions (channel, freq, time) +* `mel_specgram`: a mel spectrogram with dimensions (channel, mel, time) * `hop_length`: the number of samples between the starts of consecutive frames * `n_fft`: the number of Fourier bins * `n_mel`, `n_mfcc`: the number of mel and MFCC bins @@ -216,16 +185,16 @@ dimension (channels, time)") Transforms expect and return the following dimensions. -* `Spectrogram`: (channels, time) -> (channels, freq, time) -* `AmplitudeToDB`: (channels, freq, time) -> (channels, freq, time) -* `MelScale`: (channels, freq, time) -> (channels, mel, time) -* `MelSpectrogram`: (channels, time) -> (channels, mel, time) -* `MFCC`: (channels, time) -> (channel, mfcc, time) -* `MuLawEncode`: (channels, time) -> (channels, time) -* `MuLawDecode`: (channels, time) -> (channels, time) -* `Resample`: (channels, time) -> (channels, time) -* `Fade`: (channels, time) -> (channels, time) -* `Vol`: (channels, time) -> (channels, time) +* `Spectrogram`: (channel, time) -> (channel, freq, time) +* `AmplitudeToDB`: (channel, freq, time) -> (channel, freq, time) +* `MelScale`: (channel, freq, time) -> (channel, mel, time) +* `MelSpectrogram`: (channel, time) -> (channel, mel, time) +* `MFCC`: (channel, time) -> (channel, mfcc, time) +* `MuLawEncode`: (channel, time) -> (channel, time) +* `MuLawDecode`: (channel, time) -> (channel, time) +* `Resample`: (channel, time) -> (channel, time) +* `Fade`: (channel, time) -> (channel, time) +* `Vol`: (channel, time) -> (channel, time) Complex numbers are supported via tensors of dimension (..., 2), and torchaudio provides `complex_norm` and `angle` to convert such a tensor into its magnitude and phase. Here, and in the documentation, we use an ellipsis "..." as a placeholder for the rest of the dimensions of a tensor, e.g. optional batching and channel dimensions. diff --git a/build_tools/setup_helpers/extension.py b/build_tools/setup_helpers/extension.py index d34464ed37..4e04097716 100644 --- a/build_tools/setup_helpers/extension.py +++ b/build_tools/setup_helpers/extension.py @@ -18,7 +18,10 @@ _TORCHAUDIO_DIR = _ROOT_DIR / 'torchaudio' -def _get_build(var): +def _get_build(var, default=False): + if var not in os.environ: + return default + val = os.environ.get(var, '0') trues = ['1', 'true', 'TRUE', 'on', 'ON', 'yes', 'YES'] falses = ['0', 'false', 'FALSE', 'off', 'OFF', 'no', 'NO'] @@ -31,13 +34,12 @@ def _get_build(var): return False -_BUILD_SOX = _get_build("BUILD_SOX") +_BUILD_SOX = False if platform.system() == 'Windows' else _get_build("BUILD_SOX") +_BUILD_KALDI = False if platform.system() == 'Windows' else _get_build("BUILD_KALDI", True) _BUILD_TRANSDUCER = _get_build("BUILD_TRANSDUCER") def get_ext_modules(): - if platform.system() == 'Windows': - return None return [Extension(name='torchaudio._torchaudio', sources=[])] @@ -68,6 +70,7 @@ def build_extension(self, ext): '-DCMAKE_VERBOSE_MAKEFILE=ON', f"-DPython_INCLUDE_DIR={distutils.sysconfig.get_python_inc()}", f"-DBUILD_SOX:BOOL={'ON' if _BUILD_SOX else 'OFF'}", + f"-DBUILD_KALDI:BOOL={'ON' if _BUILD_KALDI else 'OFF'}", f"-DBUILD_TRANSDUCER:BOOL={'ON' if _BUILD_TRANSDUCER else 'OFF'}", "-DBUILD_TORCHAUDIO_PYTHON_EXTENSION:BOOL=ON", "-DBUILD_LIBTORCHAUDIO:BOOL=OFF", @@ -77,8 +80,16 @@ def build_extension(self, ext): ] # Default to Ninja - if 'CMAKE_GENERATOR' not in os.environ: + if 'CMAKE_GENERATOR' not in os.environ or platform.system() == 'Windows': cmake_args += ["-GNinja"] + if platform.system() == 'Windows': + import sys + python_version = sys.version_info + cmake_args += [ + "-DCMAKE_C_COMPILER=cl", + "-DCMAKE_CXX_COMPILER=cl", + f"-DPYTHON_VERSION={python_version.major}.{python_version.minor}", + ] # Set CMAKE_BUILD_PARALLEL_LEVEL to control the parallel build level # across all generators. diff --git a/docs/Makefile b/docs/Makefile index 630a95dc19..76b604393a 100644 --- a/docs/Makefile +++ b/docs/Makefile @@ -2,7 +2,7 @@ # # You can set these variables from the command line. -SPHINXOPTS = +SPHINXOPTS = -W # converts warnings into error SPHINXBUILD = sphinx-build SPHINXPROJ = torchaudio SOURCEDIR = source diff --git a/docs/source/_templates/layout.html b/docs/source/_templates/layout.html new file mode 100644 index 0000000000..8727b6ce5d --- /dev/null +++ b/docs/source/_templates/layout.html @@ -0,0 +1,8 @@ +{% extends "!layout.html" %} + +{% block sidebartitle %} + + {% include "searchbox.html" %} +{% endblock %} diff --git a/docs/source/backend.rst b/docs/source/backend.rst index 1cdb1c923e..6eda225307 100644 --- a/docs/source/backend.rst +++ b/docs/source/backend.rst @@ -6,49 +6,23 @@ torchaudio.backend Overview ~~~~~~~~ -:mod:`torchaudio.backend` module provides implementations for audio file I/O functionalities, which are ``torchaudio.info``, ``torchaudio.load``, ``torchaudio.load_wav`` and ``torchaudio.save``. +:mod:`torchaudio.backend` module provides implementations for audio file I/O functionalities, which are ``torchaudio.info``, ``torchaudio.load``, and ``torchaudio.save``. There are currently four implementations available. * :ref:`"sox_io" ` (default on Linux/macOS) -* :ref:`"sox" ` (deprecated, will be removed in 0.9.0 release) * :ref:`"soundfile" ` (default on Windows) -* :ref:`"soundfile" (legacy interface) ` (deprecated, will be removed in 0.9.0 release) - -The use of ``"sox"`` backend is strongly discouraged as it cannot correctly handle formats other than 16-bit integer WAV. See `#726 `_ for the detail. .. note:: - Instead of calling functions in ``torchaudio.backend`` directly, please use ``torchaudio.info``, ``torchaudio.load``, ``torchaudio.load_wav`` and ``torchaudio.save`` with proper backend set with :func:`torchaudio.set_audio_backend`. + Instead of calling functions in ``torchaudio.backend`` directly, please use ``torchaudio.info``, ``torchaudio.load``, and ``torchaudio.save`` with proper backend set with :func:`torchaudio.set_audio_backend`. Availability ------------ -``"sox"`` and ``"sox_io"`` backends require C++ extension module, which is included in Linux/macOS binary distributions. These backends are not available on Windows. +``"sox_io"`` backend requires C++ extension module, which is included in Linux/macOS binary distributions. This backend is not available on Windows. ``"soundfile"`` backend requires ``SoundFile``. Please refer to `the SoundFile documentation `_ for the installation. -Changes in default backend and deprecation ------------------------------------------- - -Backend module is going through a major overhaul. The following table summarizes the timeline for the deprecations and removals. - - +--------------------+-----------------------+------------------------+ - | **Backend** | **0.8.0** | **0.9.0** | - +====================+=======================+========================+ - | ``"sox_io"`` | Default on Linx/macOS | Default on Linux/macOS | - +--------------------+-----------------------+------------------------+ - | ``"sox"`` | Available | Removed | - | (deprecated) | | | - +--------------------+-----------------------+------------------------+ - | ``"soundfile"`` | Default on Windows | Default on Windows | - +--------------------+-----------------------+------------------------+ - | ``"soundfile"`` | Available | Removed | - | (legacy interface, | | | - | deprecated) | | | - +--------------------+-----------------------+------------------------+ - -* The ``"sox"`` and ``"soundfile" (legacy interface)`` backends are deprecated and will be removed in 0.9.0 release. - Common Data Structure ~~~~~~~~~~~~~~~~~~~~~ @@ -59,16 +33,6 @@ AudioMetaData .. autoclass:: torchaudio.backend.common.AudioMetaData -SignalInfo (Deprecated) ------------------------ - -.. autoclass:: torchaudio.backend.common.SignalInfo - -EncodingInfo (Deprecated) -------------------------- - -.. autoclass:: torchaudio.backend.common.EncodingInfo - .. _sox_io_backend: Sox IO Backend @@ -94,52 +58,11 @@ load .. autofunction:: torchaudio.backend.sox_io_backend.load -.. autofunction:: torchaudio.backend.sox_io_backend.load_wav - - save ---- .. autofunction:: torchaudio.backend.sox_io_backend.save -.. _sox_backend: - -Sox Backend (Deprecated) -~~~~~~~~~~~~~~~~~~~~~~~~ - -The ``"sox"`` backend is available on Linux/macOS and not available on Windows. This backend is deprecated and will be removed in ``0.9.0`` release. - -You can switch from another backend to ``sox`` backend with the following; - -.. code:: - - torchaudio.set_audio_backend("sox") - -info ----- - -.. autofunction:: torchaudio.backend.sox_backend.info - -load ----- - -.. autofunction:: torchaudio.backend.sox_backend.load - -.. autofunction:: torchaudio.backend.sox_backend.load_wav - - -save ----- - -.. autofunction:: torchaudio.backend.sox_backend.save - -others ------- - -.. automodule:: torchaudio.backend.sox_backend - :members: - :exclude-members: info, load, load_wav, save - .. _soundfile_backend: Soundfile Backend @@ -153,55 +76,17 @@ You can switch from another backend to the ``"soundfile"`` backend with the foll torchaudio.set_audio_backend("soundfile") -.. note:: - If you are switching from `"soundfile" (legacy interface) ` backend, set ``torchaudio.USE_SOUNDFILE_LEGACY_INTERFACE`` flag **before** switching the backend. - info -^^^^ - -.. autofunction:: torchaudio.backend._soundfile_backend.info - -load -^^^^ - -.. autofunction:: torchaudio.backend._soundfile_backend.load - -.. autofunction:: torchaudio.backend._soundfile_backend.load_wav - - -save -^^^^ - -.. autofunction:: torchaudio.backend._soundfile_backend.save - -.. _soundfile_legacy_backend: - -Legacy Interface (Deprecated) ------------------------------ - -``"soundfile"`` backend with legacy interface is made available for backward compatibility reason, however this interface is deprecated and will be removed in the ``0.9.0`` release. - -To switch to this backend/interface, set ``torchaudio.USE_SOUNDFILE_LEGACY_INTERFACE`` flag **before** switching the backend. - -.. code:: - - torchaudio.USE_SOUNDFILE_LEGACY_INTERFACE = True - torchaudio.set_audio_backend("soundfile") # The legacy interface - -info -^^^^ +---- .. autofunction:: torchaudio.backend.soundfile_backend.info load -^^^^ +---- .. autofunction:: torchaudio.backend.soundfile_backend.load -.. autofunction:: torchaudio.backend.soundfile_backend.load_wav - - save -^^^^ +---- .. autofunction:: torchaudio.backend.soundfile_backend.save diff --git a/docs/source/conf.py b/docs/source/conf.py index 9d8faaa61b..3bc89e999d 100644 --- a/docs/source/conf.py +++ b/docs/source/conf.py @@ -20,8 +20,6 @@ # import os # import sys # sys.path.insert(0, os.path.abspath('.')) -import torch -import torchaudio import pytorch_sphinx_theme # -- General configuration ------------------------------------------------ @@ -58,6 +56,8 @@ ''' napoleon_use_ivar = True +napoleon_numpy_docstring = False +napoleon_google_docstring = True # Add any paths that contain templates here, relative to this directory. templates_path = ['_templates'] @@ -123,6 +123,7 @@ 'collapse_navigation': False, 'display_version': True, 'logo_only': True, + 'navigation_with_keys': True } html_logo = '_static/img/pytorch-logo-dark.svg' @@ -132,6 +133,7 @@ # so a file named "default.css" will overwrite the builtin "default.css". html_static_path = ['_static'] + def setup(app): # NOTE: in Sphinx 1.8+ `html_css_files` is an official configuration value # and can be moved outside of this function (and the setup(app) function @@ -142,7 +144,7 @@ def setup(app): # In Sphinx 1.8 it was renamed to `add_css_file`, 1.7 and prior it is # `add_stylesheet` (deprecated in 1.8). - add_css = getattr(app, 'add_css_file', getattr(app, 'add_stylesheet')) + add_css = getattr(app, 'add_css_file', app.add_stylesheet) for css_file in html_css_files: add_css(css_file) @@ -223,7 +225,7 @@ def patched_make_field(self, types, domain, items, **kw): # `kw` catches `env=None` needed for newer sphinx while maintaining # backwards compatibility when passed along further down! - # type: (List, unicode, Tuple) -> nodes.field + # type: (list, str, tuple) -> nodes.field def handle_item(fieldarg, content): par = nodes.paragraph() par += addnodes.literal_strong('', fieldarg) # Patch: this line added diff --git a/docs/source/functional.rst b/docs/source/functional.rst index ebed60de6b..e52e83ca42 100644 --- a/docs/source/functional.rst +++ b/docs/source/functional.rst @@ -8,6 +8,75 @@ torchaudio.functional Functions to perform common audio operations. +:hidden:`Utility` +~~~~~~~~~~~~~~~~~ + +amplitude_to_DB +--------------- + +.. autofunction:: amplitude_to_DB + +DB_to_amplitude +--------------- + +.. autofunction:: DB_to_amplitude + +create_fb_matrix +---------------- + +.. autofunction:: create_fb_matrix + +create_dct +---------- + +.. autofunction:: create_dct + +mask_along_axis +--------------- + +.. autofunction:: mask_along_axis + +mask_along_axis_iid +------------------- + +.. autofunction:: mask_along_axis_iid + +mu_law_encoding +--------------- + +.. autofunction:: mu_law_encoding + +mu_law_decoding +--------------- + +.. autofunction:: mu_law_decoding + +apply_codec +----------- + +.. autofunction:: apply_codec + +:hidden:`Complex Utility` +~~~~~~~~~~~~~~~~~~~~~~~~~ + +Utilities for pseudo complex tensor. This is not for the native complex dtype, such as `cfloat64`, but for tensors with real-value type and have extra dimension at the end for real and imaginary parts. + +angle +----- + +.. autofunction:: angle + +complex_norm +------------ + +.. autofunction:: complex_norm + + +magphase +-------- + +.. autofunction:: magphase + :hidden:`Filtering` ~~~~~~~~~~~~~~~~~~~ @@ -117,89 +186,47 @@ treble_biquad vad --- +:hidden:`Feature Extractions` +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + .. autofunction:: vad :hidden:`spectrogram` -~~~~~~~~~~~~~~~~~~~~~ +--------------------- .. autofunction:: spectrogram :hidden:`griffinlim` -~~~~~~~~~~~~~~~~~~~~~~~~~ +-------------------- .. autofunction:: griffinlim -:hidden:`amplitude_to_DB` -~~~~~~~~~~~~~~~~~~~~~~~~~ - -.. autofunction:: amplitude_to_DB - -:hidden:`DB_to_amplitude` -~~~~~~~~~~~~~~~~~~~~~~~~~ - -.. autofunction:: DB_to_amplitude - -:hidden:`create_fb_matrix` -~~~~~~~~~~~~~~~~~~~~~~~~~~ - -.. autofunction:: create_fb_matrix - -:hidden:`create_dct` -~~~~~~~~~~~~~~~~~~~~ - -.. autofunction:: create_dct - -:hidden:`mu_law_encoding` -~~~~~~~~~~~~~~~~~~~~~~~~~ - -.. autofunction:: mu_law_encoding - -:hidden:`mu_law_decoding` -~~~~~~~~~~~~~~~~~~~~~~~~~ - -.. autofunction:: mu_law_decoding - -:hidden:`complex_norm` -~~~~~~~~~~~~~~~~~~~~~~ - -.. autofunction:: complex_norm - -:hidden:`angle` -~~~~~~~~~~~~~~~ - -.. autofunction:: angle - -:hidden:`magphase` -~~~~~~~~~~~~~~~~~~ - -.. autofunction:: magphase - :hidden:`phase_vocoder` -~~~~~~~~~~~~~~~~~~~~~~~ +----------------------- .. autofunction:: phase_vocoder -:hidden:`mask_along_axis` -~~~~~~~~~~~~~~~~~~~~~~~~~ - -.. autofunction:: mask_along_axis - -:hidden:`mask_along_axis_iid` -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -.. autofunction:: mask_along_axis_iid - :hidden:`compute_deltas` -~~~~~~~~~~~~~~~~~~~~~~~~ +------------------------ .. autofunction:: compute_deltas :hidden:`detect_pitch_frequency` -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +-------------------------------- .. autofunction:: detect_pitch_frequency :hidden:`sliding_window_cmn` -~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +---------------------------- .. autofunction:: sliding_window_cmn + +:hidden:`compute_kaldi_pitch` +----------------------------- + +.. autofunction:: compute_kaldi_pitch + +:hidden:`spectral_centroid` +--------------------------- + +.. autofunction:: spectral_centroid diff --git a/docs/source/torchaudio.rst b/docs/source/torchaudio.rst index 480be4393e..cb616d01aa 100644 --- a/docs/source/torchaudio.rst +++ b/docs/source/torchaudio.rst @@ -16,10 +16,6 @@ Refer to :ref:`backend` for the detail. Load audio file into torch.Tensor object. Refer to :ref:`backend` for the detail. -.. function:: torchaudio.load_wav(filepath: str, ...) - - Load audio file into torch.Tensor, Refer to :ref:`backend` for the detail. - .. function:: torchaudio.save(filepath: str, src: torch.Tensor, sample_rate: int, ...) Save torch.Tensor object into an audio format. Refer to :ref:`backend` for the detail. diff --git a/docs/source/transforms.rst b/docs/source/transforms.rst index fc6a4d4a9f..8269193e22 100644 --- a/docs/source/transforms.rst +++ b/docs/source/transforms.rst @@ -136,6 +136,13 @@ Transforms are common audio transforms. They can be chained together using :clas .. automethod:: forward +:hidden:`SpectralCentroid` +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +.. autoclass:: SpectralCentroid + + .. automethod:: forward + :hidden:`Vad` ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ diff --git a/examples/interactive_asr/vad.py b/examples/interactive_asr/vad.py index 6a363941b0..bc942032b0 100644 --- a/examples/interactive_asr/vad.py +++ b/examples/interactive_asr/vad.py @@ -35,7 +35,7 @@ def compute_spectral_flatness(frame, epsilon=0.01): return -10 * torch.log10(epsilon + geometric_mean / arithmetic_mean) -class VoiceActivityDetection(object): +class VoiceActivityDetection: def __init__( self, num_init_frames=30, @@ -148,7 +148,7 @@ def iter(self, frame): return self.silence_mark -class MicrophoneStream(object): +class MicrophoneStream: """Opens a recording stream as a generator yielding the audio chunks.""" def __init__(self, device=None, rate=22050, chunk=2205): diff --git a/examples/libtorchaudio/.gitignore b/examples/libtorchaudio/.gitignore new file mode 100644 index 0000000000..f03338dc7d --- /dev/null +++ b/examples/libtorchaudio/.gitignore @@ -0,0 +1,3 @@ +build +data/output.wav +data/pipeline.zip diff --git a/examples/libtorchaudio/CMakeLists.txt b/examples/libtorchaudio/CMakeLists.txt new file mode 100644 index 0000000000..264949bc12 --- /dev/null +++ b/examples/libtorchaudio/CMakeLists.txt @@ -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) diff --git a/examples/libtorchaudio/README.md b/examples/libtorchaudio/README.md new file mode 100644 index 0000000000..10f1228894 --- /dev/null +++ b/examples/libtorchaudio/README.md @@ -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). diff --git a/examples/libtorchaudio/create_jittable_pipeline.py b/examples/libtorchaudio/create_jittable_pipeline.py new file mode 100755 index 0000000000..14a7eefd50 --- /dev/null +++ b/examples/libtorchaudio/create_jittable_pipeline.py @@ -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() diff --git a/examples/libtorchaudio/data/README.md b/examples/libtorchaudio/data/README.md new file mode 100644 index 0000000000..6e2ff19097 --- /dev/null +++ b/examples/libtorchaudio/data/README.md @@ -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` diff --git a/examples/libtorchaudio/data/input.wav b/examples/libtorchaudio/data/input.wav new file mode 100644 index 0000000000000000000000000000000000000000..004a33532ea2547c10c0074b967733ba91edd9f8 GIT binary patch literal 108844 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

. + msk_num_feats (int): The input/output feature dimension of conv block in the mask generator, . + msk_num_hidden_feats (int): The internal feature dimension of conv block of the mask generator, . + msk_num_layers (int): The number of layers in one conv block of the mask generator, . + msk_num_stacks (int): The numbr of conv blocks of the mask generator, . + + Note: + This implementation corresponds to the "non-causal" setting in the paper. + + Reference: + - Conv-TasNet: Surpassing Ideal Time--Frequency Magnitude Masking for Speech Separation + + Luo, Yi and Mesgarani, Nima + + https://arxiv.org/abs/1809.07454 + """ + + def __init__( + self, + num_sources: int = 2, + # encoder/decoder parameters + enc_kernel_size: int = 16, + enc_num_feats: int = 512, + # mask generator parameters + msk_kernel_size: int = 3, + msk_num_feats: int = 128, + msk_num_hidden_feats: int = 512, + msk_num_layers: int = 8, + msk_num_stacks: int = 3, + ): + super().__init__() + + self.num_sources = num_sources + self.enc_num_feats = enc_num_feats + self.enc_kernel_size = enc_kernel_size + self.enc_stride = enc_kernel_size // 2 + + self.encoder = torch.nn.Conv1d( + in_channels=1, + out_channels=enc_num_feats, + kernel_size=enc_kernel_size, + stride=self.enc_stride, + padding=self.enc_stride, + bias=False, + ) + self.mask_generator = MaskGenerator( + input_dim=enc_num_feats, + num_sources=num_sources, + kernel_size=msk_kernel_size, + num_feats=msk_num_feats, + num_hidden=msk_num_hidden_feats, + num_layers=msk_num_layers, + num_stacks=msk_num_stacks, + ) + self.decoder = torch.nn.ConvTranspose1d( + in_channels=enc_num_feats, + out_channels=1, + kernel_size=enc_kernel_size, + stride=self.enc_stride, + padding=self.enc_stride, + bias=False, + ) + + def _align_num_frames_with_strides( + self, input: torch.Tensor + ) -> Tuple[torch.Tensor, int]: + """Pad input Tensor so that the end of the input tensor corresponds with + + 1. (if kernel size is odd) the center of the last convolution kernel + or 2. (if kernel size is even) the end of the first half of the last convolution kernel + + Assumption: + The resulting Tensor will be padded with the size of stride (== kernel_width // 2) + on the both ends in Conv1D + + |<--- k_1 --->| + | | |<-- k_n-1 -->| + | | | |<--- k_n --->| + | | | | | + | | | | | + | v v v | + |<---->|<--- input signal --->|<--->|<---->| + stride PAD stride + + Args: + input (torch.Tensor): 3D Tensor with shape (batch_size, channels==1, frames) + + Returns: + torch.Tensor: Padded Tensor + int: Number of paddings performed + """ + batch_size, num_channels, num_frames = input.shape + is_odd = self.enc_kernel_size % 2 + num_strides = (num_frames - is_odd) // self.enc_stride + num_remainings = num_frames - (is_odd + num_strides * self.enc_stride) + if num_remainings == 0: + return input, 0 + + num_paddings = self.enc_stride - num_remainings + pad = torch.zeros( + batch_size, + num_channels, + num_paddings, + dtype=input.dtype, + device=input.device, + ) + return torch.cat([input, pad], 2), num_paddings + + def forward(self, input: torch.Tensor) -> torch.Tensor: + """Perform source separation. Generate audio source waveforms. + + Args: + input (torch.Tensor): 3D Tensor with shape [batch, channel==1, frames] + + Returns: + torch.Tensor: 3D Tensor with shape [batch, channel==num_sources, frames] + """ + if input.ndim != 3 or input.shape[1] != 1: + raise ValueError( + f"Expected 3D tensor (batch, channel==1, frames). Found: {input.shape}" + ) + + # B: batch size + # L: input frame length + # L': padded input frame length + # F: feature dimension + # M: feature frame length + # S: number of sources + + padded, num_pads = self._align_num_frames_with_strides(input) # B, 1, L' + batch_size, num_padded_frames = padded.shape[0], padded.shape[2] + feats = self.encoder(padded) # B, F, M + masked = self.mask_generator(feats) * feats.unsqueeze(1) # B, S, F, M + masked = masked.view( + batch_size * self.num_sources, self.enc_num_feats, -1 + ) # B*S, F, M + decoded = self.decoder(masked) # B*S, 1, L' + output = decoded.view( + batch_size, self.num_sources, num_padded_frames + ) # B, S, L' + if num_pads > 0: + output = output[..., :-num_pads] # B, S, L + return output diff --git a/torchaudio/sox_effects/__init__.py b/torchaudio/sox_effects/__init__.py index d9650173c5..5baf406b10 100644 --- a/torchaudio/sox_effects/__init__.py +++ b/torchaudio/sox_effects/__init__.py @@ -5,8 +5,6 @@ effect_names, apply_effects_tensor, apply_effects_file, - SoxEffect, - SoxEffectsChain, ) diff --git a/torchaudio/sox_effects/sox_effects.py b/torchaudio/sox_effects/sox_effects.py index 9262786541..8b50d19aa7 100644 --- a/torchaudio/sox_effects/sox_effects.py +++ b/torchaudio/sox_effects/sox_effects.py @@ -1,19 +1,11 @@ -from typing import Any, Callable, List, Optional, Tuple, Union +from typing import List, Tuple import torch -from torch import Tensor -from torchaudio._internal import ( - module_utils as _mod_utils, - misc_ops as _misc_ops, -) +from torchaudio._internal import module_utils as _mod_utils from torchaudio.utils.sox_utils import list_effects -if _mod_utils.is_module_available('torchaudio._torchaudio'): - from torchaudio import _torchaudio - - @_mod_utils.requires_module('torchaudio._torchaudio') def init_sox_effects(): """Initialize resources required to use sox effects. @@ -257,189 +249,3 @@ def apply_effects_file( """ signal = torch.ops.torchaudio.sox_effects_apply_effects_file(path, effects, normalize, channels_first) return signal.get_tensor(), signal.get_sample_rate() - - -@_mod_utils.requires_module('torchaudio._torchaudio') -@_mod_utils.deprecated('Please migrate to `apply_effects_file` or `apply_effects_tensor`.') -def SoxEffect(): - r"""Create an object for passing sox effect information between python and c++ - - Warning: - This function is deprecated. - Please migrate to :func:`apply_effects_file` or :func:`apply_effects_tensor`. - - Returns: - SoxEffect: An object with the following attributes: ename (str) which is the - name of effect, and eopts (List[str]) which is a list of effect options. - """ - return _torchaudio.SoxEffect() - - -@_mod_utils.deprecated('Please migrate to `apply_effects_file` or `apply_effects_tensor`.') -class SoxEffectsChain(object): - r"""SoX effects chain class. - - Warning: - This class is deprecated. - Please migrate to :func:`apply_effects_file` or :func:`apply_effects_tensor`. - - Args: - normalization (bool, number, or callable, optional): - If boolean ``True``, then output is divided by ``1 << 31`` - (assumes signed 32-bit audio), and normalizes to ``[-1, 1]``. - If ``number``, then output is divided by that number. - If ``callable``, then the output is passed as a parameter to the given function, then - the output is divided by the result. (Default: ``True``) - channels_first (bool, optional): - Set channels first or length first in result. (Default: ``True``) - out_siginfo (sox_signalinfo_t, optional): - a sox_signalinfo_t type, which could be helpful if the audio type cannot be - automatically determined. (Default: ``None``) - out_encinfo (sox_encodinginfo_t, optional): - a sox_encodinginfo_t type, which could be set if the audio type cannot be - automatically determined. (Default: ``None``) - filetype (str, optional): - a filetype or extension to be set if sox cannot determine it automatically. - (Default: ``'raw'``) - - Returns: - Tuple[Tensor, int]: - An output Tensor of size ``[C x L]`` or ``[L x C]`` where L is the number - of audio frames and C is the number of channels. An integer which is the sample rate of the - audio (as listed in the metadata of the file) - - Example - >>> class MyDataset(Dataset): - ... def __init__(self, audiodir_path): - ... self.data = [ - ... os.path.join(audiodir_path, fn) - ... for fn in os.listdir(audiodir_path)] - ... self.E = torchaudio.sox_effects.SoxEffectsChain() - ... self.E.append_effect_to_chain("rate", [16000]) # resample to 16000hz - ... self.E.append_effect_to_chain("channels", ["1"]) # mono signal - ... def __getitem__(self, index): - ... fn = self.data[index] - ... self.E.set_input_file(fn) - ... x, sr = self.E.sox_build_flow_effects() - ... return x, sr - ... - ... def __len__(self): - ... return len(self.data) - ... - >>> ds = MyDataset(path_to_audio_files) - >>> for sig, sr in ds: - ... pass - """ - - EFFECTS_UNIMPLEMENTED = {"spectrogram", "splice", "noiseprof", "fir"} - - def __init__(self, - normalization: Union[bool, float, Callable] = True, - channels_first: bool = True, - out_siginfo: Any = None, - out_encinfo: Any = None, - filetype: str = "raw") -> None: - self.input_file: Optional[str] = None - self.chain: List[str] = [] - self.MAX_EFFECT_OPTS = 20 - self.out_siginfo = out_siginfo - self.out_encinfo = out_encinfo - self.filetype = filetype - self.normalization = normalization - self.channels_first = channels_first - - # Define in __init__ to avoid calling at import time - self.EFFECTS_AVAILABLE = set(effect_names()) - - def append_effect_to_chain(self, - ename: str, - eargs: Optional[Union[List[str], str]] = None) -> None: - r"""Append effect to a sox effects chain. - - Args: - ename (str): which is the name of effect - eargs (List[str] or str, optional): which is a list of effect options. (Default: ``None``) - """ - e = SoxEffect() - # check if we have a valid effect - ename = self._check_effect(ename) - if eargs is None or eargs == []: - eargs = [""] - elif not isinstance(eargs, list): - eargs = [eargs] - eargs = self._flatten(eargs) - if len(eargs) > self.MAX_EFFECT_OPTS: - raise RuntimeError("Number of effect options ({}) is greater than max " - "suggested number of options {}. Increase MAX_EFFECT_OPTS " - "or lower the number of effect options".format(len(eargs), self.MAX_EFFECT_OPTS)) - e.ename = ename - e.eopts = eargs - self.chain.append(e) - - @_mod_utils.requires_module('torchaudio._torchaudio') - def sox_build_flow_effects(self, - out: Optional[Tensor] = None) -> Tuple[Tensor, int]: - r"""Build effects chain and flow effects from input file to output tensor - - Args: - out (Tensor, optional): Where the output will be written to. (Default: ``None``) - - Returns: - Tuple[Tensor, int]: An output Tensor of size `[C x L]` or `[L x C]` where - L is the number of audio frames and C is the number of channels. - An integer which is the sample rate of the audio (as listed in the metadata of the file) - """ - # initialize output tensor - if out is not None: - _misc_ops.check_input(out) - else: - out = torch.FloatTensor() - if not len(self.chain): - e = SoxEffect() - e.ename = "no_effects" - e.eopts = [""] - self.chain.append(e) - - # print("effect options:", [x.eopts for x in self.chain]) - - sr = _torchaudio.build_flow_effects(self.input_file, - out, - self.channels_first, - self.out_siginfo, - self.out_encinfo, - self.filetype, - self.chain, - self.MAX_EFFECT_OPTS) - - _misc_ops.normalize_audio(out, self.normalization) - - return out, sr - - def clear_chain(self) -> None: - r"""Clear effects chain in python - """ - self.chain = [] - - def set_input_file(self, input_file: str) -> None: - r"""Set input file for input of chain - - Args: - input_file (str): The path to the input file. - """ - self.input_file = input_file - - def _check_effect(self, e: str) -> str: - if e.lower() in self.EFFECTS_UNIMPLEMENTED: - raise NotImplementedError("This effect ({}) is not implement in torchaudio".format(e)) - elif e.lower() not in self.EFFECTS_AVAILABLE: - raise LookupError("Effect name, {}, not valid".format(e.lower())) - return e.lower() - - # https://stackoverflow.com/questions/12472338/flattening-a-list-recursively - # convenience function to flatten list recursively - def _flatten(self, x: list) -> list: - if x == []: - return [] - if isinstance(x[0], list): - return self._flatten(x[:1]) + self._flatten(x[:1]) - return [str(a) for a in x[:1]] + self._flatten(x[1:]) diff --git a/torchaudio/transforms.py b/torchaudio/transforms.py index ef0a58e637..2e7e4f37ee 100644 --- a/torchaudio/transforms.py +++ b/torchaudio/transforms.py @@ -198,7 +198,8 @@ def __init__(self, stype: str = 'power', top_db: Optional[float] = None) -> None def forward(self, x: Tensor) -> Tensor: r"""Numerically stable implementation from Librosa. - https://librosa.github.io/librosa/_modules/librosa/core/spectrum.html + + https://librosa.org/doc/latest/generated/librosa.amplitude_to_db.html Args: x (Tensor): Input tensor before being converted to decibel scale. From 719ebb855a7deaa4913da9215b85521a02ae9371 Mon Sep 17 00:00:00 2001 From: Moto Hira Date: Wed, 11 Nov 2020 13:00:49 -0800 Subject: [PATCH 21/73] Import torchaudio #1004 5e54c77 Summary: Import torchaudio up to #1004 5e54c77 Reviewed By: vincentqb, cpuhrsch Differential Revision: D24841498 fbshipit-source-id: 3829130636f36779d84f01ff0d0120b80b2396d7 --- .circleci/config.yml | 4 +- .circleci/config.yml.in | 2 +- .circleci/regenerate.py | 1 + docs/source/functional.rst | 190 +- docs/source/torchaudio.rst | 7 - examples/pipeline_wav2letter/main.py | 59 +- .../sox_effect/dataset_test.py | 10 + torchaudio/_internal/fft.py | 27 + torchaudio/compliance/kaldi.py | 20 +- torchaudio/functional.py | 2332 ----------------- torchaudio/functional/__init__.py | 42 + torchaudio/functional/filtering.py | 1469 +++++++++++ torchaudio/functional/functional.py | 912 +++++++ 13 files changed, 2602 insertions(+), 2473 deletions(-) create mode 100644 torchaudio/_internal/fft.py delete mode 100644 torchaudio/functional.py create mode 100644 torchaudio/functional/__init__.py create mode 100644 torchaudio/functional/filtering.py create mode 100644 torchaudio/functional/functional.py diff --git a/.circleci/config.yml b/.circleci/config.yml index 472c3f0af6..1f6d664d7e 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -459,7 +459,7 @@ jobs: - third_party/src - run: name: Install torchaudio - command: docker run -t --gpus all -v $PWD:$PWD -w $PWD "${image_name}" .circleci/unittest/linux/scripts/install.sh + command: docker run -t --gpus all -e UPLOAD_CHANNEL -v $PWD:$PWD -w $PWD "${image_name}" .circleci/unittest/linux/scripts/install.sh - run: name: Run tests command: docker run -t --gpus all -v $PWD:$PWD -w $PWD "${image_name}" .circleci/unittest/linux/scripts/run_test.sh @@ -1394,4 +1394,4 @@ workflows: only: - master jobs: - - smoke_test_docker_image_build \ No newline at end of file + - smoke_test_docker_image_build diff --git a/.circleci/config.yml.in b/.circleci/config.yml.in index 6f6838deff..b9fccbaf30 100644 --- a/.circleci/config.yml.in +++ b/.circleci/config.yml.in @@ -459,7 +459,7 @@ jobs: - third_party/src - run: name: Install torchaudio - command: docker run -t --gpus all -v $PWD:$PWD -w $PWD "${image_name}" .circleci/unittest/linux/scripts/install.sh + command: docker run -t --gpus all -e UPLOAD_CHANNEL -v $PWD:$PWD -w $PWD "${image_name}" .circleci/unittest/linux/scripts/install.sh - run: name: Run tests command: docker run -t --gpus all -v $PWD:$PWD -w $PWD "${image_name}" .circleci/unittest/linux/scripts/run_test.sh diff --git a/.circleci/regenerate.py b/.circleci/regenerate.py index 2f4d4088d9..419db311c1 100755 --- a/.circleci/regenerate.py +++ b/.circleci/regenerate.py @@ -178,3 +178,4 @@ def unittest_workflows(indentation=6): build_workflows=build_workflows, unittest_workflows=unittest_workflows, )) + f.write("\n") diff --git a/docs/source/functional.rst b/docs/source/functional.rst index 89e992bb89..a0f3a272cf 100644 --- a/docs/source/functional.rst +++ b/docs/source/functional.rst @@ -8,145 +8,166 @@ torchaudio.functional Functions to perform common audio operations. -:hidden:`spectrogram` -~~~~~~~~~~~~~~~~~~~~~ +:hidden:`Filtering` +~~~~~~~~~~~~~~~~~~~ -.. autofunction:: spectrogram -:hidden:`amplitude_to_DB` -~~~~~~~~~~~~~~~~~~~~~~~~~ +allpass_biquad +-------------- -.. autofunction:: amplitude_to_DB +.. autofunction:: allpass_biquad -:hidden:`create_fb_matrix` -~~~~~~~~~~~~~~~~~~~~~~~~~~ +band_biquad +----------- -.. autofunction:: create_fb_matrix +.. autofunction:: band_biquad -:hidden:`create_dct` -~~~~~~~~~~~~~~~~~~~~ +bandpass_biquad +--------------- -.. autofunction:: create_dct +.. autofunction:: bandpass_biquad -:hidden:`mu_law_encoding` -~~~~~~~~~~~~~~~~~~~~~~~~~ +bandreject_biquad +----------------- -.. autofunction:: mu_law_encoding +.. autofunction:: bandreject_biquad -:hidden:`mu_law_decoding` -~~~~~~~~~~~~~~~~~~~~~~~~~ +bass_biquad +----------- -.. autofunction:: mu_law_decoding +.. autofunction:: bass_biquad -:hidden:`complex_norm` -~~~~~~~~~~~~~~~~~~~~~~ +biquad +------ -.. autofunction:: complex_norm +.. autofunction:: biquad -:hidden:`angle` -~~~~~~~~~~~~~~~ +contrast +-------- -.. autofunction:: angle +.. autofunction:: contrast -:hidden:`magphase` -~~~~~~~~~~~~~~~~~~ +dcshift +------- -.. autofunction:: magphase +.. autofunction:: dcshift -:hidden:`phase_vocoder` -~~~~~~~~~~~~~~~~~~~~~~~ +deemph_biquad +------------- -.. autofunction:: phase_vocoder +.. autofunction:: deemph_biquad -:hidden:`lfilter` -~~~~~~~~~~~~~~~~~ -.. autofunction:: lfilter +dither +------ -:hidden:`biquad` -~~~~~~~~~~~~~~~~ +.. autofunction:: dither -.. autofunction:: biquad +equalizer_biquad +---------------- -:hidden:`lowpass_biquad` -~~~~~~~~~~~~~~~~~~~~~~~~ +.. autofunction:: equalizer_biquad -.. autofunction:: lowpass_biquad +flanger +------- -:hidden:`highpass_biquad` -~~~~~~~~~~~~~~~~~~~~~~~~~ +.. autofunction:: flanger + +gain +---- + +.. autofunction:: gain + +highpass_biquad +--------------- .. autofunction:: highpass_biquad -:hidden:`allpass_biquad` -~~~~~~~~~~~~~~~~~~~~~~~~ +lfilter +------- -.. autofunction:: allpass_biquad +.. autofunction:: lfilter -:hidden:`equalizer_biquad` -~~~~~~~~~~~~~~~~~~~~~~~~~~ +lowpass_biquad +-------------- -.. autofunction:: equalizer_biquad +.. autofunction:: lowpass_biquad -:hidden:`bandpass_biquad` -~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +overdrive +--------- -.. autofunction:: bandpass_biquad +.. autofunction:: overdrive -:hidden:`bandreject_biquad` -~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +phaser +------ -.. autofunction:: bandreject_biquad +.. autofunction:: phaser -:hidden:`band_biquad` -~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +riaa_biquad +----------- -.. autofunction:: band_biquad +.. autofunction:: riaa_biquad -:hidden:`treble_biquad` -~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +treble_biquad +------------- .. autofunction:: treble_biquad -:hidden:`bass_biquad` -~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -.. autofunction:: bass_biquad +vad +--- -:hidden:`deemph_biquad` -~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +.. autofunction:: vad -.. autofunction:: deemph_biquad +:hidden:`spectrogram` +~~~~~~~~~~~~~~~~~~~~~ -:hidden:`riaa_biquad` -~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +.. autofunction:: spectrogram -.. autofunction:: riaa_biquad +:hidden:`amplitude_to_DB` +~~~~~~~~~~~~~~~~~~~~~~~~~ -:hidden:`contrast` -~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +.. autofunction:: amplitude_to_DB -.. autofunction:: contrast +:hidden:`create_fb_matrix` +~~~~~~~~~~~~~~~~~~~~~~~~~~ -:hidden:`dcshift` -~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +.. autofunction:: create_fb_matrix -.. autofunction:: dcshift +:hidden:`create_dct` +~~~~~~~~~~~~~~~~~~~~ -:hidden:`overdrive` -~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +.. autofunction:: create_dct -.. autofunction:: overdrive +:hidden:`mu_law_encoding` +~~~~~~~~~~~~~~~~~~~~~~~~~ -:hidden:`phaser` -~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +.. autofunction:: mu_law_encoding -.. autofunction:: phaser +:hidden:`mu_law_decoding` +~~~~~~~~~~~~~~~~~~~~~~~~~ -:hidden:`flanger` -~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +.. autofunction:: mu_law_decoding -.. autofunction:: flanger +:hidden:`complex_norm` +~~~~~~~~~~~~~~~~~~~~~~ + +.. autofunction:: complex_norm + +:hidden:`angle` +~~~~~~~~~~~~~~~ + +.. autofunction:: angle + +:hidden:`magphase` +~~~~~~~~~~~~~~~~~~ + +.. autofunction:: magphase + +:hidden:`phase_vocoder` +~~~~~~~~~~~~~~~~~~~~~~~ + +.. autofunction:: phase_vocoder :hidden:`mask_along_axis` ~~~~~~~~~~~~~~~~~~~~~~~~~ @@ -172,8 +193,3 @@ Functions to perform common audio operations. ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ .. autofunction:: sliding_window_cmn - -:hidden:`vad` -~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -.. autofunction:: vad diff --git a/docs/source/torchaudio.rst b/docs/source/torchaudio.rst index f7b826b571..480be4393e 100644 --- a/docs/source/torchaudio.rst +++ b/docs/source/torchaudio.rst @@ -34,10 +34,3 @@ Backend Utilities .. autofunction:: get_audio_backend .. autofunction:: set_audio_backend - -Sox Effects Utilities -~~~~~~~~~~~~~~~~~~~~~ - -.. autofunction:: initialize_sox - -.. autofunction:: shutdown_sox diff --git a/examples/pipeline_wav2letter/main.py b/examples/pipeline_wav2letter/main.py index 8f52ec6c3c..549f3dcdeb 100644 --- a/examples/pipeline_wav2letter/main.py +++ b/examples/pipeline_wav2letter/main.py @@ -83,13 +83,6 @@ def parse_args(): parser.add_argument( "--start-epoch", default=0, type=int, metavar="N", help="manual epoch number" ) - parser.add_argument( - "--print-freq", - default=10, - type=int, - metavar="N", - help="print frequency in epochs", - ) parser.add_argument( "--reduce-lr-valid", action="store_true", @@ -615,37 +608,35 @@ def main(rank, args): not args.reduce_lr_valid, ) - if not (epoch + 1) % args.print_freq or epoch == args.epochs - 1: - - loss = evaluate( - model, - criterion, - loader_validation, - decoder, - language_model, - devices[0], - epoch, - not_main_rank, - ) - - is_best = loss < best_loss - best_loss = min(loss, best_loss) - save_checkpoint( - { - "epoch": epoch + 1, - "state_dict": model.state_dict(), - "best_loss": best_loss, - "optimizer": optimizer.state_dict(), - "scheduler": scheduler.state_dict(), - }, - is_best, - args.checkpoint, - not_main_rank, - ) + loss = evaluate( + model, + criterion, + loader_validation, + decoder, + language_model, + devices[0], + epoch, + not_main_rank, + ) if args.reduce_lr_valid and isinstance(scheduler, ReduceLROnPlateau): scheduler.step(loss) + is_best = loss < best_loss + best_loss = min(loss, best_loss) + save_checkpoint( + { + "epoch": epoch + 1, + "state_dict": model.state_dict(), + "best_loss": best_loss, + "optimizer": optimizer.state_dict(), + "scheduler": scheduler.state_dict(), + }, + is_best, + args.checkpoint, + not_main_rank, + ) + logging.info("End time: %s", datetime.now()) if args.distributed: diff --git a/test/torchaudio_unittest/sox_effect/dataset_test.py b/test/torchaudio_unittest/sox_effect/dataset_test.py index e98095d0dd..647e4d2a81 100644 --- a/test/torchaudio_unittest/sox_effect/dataset_test.py +++ b/test/torchaudio_unittest/sox_effect/dataset_test.py @@ -1,3 +1,6 @@ +import sys +import platform +from unittest import skipIf from typing import List, Tuple import numpy as np @@ -68,6 +71,13 @@ def init_random_seed(worker_id): @skipIfNoExtension +@skipIf( + platform.system() == 'Darwin' and + sys.version_info.major == 3 and + sys.version_info.minor in [6, 7], + 'This test is known to get stuck for macOS with Python < 3.8. ' + 'See https://github.com/pytorch/pytorch/issues/46409' +) class TestSoxEffectsDataset(TempDirMixin, PytorchTestCase): """Test `apply_effects_file` in multi-process dataloader setting""" diff --git a/torchaudio/_internal/fft.py b/torchaudio/_internal/fft.py new file mode 100644 index 0000000000..45350a4972 --- /dev/null +++ b/torchaudio/_internal/fft.py @@ -0,0 +1,27 @@ +"""Compatibility module for fft-related functions + +In PyTorch 1.7, the new `torch.fft` module was introduced. + +To use this new module, one has to explicitly import `torch.fft`. however this will change +the reference `torch.fft` is pointing from function to module. +And this change takes effect not only in the client code but also in already-imported libraries too. +Similarly, if a library does the explicit import, the rest of the application code must use the +`torch.fft.fft` function. + +For this reason, to migrate the deprecated functions of fft-family, we need to use the new +implementation under `torch.fft` without explicitly importing `torch.fft` module. + +This module provides a simple interface for the migration, abstracting away +the access to the underlying C functions. + +Once the deprecated functions are removed from PyTorch and `torch.fft` starts to always represent +the new module, we can get rid of this module and call functions under `torch.fft` directly. +""" +from typing import Optional + +import torch + + +def rfft(input: torch.Tensor, n: Optional[int] = None, dim: int = -1, norm: Optional[str] = None) -> torch.Tensor: + # see: https://pytorch.org/docs/master/fft.html#torch.fft.rfft + return torch._C._fft.fft_rfft(input, n, dim, norm) diff --git a/torchaudio/compliance/kaldi.py b/torchaudio/compliance/kaldi.py index 1160595992..afabebeb6a 100644 --- a/torchaudio/compliance/kaldi.py +++ b/torchaudio/compliance/kaldi.py @@ -2,9 +2,11 @@ import math import torch -import torchaudio from torch import Tensor +import torchaudio +import torchaudio._internal.fft + __all__ = [ 'get_mel_banks', 'inverse_mel_scale', @@ -289,10 +291,10 @@ def spectrogram(waveform: Tensor, snip_edges, raw_energy, energy_floor, dither, remove_dc_offset, preemphasis_coefficient) # size (m, padded_window_size // 2 + 1, 2) - fft = torch.rfft(strided_input, 1, normalized=False, onesided=True) + fft = torchaudio._internal.fft.rfft(strided_input) # Convert the FFT into a power spectrum - power_spectrum = torch.max(fft.pow(2).sum(2), epsilon).log() # size (m, padded_window_size // 2 + 1) + power_spectrum = torch.max(fft.abs().pow(2.), epsilon).log() # size (m, padded_window_size // 2 + 1) power_spectrum[:, 0] = signal_log_energy power_spectrum = _subtract_column_mean(power_spectrum, subtract_mean) @@ -570,12 +572,10 @@ def fbank(waveform: Tensor, waveform, padded_window_size, window_size, window_shift, window_type, blackman_coeff, snip_edges, raw_energy, energy_floor, dither, remove_dc_offset, preemphasis_coefficient) - # size (m, padded_window_size // 2 + 1, 2) - fft = torch.rfft(strided_input, 1, normalized=False, onesided=True) - - power_spectrum = fft.pow(2).sum(2) # size (m, padded_window_size // 2 + 1) - if not use_power: - power_spectrum = power_spectrum.pow(0.5) + # size (m, padded_window_size // 2 + 1) + spectrum = torchaudio._internal.fft.rfft(strided_input).abs() + if use_power: + spectrum = spectrum.pow(2.) # size (num_mel_bins, padded_window_size // 2) mel_energies, _ = get_mel_banks(num_mel_bins, padded_window_size, sample_frequency, @@ -586,7 +586,7 @@ def fbank(waveform: Tensor, mel_energies = torch.nn.functional.pad(mel_energies, (0, 1), mode='constant', value=0) # sum with mel fiterbanks over the power spectrum, size (m, num_mel_bins) - mel_energies = torch.mm(power_spectrum, mel_energies.T) + mel_energies = torch.mm(spectrum, mel_energies.T) if use_log_fbank: # avoid log of zero (which should be prevented anyway by dithering) mel_energies = torch.max(mel_energies, _get_epsilon(device, dtype)).log() diff --git a/torchaudio/functional.py b/torchaudio/functional.py deleted file mode 100644 index d8adfe86e6..0000000000 --- a/torchaudio/functional.py +++ /dev/null @@ -1,2332 +0,0 @@ -# -*- coding: utf-8 -*- - -import math -from typing import Optional, Tuple -import warnings - -import torch -from torch import Tensor - -__all__ = [ - "spectrogram", - "griffinlim", - "amplitude_to_DB", - "create_fb_matrix", - "create_dct", - "mu_law_encoding", - "mu_law_decoding", - "complex_norm", - "angle", - "magphase", - "phase_vocoder", - "lfilter", - "lowpass_biquad", - "highpass_biquad", - "allpass_biquad", - "bandpass_biquad", - "bandreject_biquad", - "equalizer_biquad", - "band_biquad", - "treble_biquad", - "bass_biquad", - "deemph_biquad", - "riaa_biquad", - "biquad", - "contrast", - "dcshift", - "overdrive", - "phaser", - "flanger", - 'mask_along_axis', - 'mask_along_axis_iid', - 'sliding_window_cmn', - 'vad', -] - - -def spectrogram( - waveform: Tensor, - pad: int, - window: Tensor, - n_fft: int, - hop_length: int, - win_length: int, - power: Optional[float], - normalized: bool -) -> Tensor: - r"""Create a spectrogram or a batch of spectrograms from a raw audio signal. - The spectrogram can be either magnitude-only or complex. - - Args: - waveform (Tensor): Tensor of audio of dimension (..., time) - pad (int): Two sided padding of signal - window (Tensor): Window tensor that is applied/multiplied to each frame/window - n_fft (int): Size of FFT - hop_length (int): Length of hop between STFT windows - win_length (int): Window size - power (float or None): Exponent for the magnitude spectrogram, - (must be > 0) e.g., 1 for energy, 2 for power, etc. - If None, then the complex spectrum is returned instead. - normalized (bool): Whether to normalize by magnitude after stft - - Returns: - Tensor: Dimension (..., freq, time), freq is - ``n_fft // 2 + 1`` and ``n_fft`` is the number of - Fourier bins, and time is the number of window hops (n_frame). - """ - - if pad > 0: - # TODO add "with torch.no_grad():" back when JIT supports it - waveform = torch.nn.functional.pad(waveform, (pad, pad), "constant") - - # pack batch - shape = waveform.size() - waveform = waveform.reshape(-1, shape[-1]) - - # default values are consistent with librosa.core.spectrum._spectrogram - spec_f = torch.stft( - waveform, n_fft, hop_length, win_length, window, True, "reflect", False, True - ) - - # unpack batch - spec_f = spec_f.reshape(shape[:-1] + spec_f.shape[-3:]) - - if normalized: - spec_f /= window.pow(2.).sum().sqrt() - if power is not None: - spec_f = complex_norm(spec_f, power=power) - - return spec_f - - -def griffinlim( - specgram: Tensor, - window: Tensor, - n_fft: int, - hop_length: int, - win_length: int, - power: float, - normalized: bool, - n_iter: int, - momentum: float, - length: Optional[int], - rand_init: bool -) -> Tensor: - r"""Compute waveform from a linear scale magnitude spectrogram using the Griffin-Lim transformation. - Implementation ported from `librosa`. - - .. [1] McFee, Brian, Colin Raffel, Dawen Liang, Daniel PW Ellis, Matt McVicar, Eric Battenberg, and Oriol Nieto. - "librosa: Audio and music signal analysis in python." - In Proceedings of the 14th python in science conference, pp. 18-25. 2015. - - .. [2] Perraudin, N., Balazs, P., & Sรธndergaard, P. L. - "A fast Griffin-Lim algorithm," - IEEE Workshop on Applications of Signal Processing to Audio and Acoustics (pp. 1-4), - Oct. 2013. - - .. [3] D. W. Griffin and J. S. Lim, - "Signal estimation from modified short-time Fourier transform," - IEEE Trans. ASSP, vol.32, no.2, pp.236โ€“243, Apr. 1984. - - Args: - specgram (Tensor): A magnitude-only STFT spectrogram of dimension (..., freq, frames) - where freq is ``n_fft // 2 + 1``. - window (Tensor): Window tensor that is applied/multiplied to each frame/window - n_fft (int): Size of FFT, creates ``n_fft // 2 + 1`` bins - hop_length (int): Length of hop between STFT windows. ( - Default: ``win_length // 2``) - win_length (int): Window size. (Default: ``n_fft``) - power (float): Exponent for the magnitude spectrogram, - (must be > 0) e.g., 1 for energy, 2 for power, etc. - normalized (bool): Whether to normalize by magnitude after stft. - n_iter (int): Number of iteration for phase recovery process. - momentum (float): The momentum parameter for fast Griffin-Lim. - Setting this to 0 recovers the original Griffin-Lim method. - Values near 1 can lead to faster convergence, but above 1 may not converge. - length (int or None): Array length of the expected output. - rand_init (bool): Initializes phase randomly if True, to zero otherwise. - - Returns: - torch.Tensor: waveform of (..., time), where time equals the ``length`` parameter if given. - """ - assert momentum < 1, 'momentum={} > 1 can be unstable'.format(momentum) - assert momentum >= 0, 'momentum={} < 0'.format(momentum) - - # pack batch - shape = specgram.size() - specgram = specgram.reshape([-1] + list(shape[-2:])) - - specgram = specgram.pow(1 / power) - - # randomly initialize the phase - batch, freq, frames = specgram.size() - if rand_init: - angles = 2 * math.pi * torch.rand(batch, freq, frames) - else: - angles = torch.zeros(batch, freq, frames) - angles = torch.stack([angles.cos(), angles.sin()], dim=-1) \ - .to(dtype=specgram.dtype, device=specgram.device) - specgram = specgram.unsqueeze(-1).expand_as(angles) - - # And initialize the previous iterate to 0 - rebuilt = torch.tensor(0.) - - for _ in range(n_iter): - # Store the previous iterate - tprev = rebuilt - - # Invert with our current estimate of the phases - inverse = torch.istft(specgram * angles, - n_fft=n_fft, - hop_length=hop_length, - win_length=win_length, - window=window, - length=length).float() - - # Rebuild the spectrogram - rebuilt = torch.stft(inverse, n_fft, hop_length, win_length, window, - True, 'reflect', False, True) - - # Update our phase estimates - angles = rebuilt - if momentum: - angles = angles - tprev.mul_(momentum / (1 + momentum)) - angles = angles.div(complex_norm(angles).add(1e-16).unsqueeze(-1).expand_as(angles)) - - # Return the final phase estimates - waveform = torch.istft(specgram * angles, - n_fft=n_fft, - hop_length=hop_length, - win_length=win_length, - window=window, - length=length) - - # unpack batch - waveform = waveform.reshape(shape[:-2] + waveform.shape[-1:]) - - return waveform - - -def amplitude_to_DB( - x: Tensor, - multiplier: float, - amin: float, - db_multiplier: float, - top_db: Optional[float] = None -) -> Tensor: - r"""Turn a tensor from the power/amplitude scale to the decibel scale. - - This output depends on the maximum value in the input tensor, and so - may return different values for an audio clip split into snippets vs. a - a full clip. - - Args: - x (Tensor): Input tensor before being converted to decibel scale - multiplier (float): Use 10. for power and 20. for amplitude - amin (float): Number to clamp ``x`` - db_multiplier (float): Log10(max(reference value and amin)) - top_db (float or None, optional): Minimum negative cut-off in decibels. A reasonable number - is 80. (Default: ``None``) - - Returns: - Tensor: Output tensor in decibel scale - """ - x_db = multiplier * torch.log10(torch.clamp(x, min=amin)) - x_db -= multiplier * db_multiplier - - if top_db is not None: - x_db = x_db.clamp(min=x_db.max().item() - top_db) - - return x_db - - -def DB_to_amplitude( - x: Tensor, - ref: float, - power: float -) -> Tensor: - r"""Turn a tensor from the decibel scale to the power/amplitude scale. - - Args: - x (Tensor): Input tensor before being converted to power/amplitude scale. - ref (float): Reference which the output will be scaled by. - power (float): If power equals 1, will compute DB to power. If 0.5, will compute DB to amplitude. - - Returns: - Tensor: Output tensor in power/amplitude scale. - """ - return ref * torch.pow(torch.pow(10.0, 0.1 * x), power) - - -def create_fb_matrix( - n_freqs: int, - f_min: float, - f_max: float, - n_mels: int, - sample_rate: int, - norm: Optional[str] = None -) -> Tensor: - r"""Create a frequency bin conversion matrix. - - Args: - n_freqs (int): Number of frequencies to highlight/apply - f_min (float): Minimum frequency (Hz) - f_max (float): Maximum frequency (Hz) - n_mels (int): Number of mel filterbanks - sample_rate (int): Sample rate of the audio waveform - norm (Optional[str]): If 'slaney', divide the triangular mel weights by the width of the mel band - (area normalization). (Default: ``None``) - - Returns: - Tensor: Triangular filter banks (fb matrix) of size (``n_freqs``, ``n_mels``) - meaning number of frequencies to highlight/apply to x the number of filterbanks. - Each column is a filterbank so that assuming there is a matrix A of - size (..., ``n_freqs``), the applied result would be - ``A * create_fb_matrix(A.size(-1), ...)``. - """ - - if norm is not None and norm != "slaney": - raise ValueError("norm must be one of None or 'slaney'") - - # freq bins - # Equivalent filterbank construction by Librosa - all_freqs = torch.linspace(0, sample_rate // 2, n_freqs) - - # calculate mel freq bins - # hertz to mel(f) is 2595. * math.log10(1. + (f / 700.)) - m_min = 2595.0 * math.log10(1.0 + (f_min / 700.0)) - m_max = 2595.0 * math.log10(1.0 + (f_max / 700.0)) - m_pts = torch.linspace(m_min, m_max, n_mels + 2) - # mel to hertz(mel) is 700. * (10**(mel / 2595.) - 1.) - f_pts = 700.0 * (10 ** (m_pts / 2595.0) - 1.0) - # calculate the difference between each mel point and each stft freq point in hertz - f_diff = f_pts[1:] - f_pts[:-1] # (n_mels + 1) - slopes = f_pts.unsqueeze(0) - all_freqs.unsqueeze(1) # (n_freqs, n_mels + 2) - # create overlapping triangles - zero = torch.zeros(1) - down_slopes = (-1.0 * slopes[:, :-2]) / f_diff[:-1] # (n_freqs, n_mels) - up_slopes = slopes[:, 2:] / f_diff[1:] # (n_freqs, n_mels) - fb = torch.max(zero, torch.min(down_slopes, up_slopes)) - - if norm is not None and norm == "slaney": - # Slaney-style mel is scaled to be approx constant energy per channel - enorm = 2.0 / (f_pts[2:n_mels + 2] - f_pts[:n_mels]) - fb *= enorm.unsqueeze(0) - - if (fb.max(dim=0).values == 0.).any(): - warnings.warn( - "At least one mel filterbank has all zero values. " - f"The value for `n_mels` ({n_mels}) may be set too high. " - f"Or, the value for `n_freqs` ({n_freqs}) may be set too low." - ) - - return fb - - -def create_dct( - n_mfcc: int, - n_mels: int, - norm: Optional[str] -) -> Tensor: - r"""Create a DCT transformation matrix with shape (``n_mels``, ``n_mfcc``), - normalized depending on norm. - - Args: - n_mfcc (int): Number of mfc coefficients to retain - n_mels (int): Number of mel filterbanks - norm (str or None): Norm to use (either 'ortho' or None) - - Returns: - Tensor: The transformation matrix, to be right-multiplied to - row-wise data of size (``n_mels``, ``n_mfcc``). - """ - # http://en.wikipedia.org/wiki/Discrete_cosine_transform#DCT-II - n = torch.arange(float(n_mels)) - k = torch.arange(float(n_mfcc)).unsqueeze(1) - dct = torch.cos(math.pi / float(n_mels) * (n + 0.5) * k) # size (n_mfcc, n_mels) - if norm is None: - dct *= 2.0 - else: - assert norm == "ortho" - dct[0] *= 1.0 / math.sqrt(2.0) - dct *= math.sqrt(2.0 / float(n_mels)) - return dct.t() - - -def mu_law_encoding( - x: Tensor, - quantization_channels: int -) -> Tensor: - r"""Encode signal based on mu-law companding. For more info see the - `Wikipedia Entry `_ - - This algorithm assumes the signal has been scaled to between -1 and 1 and - returns a signal encoded with values from 0 to quantization_channels - 1. - - Args: - x (Tensor): Input tensor - quantization_channels (int): Number of channels - - Returns: - Tensor: Input after mu-law encoding - """ - mu = quantization_channels - 1.0 - if not x.is_floating_point(): - x = x.to(torch.float) - mu = torch.tensor(mu, dtype=x.dtype) - x_mu = torch.sign(x) * torch.log1p(mu * torch.abs(x)) / torch.log1p(mu) - x_mu = ((x_mu + 1) / 2 * mu + 0.5).to(torch.int64) - return x_mu - - -def mu_law_decoding( - x_mu: Tensor, - quantization_channels: int -) -> Tensor: - r"""Decode mu-law encoded signal. For more info see the - `Wikipedia Entry `_ - - This expects an input with values between 0 and quantization_channels - 1 - and returns a signal scaled between -1 and 1. - - Args: - x_mu (Tensor): Input tensor - quantization_channels (int): Number of channels - - Returns: - Tensor: Input after mu-law decoding - """ - mu = quantization_channels - 1.0 - if not x_mu.is_floating_point(): - x_mu = x_mu.to(torch.float) - mu = torch.tensor(mu, dtype=x_mu.dtype) - x = ((x_mu) / mu) * 2 - 1.0 - x = torch.sign(x) * (torch.exp(torch.abs(x) * torch.log1p(mu)) - 1.0) / mu - return x - - -def complex_norm( - complex_tensor: Tensor, - power: float = 1.0 -) -> Tensor: - r"""Compute the norm of complex tensor input. - - Args: - complex_tensor (Tensor): Tensor shape of `(..., complex=2)` - power (float): Power of the norm. (Default: `1.0`). - - Returns: - Tensor: Power of the normed input tensor. Shape of `(..., )` - """ - - # Replace by torch.norm once issue is fixed - # https://github.com/pytorch/pytorch/issues/34279 - return complex_tensor.pow(2.).sum(-1).pow(0.5 * power) - - -def angle( - complex_tensor: Tensor -) -> Tensor: - r"""Compute the angle of complex tensor input. - - Args: - complex_tensor (Tensor): Tensor shape of `(..., complex=2)` - - Return: - Tensor: Angle of a complex tensor. Shape of `(..., )` - """ - return torch.atan2(complex_tensor[..., 1], complex_tensor[..., 0]) - - -def magphase( - complex_tensor: Tensor, - power: float = 1.0 -) -> Tuple[Tensor, Tensor]: - r"""Separate a complex-valued spectrogram with shape `(..., 2)` into its magnitude and phase. - - Args: - complex_tensor (Tensor): Tensor shape of `(..., complex=2)` - power (float): Power of the norm. (Default: `1.0`) - - Returns: - (Tensor, Tensor): The magnitude and phase of the complex tensor - """ - mag = complex_norm(complex_tensor, power) - phase = angle(complex_tensor) - return mag, phase - - -def phase_vocoder( - complex_specgrams: Tensor, - rate: float, - phase_advance: Tensor -) -> Tensor: - r"""Given a STFT tensor, speed up in time without modifying pitch by a - factor of ``rate``. - - Args: - complex_specgrams (Tensor): Dimension of `(..., freq, time, complex=2)` - rate (float): Speed-up factor - phase_advance (Tensor): Expected phase advance in each bin. Dimension of (freq, 1) - - Returns: - Tensor: Complex Specgrams Stretch with dimension of `(..., freq, ceil(time/rate), complex=2)` - - Example - >>> freq, hop_length = 1025, 512 - >>> # (channel, freq, time, complex=2) - >>> complex_specgrams = torch.randn(2, freq, 300, 2) - >>> rate = 1.3 # Speed up by 30% - >>> phase_advance = torch.linspace( - >>> 0, math.pi * hop_length, freq)[..., None] - >>> x = phase_vocoder(complex_specgrams, rate, phase_advance) - >>> x.shape # with 231 == ceil(300 / 1.3) - torch.Size([2, 1025, 231, 2]) - """ - - # pack batch - shape = complex_specgrams.size() - complex_specgrams = complex_specgrams.reshape([-1] + list(shape[-3:])) - - time_steps = torch.arange(0, - complex_specgrams.size(-2), - rate, - device=complex_specgrams.device, - dtype=complex_specgrams.dtype) - - alphas = time_steps % 1.0 - phase_0 = angle(complex_specgrams[..., :1, :]) - - # Time Padding - complex_specgrams = torch.nn.functional.pad(complex_specgrams, [0, 0, 0, 2]) - - # (new_bins, freq, 2) - complex_specgrams_0 = complex_specgrams.index_select(-2, time_steps.long()) - complex_specgrams_1 = complex_specgrams.index_select(-2, (time_steps + 1).long()) - - angle_0 = angle(complex_specgrams_0) - angle_1 = angle(complex_specgrams_1) - - norm_0 = torch.norm(complex_specgrams_0, p=2, dim=-1) - norm_1 = torch.norm(complex_specgrams_1, p=2, dim=-1) - - phase = angle_1 - angle_0 - phase_advance - phase = phase - 2 * math.pi * torch.round(phase / (2 * math.pi)) - - # Compute Phase Accum - phase = phase + phase_advance - phase = torch.cat([phase_0, phase[..., :-1]], dim=-1) - phase_acc = torch.cumsum(phase, -1) - - mag = alphas * norm_1 + (1 - alphas) * norm_0 - - real_stretch = mag * torch.cos(phase_acc) - imag_stretch = mag * torch.sin(phase_acc) - - complex_specgrams_stretch = torch.stack([real_stretch, imag_stretch], dim=-1) - - # unpack batch - complex_specgrams_stretch = complex_specgrams_stretch.reshape(shape[:-3] + complex_specgrams_stretch.shape[1:]) - - return complex_specgrams_stretch - - -def lfilter( - waveform: Tensor, - a_coeffs: Tensor, - b_coeffs: Tensor, - clamp: bool = True, -) -> Tensor: - r"""Perform an IIR filter by evaluating difference equation. - - Args: - waveform (Tensor): audio waveform of dimension of ``(..., time)``. Must be normalized to -1 to 1. - a_coeffs (Tensor): denominator coefficients of difference equation of dimension of ``(n_order + 1)``. - Lower delays coefficients are first, e.g. ``[a0, a1, a2, ...]``. - Must be same size as b_coeffs (pad with 0's as necessary). - b_coeffs (Tensor): numerator coefficients of difference equation of dimension of ``(n_order + 1)``. - Lower delays coefficients are first, e.g. ``[b0, b1, b2, ...]``. - Must be same size as a_coeffs (pad with 0's as necessary). - clamp (bool, optional): If ``True``, clamp the output signal to be in the range [-1, 1] (Default: ``True``) - - Returns: - Tensor: Waveform with dimension of ``(..., time)``. - """ - # pack batch - shape = waveform.size() - waveform = waveform.reshape(-1, shape[-1]) - - assert (a_coeffs.size(0) == b_coeffs.size(0)) - assert (len(waveform.size()) == 2) - assert (waveform.device == a_coeffs.device) - assert (b_coeffs.device == a_coeffs.device) - - device = waveform.device - dtype = waveform.dtype - n_channel, n_sample = waveform.size() - n_order = a_coeffs.size(0) - n_sample_padded = n_sample + n_order - 1 - assert (n_order > 0) - - # Pad the input and create output - padded_waveform = torch.zeros(n_channel, n_sample_padded, dtype=dtype, device=device) - padded_waveform[:, (n_order - 1):] = waveform - padded_output_waveform = torch.zeros(n_channel, n_sample_padded, dtype=dtype, device=device) - - # Set up the coefficients matrix - # Flip coefficients' order - a_coeffs_flipped = a_coeffs.flip(0) - b_coeffs_flipped = b_coeffs.flip(0) - - # calculate windowed_input_signal in parallel - # create indices of original with shape (n_channel, n_order, n_sample) - window_idxs = torch.arange(n_sample, device=device).unsqueeze(0) + torch.arange(n_order, device=device).unsqueeze(1) - window_idxs = window_idxs.repeat(n_channel, 1, 1) - window_idxs += (torch.arange(n_channel, device=device).unsqueeze(-1).unsqueeze(-1) * n_sample_padded) - window_idxs = window_idxs.long() - # (n_order, ) matmul (n_channel, n_order, n_sample) -> (n_channel, n_sample) - input_signal_windows = torch.matmul(b_coeffs_flipped, torch.take(padded_waveform, window_idxs)) - - input_signal_windows.div_(a_coeffs[0]) - a_coeffs_flipped.div_(a_coeffs[0]) - for i_sample, o0 in enumerate(input_signal_windows.t()): - windowed_output_signal = padded_output_waveform[:, i_sample:(i_sample + n_order)] - o0.addmv_(windowed_output_signal, a_coeffs_flipped, alpha=-1) - padded_output_waveform[:, i_sample + n_order - 1] = o0 - - output = padded_output_waveform[:, (n_order - 1):] - - if clamp: - output = torch.clamp(output, min=-1., max=1.) - - # unpack batch - output = output.reshape(shape[:-1] + output.shape[-1:]) - - return output - - -def biquad( - waveform: Tensor, - b0: float, - b1: float, - b2: float, - a0: float, - a1: float, - a2: float -) -> Tensor: - r"""Perform a biquad filter of input tensor. Initial conditions set to 0. - https://en.wikipedia.org/wiki/Digital_biquad_filter - - Args: - waveform (Tensor): audio waveform of dimension of `(..., time)` - b0 (float): numerator coefficient of current input, x[n] - b1 (float): numerator coefficient of input one time step ago x[n-1] - b2 (float): numerator coefficient of input two time steps ago x[n-2] - a0 (float): denominator coefficient of current output y[n], typically 1 - a1 (float): denominator coefficient of current output y[n-1] - a2 (float): denominator coefficient of current output y[n-2] - - Returns: - Tensor: Waveform with dimension of `(..., time)` - """ - - device = waveform.device - dtype = waveform.dtype - - output_waveform = lfilter( - waveform, - torch.tensor([a0, a1, a2], dtype=dtype, device=device), - torch.tensor([b0, b1, b2], dtype=dtype, device=device) - ) - return output_waveform - - -def _dB2Linear(x: float) -> float: - return math.exp(x * math.log(10) / 20.0) - - -def highpass_biquad( - waveform: Tensor, - sample_rate: int, - cutoff_freq: float, - Q: float = 0.707 -) -> Tensor: - r"""Design biquad highpass filter and perform filtering. Similar to SoX implementation. - - Args: - waveform (Tensor): audio waveform of dimension of `(..., time)` - sample_rate (int): sampling rate of the waveform, e.g. 44100 (Hz) - cutoff_freq (float): filter cutoff frequency - Q (float, optional): https://en.wikipedia.org/wiki/Q_factor (Default: ``0.707``) - - Returns: - Tensor: Waveform dimension of `(..., time)` - """ - w0 = 2 * math.pi * cutoff_freq / sample_rate - alpha = math.sin(w0) / 2. / Q - - b0 = (1 + math.cos(w0)) / 2 - b1 = -1 - math.cos(w0) - b2 = b0 - a0 = 1 + alpha - a1 = -2 * math.cos(w0) - a2 = 1 - alpha - return biquad(waveform, b0, b1, b2, a0, a1, a2) - - -def lowpass_biquad( - waveform: Tensor, - sample_rate: int, - cutoff_freq: float, - Q: float = 0.707 -) -> Tensor: - r"""Design biquad lowpass filter and perform filtering. Similar to SoX implementation. - - Args: - waveform (torch.Tensor): audio waveform of dimension of `(..., time)` - sample_rate (int): sampling rate of the waveform, e.g. 44100 (Hz) - cutoff_freq (float): filter cutoff frequency - Q (float, optional): https://en.wikipedia.org/wiki/Q_factor (Default: ``0.707``) - - Returns: - Tensor: Waveform of dimension of `(..., time)` - """ - w0 = 2 * math.pi * cutoff_freq / sample_rate - alpha = math.sin(w0) / 2 / Q - - b0 = (1 - math.cos(w0)) / 2 - b1 = 1 - math.cos(w0) - b2 = b0 - a0 = 1 + alpha - a1 = -2 * math.cos(w0) - a2 = 1 - alpha - return biquad(waveform, b0, b1, b2, a0, a1, a2) - - -def allpass_biquad( - waveform: Tensor, - sample_rate: int, - central_freq: float, - Q: float = 0.707 -) -> Tensor: - r"""Design two-pole all-pass filter. Similar to SoX implementation. - - Args: - waveform(torch.Tensor): audio waveform of dimension of `(..., time)` - sample_rate (int): sampling rate of the waveform, e.g. 44100 (Hz) - central_freq (float): central frequency (in Hz) - Q (float, optional): https://en.wikipedia.org/wiki/Q_factor (Default: ``0.707``) - - Returns: - Tensor: Waveform of dimension of `(..., time)` - - References: - http://sox.sourceforge.net/sox.html - https://www.w3.org/2011/audio/audio-eq-cookbook.html#APF - """ - w0 = 2 * math.pi * central_freq / sample_rate - alpha = math.sin(w0) / 2 / Q - - b0 = 1 - alpha - b1 = -2 * math.cos(w0) - b2 = 1 + alpha - a0 = 1 + alpha - a1 = -2 * math.cos(w0) - a2 = 1 - alpha - return biquad(waveform, b0, b1, b2, a0, a1, a2) - - -def bandpass_biquad( - waveform: Tensor, - sample_rate: int, - central_freq: float, - Q: float = 0.707, - const_skirt_gain: bool = False -) -> Tensor: - r"""Design two-pole band-pass filter. Similar to SoX implementation. - - Args: - waveform (Tensor): audio waveform of dimension of `(..., time)` - sample_rate (int): sampling rate of the waveform, e.g. 44100 (Hz) - central_freq (float): central frequency (in Hz) - Q (float, optional): https://en.wikipedia.org/wiki/Q_factor (Default: ``0.707``) - const_skirt_gain (bool, optional) : If ``True``, uses a constant skirt gain (peak gain = Q). - If ``False``, uses a constant 0dB peak gain. (Default: ``False``) - - Returns: - Tensor: Waveform of dimension of `(..., time)` - - References: - http://sox.sourceforge.net/sox.html - https://www.w3.org/2011/audio/audio-eq-cookbook.html#APF - """ - w0 = 2 * math.pi * central_freq / sample_rate - alpha = math.sin(w0) / 2 / Q - - temp = math.sin(w0) / 2 if const_skirt_gain else alpha - b0 = temp - b1 = 0. - b2 = -temp - a0 = 1 + alpha - a1 = -2 * math.cos(w0) - a2 = 1 - alpha - return biquad(waveform, b0, b1, b2, a0, a1, a2) - - -def bandreject_biquad( - waveform: Tensor, - sample_rate: int, - central_freq: float, - Q: float = 0.707 -) -> Tensor: - r"""Design two-pole band-reject filter. Similar to SoX implementation. - - Args: - waveform (Tensor): audio waveform of dimension of `(..., time)` - sample_rate (int): sampling rate of the waveform, e.g. 44100 (Hz) - central_freq (float): central frequency (in Hz) - Q (float, optional): https://en.wikipedia.org/wiki/Q_factor (Default: ``0.707``) - - Returns: - Tensor: Waveform of dimension of `(..., time)` - - References: - http://sox.sourceforge.net/sox.html - https://www.w3.org/2011/audio/audio-eq-cookbook.html#APF - """ - w0 = 2 * math.pi * central_freq / sample_rate - alpha = math.sin(w0) / 2 / Q - - b0 = 1. - b1 = -2 * math.cos(w0) - b2 = 1. - a0 = 1 + alpha - a1 = -2 * math.cos(w0) - a2 = 1 - alpha - return biquad(waveform, b0, b1, b2, a0, a1, a2) - - -def equalizer_biquad( - waveform: Tensor, - sample_rate: int, - center_freq: float, - gain: float, - Q: float = 0.707 -) -> Tensor: - r"""Design biquad peaking equalizer filter and perform filtering. Similar to SoX implementation. - - Args: - waveform (Tensor): audio waveform of dimension of `(..., time)` - sample_rate (int): sampling rate of the waveform, e.g. 44100 (Hz) - center_freq (float): filter's central frequency - gain (float): desired gain at the boost (or attenuation) in dB - Q (float, optional): https://en.wikipedia.org/wiki/Q_factor (Default: ``0.707``) - - Returns: - Tensor: Waveform of dimension of `(..., time)` - """ - w0 = 2 * math.pi * center_freq / sample_rate - A = math.exp(gain / 40.0 * math.log(10)) - alpha = math.sin(w0) / 2 / Q - - b0 = 1 + alpha * A - b1 = -2 * math.cos(w0) - b2 = 1 - alpha * A - a0 = 1 + alpha / A - a1 = -2 * math.cos(w0) - a2 = 1 - alpha / A - return biquad(waveform, b0, b1, b2, a0, a1, a2) - - -def band_biquad( - waveform: Tensor, - sample_rate: int, - central_freq: float, - Q: float = 0.707, - noise: bool = False -) -> Tensor: - r"""Design two-pole band filter. Similar to SoX implementation. - - Args: - waveform (Tensor): audio waveform of dimension of `(..., time)` - sample_rate (int): sampling rate of the waveform, e.g. 44100 (Hz) - central_freq (float): central frequency (in Hz) - Q (float, optional): https://en.wikipedia.org/wiki/Q_factor (Default: ``0.707``). - noise (bool, optional) : If ``True``, uses the alternate mode for un-pitched audio (e.g. percussion). - If ``False``, uses mode oriented to pitched audio, i.e. voice, singing, - or instrumental music (Default: ``False``). - - Returns: - Tensor: Waveform of dimension of `(..., time)` - - References: - http://sox.sourceforge.net/sox.html - https://www.w3.org/2011/audio/audio-eq-cookbook.html#APF - """ - w0 = 2 * math.pi * central_freq / sample_rate - bw_Hz = central_freq / Q - - a0 = 1. - a2 = math.exp(-2 * math.pi * bw_Hz / sample_rate) - a1 = -4 * a2 / (1 + a2) * math.cos(w0) - - b0 = math.sqrt(1 - a1 * a1 / (4 * a2)) * (1 - a2) - - if noise: - mult = math.sqrt(((1 + a2) * (1 + a2) - a1 * a1) * (1 - a2) / (1 + a2)) / b0 - b0 *= mult - - b1 = 0. - b2 = 0. - - return biquad(waveform, b0, b1, b2, a0, a1, a2) - - -def treble_biquad( - waveform: Tensor, - sample_rate: int, - gain: float, - central_freq: float = 3000, - Q: float = 0.707 -) -> Tensor: - r"""Design a treble tone-control effect. Similar to SoX implementation. - - Args: - waveform (Tensor): audio waveform of dimension of `(..., time)` - sample_rate (int): sampling rate of the waveform, e.g. 44100 (Hz) - gain (float): desired gain at the boost (or attenuation) in dB. - central_freq (float, optional): central frequency (in Hz). (Default: ``3000``) - Q (float, optional): https://en.wikipedia.org/wiki/Q_factor (Default: ``0.707``). - - Returns: - Tensor: Waveform of dimension of `(..., time)` - - References: - http://sox.sourceforge.net/sox.html - https://www.w3.org/2011/audio/audio-eq-cookbook.html#APF - """ - w0 = 2 * math.pi * central_freq / sample_rate - alpha = math.sin(w0) / 2 / Q - A = math.exp(gain / 40 * math.log(10)) - - temp1 = 2 * math.sqrt(A) * alpha - temp2 = (A - 1) * math.cos(w0) - temp3 = (A + 1) * math.cos(w0) - - b0 = A * ((A + 1) + temp2 + temp1) - b1 = -2 * A * ((A - 1) + temp3) - b2 = A * ((A + 1) + temp2 - temp1) - a0 = (A + 1) - temp2 + temp1 - a1 = 2 * ((A - 1) - temp3) - a2 = (A + 1) - temp2 - temp1 - - return biquad(waveform, b0, b1, b2, a0, a1, a2) - - -def bass_biquad( - waveform: Tensor, - sample_rate: int, - gain: float, - central_freq: float = 100, - Q: float = 0.707 -) -> Tensor: - r"""Design a bass tone-control effect. Similar to SoX implementation. - - Args: - waveform (Tensor): audio waveform of dimension of `(..., time)` - sample_rate (int): sampling rate of the waveform, e.g. 44100 (Hz) - gain (float): desired gain at the boost (or attenuation) in dB. - central_freq (float, optional): central frequency (in Hz). (Default: ``100``) - Q (float, optional): https://en.wikipedia.org/wiki/Q_factor (Default: ``0.707``). - - Returns: - Tensor: Waveform of dimension of `(..., time)` - - References: - http://sox.sourceforge.net/sox.html - https://www.w3.org/2011/audio/audio-eq-cookbook.html#APF - """ - w0 = 2 * math.pi * central_freq / sample_rate - alpha = math.sin(w0) / 2 / Q - A = math.exp(gain / 40 * math.log(10)) - - temp1 = 2 * math.sqrt(A) * alpha - temp2 = (A - 1) * math.cos(w0) - temp3 = (A + 1) * math.cos(w0) - - b0 = A * ((A + 1) - temp2 + temp1) - b1 = 2 * A * ((A - 1) - temp3) - b2 = A * ((A + 1) - temp2 - temp1) - a0 = (A + 1) + temp2 + temp1 - a1 = -2 * ((A - 1) + temp3) - a2 = (A + 1) + temp2 - temp1 - - return biquad(waveform, b0 / a0, b1 / a0, b2 / a0, a0 / a0, a1 / a0, a2 / a0) - - -def deemph_biquad( - waveform: Tensor, - sample_rate: int -) -> Tensor: - r"""Apply ISO 908 CD de-emphasis (shelving) IIR filter. Similar to SoX implementation. - - Args: - waveform (Tensor): audio waveform of dimension of `(..., time)` - sample_rate (int): sampling rate of the waveform, Allowed sample rate ``44100`` or ``48000`` - - Returns: - Tensor: Waveform of dimension of `(..., time)` - - References: - http://sox.sourceforge.net/sox.html - https://www.w3.org/2011/audio/audio-eq-cookbook.html#APF - """ - - if sample_rate == 44100: - central_freq = 5283 - width_slope = 0.4845 - gain = -9.477 - elif sample_rate == 48000: - central_freq = 5356 - width_slope = 0.479 - gain = -9.62 - else: - raise ValueError("Sample rate must be 44100 (audio-CD) or 48000 (DAT)") - - w0 = 2 * math.pi * central_freq / sample_rate - A = math.exp(gain / 40.0 * math.log(10)) - alpha = math.sin(w0) / 2 * math.sqrt((A + 1 / A) * (1 / width_slope - 1) + 2) - - temp1 = 2 * math.sqrt(A) * alpha - temp2 = (A - 1) * math.cos(w0) - temp3 = (A + 1) * math.cos(w0) - - b0 = A * ((A + 1) + temp2 + temp1) - b1 = -2 * A * ((A - 1) + temp3) - b2 = A * ((A + 1) + temp2 - temp1) - a0 = (A + 1) - temp2 + temp1 - a1 = 2 * ((A - 1) - temp3) - a2 = (A + 1) - temp2 - temp1 - - return biquad(waveform, b0, b1, b2, a0, a1, a2) - - -def riaa_biquad( - waveform: Tensor, - sample_rate: int -) -> Tensor: - r"""Apply RIAA vinyl playback equalisation. Similar to SoX implementation. - - Args: - waveform (Tensor): audio waveform of dimension of `(..., time)` - sample_rate (int): sampling rate of the waveform, e.g. 44100 (Hz). - Allowed sample rates in Hz : ``44100``,``48000``,``88200``,``96000`` - - Returns: - Tensor: Waveform of dimension of `(..., time)` - - References: - http://sox.sourceforge.net/sox.html - https://www.w3.org/2011/audio/audio-eq-cookbook.html#APF - """ - - if (sample_rate == 44100): - zeros = [-0.2014898, 0.9233820] - poles = [0.7083149, 0.9924091] - - elif (sample_rate == 48000): - zeros = [-0.1766069, 0.9321590] - poles = [0.7396325, 0.9931330] - - elif (sample_rate == 88200): - zeros = [-0.1168735, 0.9648312] - poles = [0.8590646, 0.9964002] - - elif (sample_rate == 96000): - zeros = [-0.1141486, 0.9676817] - poles = [0.8699137, 0.9966946] - - else: - raise ValueError("Sample rate must be 44.1k, 48k, 88.2k, or 96k") - - # polynomial coefficients with roots zeros[0] and zeros[1] - b0 = 1. - b1 = -(zeros[0] + zeros[1]) - b2 = (zeros[0] * zeros[1]) - - # polynomial coefficients with roots poles[0] and poles[1] - a0 = 1. - a1 = -(poles[0] + poles[1]) - a2 = (poles[0] * poles[1]) - - # Normalise to 0dB at 1kHz - y = 2 * math.pi * 1000 / sample_rate - b_re = b0 + b1 * math.cos(-y) + b2 * math.cos(-2 * y) - a_re = a0 + a1 * math.cos(-y) + a2 * math.cos(-2 * y) - b_im = b1 * math.sin(-y) + b2 * math.sin(-2 * y) - a_im = a1 * math.sin(-y) + a2 * math.sin(-2 * y) - g = 1 / math.sqrt((b_re ** 2 + b_im ** 2) / (a_re ** 2 + a_im ** 2)) - - b0 *= g - b1 *= g - b2 *= g - - return biquad(waveform, b0, b1, b2, a0, a1, a2) - - -def contrast( - waveform: Tensor, - enhancement_amount: float = 75. -) -> Tensor: - r"""Apply contrast effect. Similar to SoX implementation. - Comparable with compression, this effect modifies an audio signal to make it sound louder - - Args: - waveform (Tensor): audio waveform of dimension of `(..., time)` - enhancement_amount (float): controls the amount of the enhancement - Allowed range of values for enhancement_amount : 0-100 - Note that enhancement_amount = 0 still gives a significant contrast enhancement - - Returns: - Tensor: Waveform of dimension of `(..., time)` - - References: - http://sox.sourceforge.net/sox.html - """ - - if not 0 <= enhancement_amount <= 100: - raise ValueError("Allowed range of values for enhancement_amount : 0-100") - - contrast = enhancement_amount / 750. - - temp1 = waveform * (math.pi / 2) - temp2 = contrast * torch.sin(temp1 * 4) - output_waveform = torch.sin(temp1 + temp2) - - return output_waveform - - -def dcshift( - waveform: Tensor, - shift: float, - limiter_gain: Optional[float] = None -) -> Tensor: - r"""Apply a DC shift to the audio. Similar to SoX implementation. - This can be useful to remove a DC offset - (caused perhaps by a hardware problem in the recording chain) from the audio - - Args: - waveform (Tensor): audio waveform of dimension of `(..., time)` - shift (float): indicates the amount to shift the audio - Allowed range of values for shift : -2.0 to +2.0 - limiter_gain (float): It is used only on peaks to prevent clipping - It should have a value much less than 1 (e.g. 0.05 or 0.02) - - Returns: - Tensor: Waveform of dimension of `(..., time)` - - References: - http://sox.sourceforge.net/sox.html - """ - output_waveform = waveform - limiter_threshold = 0. - - if limiter_gain is not None: - limiter_threshold = 1.0 - (abs(shift) - limiter_gain) - - if limiter_gain is not None and shift > 0: - mask = waveform > limiter_threshold - temp = (waveform[mask] - limiter_threshold) * limiter_gain / (1 - limiter_threshold) - output_waveform[mask] = (temp + limiter_threshold + shift).clamp(max=limiter_threshold) - output_waveform[~mask] = (waveform[~mask] + shift).clamp(min=-1, max=1) - elif limiter_gain is not None and shift < 0: - mask = waveform < -limiter_threshold - temp = (waveform[mask] + limiter_threshold) * limiter_gain / (1 - limiter_threshold) - output_waveform[mask] = (temp - limiter_threshold + shift).clamp(min=-limiter_threshold) - output_waveform[~mask] = (waveform[~mask] + shift).clamp(min=-1, max=1) - else: - output_waveform = (waveform + shift).clamp(min=-1, max=1) - - return output_waveform - - -def overdrive( - waveform: Tensor, - gain: float = 20, - colour: float = 20 -) -> Tensor: - r"""Apply a overdrive effect to the audio. Similar to SoX implementation. - This effect applies a non linear distortion to the audio signal. - - Args: - waveform (Tensor): audio waveform of dimension of `(..., time)` - gain (float): desired gain at the boost (or attenuation) in dB - Allowed range of values are 0 to 100 - colour (float): controls the amount of even harmonic content in the over-driven output - Allowed range of values are 0 to 100 - - Returns: - Tensor: Waveform of dimension of `(..., time)` - - References: - http://sox.sourceforge.net/sox.html - """ - actual_shape = waveform.shape - device, dtype = waveform.device, waveform.dtype - - # convert to 2D (..,time) - waveform = waveform.view(-1, actual_shape[-1]) - - gain = _dB2Linear(gain) - colour = colour / 200 - last_in = torch.zeros(waveform.shape[:-1], dtype=dtype, device=device) - last_out = torch.zeros(waveform.shape[:-1], dtype=dtype, device=device) - - temp = waveform * gain + colour - - mask1 = temp < -1 - temp[mask1] = torch.tensor(-2.0 / 3.0, dtype=dtype, device=device) - # Wrapping the constant with Tensor is required for Torchscript - - mask2 = temp > 1 - temp[mask2] = torch.tensor(2.0 / 3.0, dtype=dtype, device=device) - - mask3 = (~mask1 & ~mask2) - temp[mask3] = temp[mask3] - (temp[mask3]**3) * (1. / 3) - - output_waveform = torch.zeros_like(waveform, dtype=dtype, device=device) - - # TODO: Implement a torch CPP extension - for i in range(waveform.shape[-1]): - last_out = temp[:, i] - last_in + 0.995 * last_out - last_in = temp[:, i] - output_waveform[:, i] = waveform[:, i] * 0.5 + last_out * 0.75 - - return output_waveform.clamp(min=-1, max=1).view(actual_shape) - - -def phaser( - waveform: Tensor, - sample_rate: int, - gain_in: float = 0.4, - gain_out: float = 0.74, - delay_ms: float = 3.0, - decay: float = 0.4, - mod_speed: float = 0.5, - sinusoidal: bool = True -) -> Tensor: - r"""Apply a phasing effect to the audio. Similar to SoX implementation. - - Args: - waveform (Tensor): audio waveform of dimension of `(..., time)` - sample_rate (int): sampling rate of the waveform, e.g. 44100 (Hz) - gain_in (float): desired input gain at the boost (or attenuation) in dB - Allowed range of values are 0 to 1 - gain_out (float): desired output gain at the boost (or attenuation) in dB - Allowed range of values are 0 to 1e9 - delay_ms (float): desired delay in milli seconds - Allowed range of values are 0 to 5.0 - decay (float): desired decay relative to gain-in - Allowed range of values are 0 to 0.99 - mod_speed (float): modulation speed in Hz - Allowed range of values are 0.1 to 2 - sinusoidal (bool): If ``True``, uses sinusoidal modulation (preferable for multiple instruments) - If ``False``, uses triangular modulation (gives single instruments a sharper phasing effect) - (Default: ``True``) - - Returns: - Tensor: Waveform of dimension of `(..., time)` - - References: - http://sox.sourceforge.net/sox.html - Scott Lehman, Effects Explained, http://harmony-central.com/Effects/effects-explained.html - """ - actual_shape = waveform.shape - device, dtype = waveform.device, waveform.dtype - - # convert to 2D (channels,time) - waveform = waveform.view(-1, actual_shape[-1]) - - delay_buf_len = int((delay_ms * .001 * sample_rate) + .5) - delay_buf = torch.zeros(waveform.shape[0], delay_buf_len, dtype=dtype, device=device) - - mod_buf_len = int(sample_rate / mod_speed + .5) - - if sinusoidal: - wave_type = 'SINE' - else: - wave_type = 'TRIANGLE' - - mod_buf = _generate_wave_table(wave_type=wave_type, - data_type='INT', - table_size=mod_buf_len, - min=1., - max=float(delay_buf_len), - phase=math.pi / 2, - device=device) - - delay_pos = 0 - mod_pos = 0 - - output_waveform_pre_gain_list = [] - waveform = waveform * gain_in - delay_buf = delay_buf * decay - waveform_list = [waveform[:, i] for i in range(waveform.size(1))] - delay_buf_list = [delay_buf[:, i] for i in range(delay_buf.size(1))] - mod_buf_list = [mod_buf[i] for i in range(mod_buf.size(0))] - - for i in range(waveform.shape[-1]): - idx = int((delay_pos + mod_buf_list[mod_pos]) % delay_buf_len) - mod_pos = (mod_pos + 1) % mod_buf_len - delay_pos = (delay_pos + 1) % delay_buf_len - temp = (waveform_list[i]) + (delay_buf_list[idx]) - delay_buf_list[delay_pos] = temp * decay - output_waveform_pre_gain_list.append(temp) - - output_waveform = torch.stack(output_waveform_pre_gain_list, dim=1).to(dtype=dtype, device=device) - output_waveform.mul_(gain_out) - - return output_waveform.clamp(min=-1, max=1).view(actual_shape) - - -def _generate_wave_table( - wave_type: str, - data_type: str, - table_size: int, - min: float, - max: float, - phase: float, - device: torch.device -) -> Tensor: - r"""A helper fucntion for phaser. Generates a table with given parameters - - Args: - wave_type (str): SINE or TRIANGULAR - data_type (str): desired data_type ( `INT` or `FLOAT` ) - table_size (int): desired table size - min (float): desired min value - max (float): desired max value - phase (float): desired phase - device (torch.device): Torch device on which table must be generated - Returns: - Tensor: A 1D tensor with wave table values - """ - - phase_offset = int(phase / math.pi / 2 * table_size + 0.5) - - t = torch.arange(table_size, device=device, dtype=torch.int32) - - point = (t + phase_offset) % table_size - - d = torch.zeros_like(point, device=device, dtype=torch.float64) - - if wave_type == 'SINE': - d = (torch.sin(point.to(torch.float64) / table_size * 2 * math.pi) + 1) / 2 - elif wave_type == 'TRIANGLE': - d = point.to(torch.float64) * 2 / table_size - value = 4 * point // table_size - d[value == 0] = d[value == 0] + 0.5 - d[value == 1] = 1.5 - d[value == 1] - d[value == 2] = 1.5 - d[value == 2] - d[value == 3] = d[value == 3] - 1.5 - - d = d * (max - min) + min - - if data_type == 'INT': - mask = d < 0 - d[mask] = d[mask] - 0.5 - d[~mask] = d[~mask] + 0.5 - d = d.to(torch.int32) - elif data_type == 'FLOAT': - d = d.to(torch.float32) - - return d - - -def flanger( - waveform: Tensor, - sample_rate: int, - delay: float = 0., - depth: float = 2., - regen: float = 0., - width: float = 71., - speed: float = 0.5, - phase: float = 25., - modulation: str = 'sinusoidal', - interpolation: str = 'linear' -) -> Tensor: - r"""Apply a flanger effect to the audio. Similar to SoX implementation. - - Args: - waveform (Tensor): audio waveform of dimension of `(..., channel, time)` . - Max 4 channels allowed - sample_rate (int): sampling rate of the waveform, e.g. 44100 (Hz) - delay (float): desired delay in milliseconds(ms) - Allowed range of values are 0 to 30 - depth (float): desired delay depth in milliseconds(ms) - Allowed range of values are 0 to 10 - regen (float): desired regen(feeback gain) in dB - Allowed range of values are -95 to 95 - width (float): desired width(delay gain) in dB - Allowed range of values are 0 to 100 - speed (float): modulation speed in Hz - Allowed range of values are 0.1 to 10 - phase (float): percentage phase-shift for multi-channel - Allowed range of values are 0 to 100 - modulation (str): Use either "sinusoidal" or "triangular" modulation. (Default: ``sinusoidal``) - interpolation (str): Use either "linear" or "quadratic" for delay-line interpolation. (Default: ``linear``) - - Returns: - Tensor: Waveform of dimension of `(..., channel, time)` - - References: - http://sox.sourceforge.net/sox.html - - Scott Lehman, Effects Explained, - https://web.archive.org/web/20051125072557/http://www.harmony-central.com/Effects/effects-explained.html - """ - - if modulation not in ('sinusoidal', 'triangular'): - raise ValueError("Only 'sinusoidal' or 'triangular' modulation allowed") - - if interpolation not in ('linear', 'quadratic'): - raise ValueError("Only 'linear' or 'quadratic' interpolation allowed") - - actual_shape = waveform.shape - device, dtype = waveform.device, waveform.dtype - - if actual_shape[-2] > 4: - raise ValueError("Max 4 channels allowed") - - # convert to 3D (batch, channels, time) - waveform = waveform.view(-1, actual_shape[-2], actual_shape[-1]) - - # Scaling - feedback_gain = regen / 100 - delay_gain = width / 100 - channel_phase = phase / 100 - delay_min = delay / 1000 - delay_depth = depth / 1000 - - n_channels = waveform.shape[-2] - - if modulation == 'sinusoidal': - wave_type = 'SINE' - else: - wave_type = 'TRIANGLE' - - # Balance output: - in_gain = 1. / (1 + delay_gain) - delay_gain = delay_gain / (1 + delay_gain) - - # Balance feedback loop: - delay_gain = delay_gain * (1 - abs(feedback_gain)) - - delay_buf_length = int((delay_min + delay_depth) * sample_rate + 0.5) - delay_buf_length = delay_buf_length + 2 - - delay_bufs = torch.zeros(waveform.shape[0], n_channels, delay_buf_length, dtype=dtype, device=device) - delay_last = torch.zeros(waveform.shape[0], n_channels, dtype=dtype, device=device) - - lfo_length = int(sample_rate / speed) - - table_min = math.floor(delay_min * sample_rate + 0.5) - table_max = delay_buf_length - 2. - - lfo = _generate_wave_table(wave_type=wave_type, - data_type='FLOAT', - table_size=lfo_length, - min=float(table_min), - max=float(table_max), - phase=3 * math.pi / 2, - device=device) - - output_waveform = torch.zeros_like(waveform, dtype=dtype, device=device) - - delay_buf_pos = 0 - lfo_pos = 0 - channel_idxs = torch.arange(0, n_channels, device=device) - - for i in range(waveform.shape[-1]): - - delay_buf_pos = (delay_buf_pos + delay_buf_length - 1) % delay_buf_length - - cur_channel_phase = (channel_idxs * lfo_length * channel_phase + .5).to(torch.int64) - delay_tensor = lfo[(lfo_pos + cur_channel_phase) % lfo_length] - frac_delay = torch.frac(delay_tensor) - delay_tensor = torch.floor(delay_tensor) - - int_delay = delay_tensor.to(torch.int64) - - temp = waveform[:, :, i] - - delay_bufs[:, :, delay_buf_pos] = temp + delay_last * feedback_gain - - delayed_0 = delay_bufs[:, channel_idxs, (delay_buf_pos + int_delay) % delay_buf_length] - - int_delay = int_delay + 1 - - delayed_1 = delay_bufs[:, channel_idxs, (delay_buf_pos + int_delay) % delay_buf_length] - - int_delay = int_delay + 1 - - if interpolation == 'linear': - delayed = delayed_0 + (delayed_1 - delayed_0) * frac_delay - else: - delayed_2 = delay_bufs[:, channel_idxs, (delay_buf_pos + int_delay) % delay_buf_length] - - int_delay = int_delay + 1 - - delayed_2 = delayed_2 - delayed_0 - delayed_1 = delayed_1 - delayed_0 - a = delayed_2 * .5 - delayed_1 - b = delayed_1 * 2 - delayed_2 * .5 - - delayed = delayed_0 + (a * frac_delay + b) * frac_delay - - delay_last = delayed - output_waveform[:, :, i] = waveform[:, :, i] * in_gain + delayed * delay_gain - - lfo_pos = (lfo_pos + 1) % lfo_length - - return output_waveform.clamp(min=-1, max=1).view(actual_shape) - - -def mask_along_axis_iid( - specgrams: Tensor, - mask_param: int, - mask_value: float, - axis: int -) -> Tensor: - r""" - Apply a mask along ``axis``. Mask will be applied from indices ``[v_0, v_0 + v)``, where - ``v`` is sampled from ``uniform(0, mask_param)``, and ``v_0`` from ``uniform(0, max_v - v)``. - - Args: - specgrams (Tensor): Real spectrograms (batch, channel, freq, time) - mask_param (int): Number of columns to be masked will be uniformly sampled from [0, mask_param] - mask_value (float): Value to assign to the masked columns - axis (int): Axis to apply masking on (2 -> frequency, 3 -> time) - - Returns: - Tensor: Masked spectrograms of dimensions (batch, channel, freq, time) - """ - - if axis != 2 and axis != 3: - raise ValueError('Only Frequency and Time masking are supported') - - device = specgrams.device - dtype = specgrams.dtype - - value = torch.rand(specgrams.shape[:2], device=device, dtype=dtype) * mask_param - min_value = torch.rand(specgrams.shape[:2], device=device, dtype=dtype) * (specgrams.size(axis) - value) - - # Create broadcastable mask - mask_start = min_value[..., None, None] - mask_end = (min_value + value)[..., None, None] - mask = torch.arange(0, specgrams.size(axis), device=device, dtype=dtype) - - # Per batch example masking - specgrams = specgrams.transpose(axis, -1) - specgrams.masked_fill_((mask >= mask_start) & (mask < mask_end), mask_value) - specgrams = specgrams.transpose(axis, -1) - - return specgrams - - -def mask_along_axis( - specgram: Tensor, - mask_param: int, - mask_value: float, - axis: int -) -> Tensor: - r""" - Apply a mask along ``axis``. Mask will be applied from indices ``[v_0, v_0 + v)``, where - ``v`` is sampled from ``uniform(0, mask_param)``, and ``v_0`` from ``uniform(0, max_v - v)``. - All examples will have the same mask interval. - - Args: - specgram (Tensor): Real spectrogram (channel, freq, time) - mask_param (int): Number of columns to be masked will be uniformly sampled from [0, mask_param] - mask_value (float): Value to assign to the masked columns - axis (int): Axis to apply masking on (1 -> frequency, 2 -> time) - - Returns: - Tensor: Masked spectrogram of dimensions (channel, freq, time) - """ - - # pack batch - shape = specgram.size() - specgram = specgram.reshape([-1] + list(shape[-2:])) - - value = torch.rand(1) * mask_param - min_value = torch.rand(1) * (specgram.size(axis) - value) - - mask_start = (min_value.long()).squeeze() - mask_end = (min_value.long() + value.long()).squeeze() - - assert mask_end - mask_start < mask_param - if axis == 1: - specgram[:, mask_start:mask_end] = mask_value - elif axis == 2: - specgram[:, :, mask_start:mask_end] = mask_value - else: - raise ValueError('Only Frequency and Time masking are supported') - - # unpack batch - specgram = specgram.reshape(shape[:-2] + specgram.shape[-2:]) - - return specgram - - -def compute_deltas( - specgram: Tensor, - win_length: int = 5, - mode: str = "replicate" -) -> Tensor: - r"""Compute delta coefficients of a tensor, usually a spectrogram: - - .. math:: - d_t = \frac{\sum_{n=1}^{\text{N}} n (c_{t+n} - c_{t-n})}{2 \sum_{n=1}^{\text{N}} n^2} - - where :math:`d_t` is the deltas at time :math:`t`, - :math:`c_t` is the spectrogram coeffcients at time :math:`t`, - :math:`N` is ``(win_length-1)//2``. - - Args: - specgram (Tensor): Tensor of audio of dimension (..., freq, time) - win_length (int, optional): The window length used for computing delta (Default: ``5``) - mode (str, optional): Mode parameter passed to padding (Default: ``"replicate"``) - - Returns: - Tensor: Tensor of deltas of dimension (..., freq, time) - - Example - >>> specgram = torch.randn(1, 40, 1000) - >>> delta = compute_deltas(specgram) - >>> delta2 = compute_deltas(delta) - """ - device = specgram.device - dtype = specgram.dtype - - # pack batch - shape = specgram.size() - specgram = specgram.reshape(1, -1, shape[-1]) - - assert win_length >= 3 - - n = (win_length - 1) // 2 - - # twice sum of integer squared - denom = n * (n + 1) * (2 * n + 1) / 3 - - specgram = torch.nn.functional.pad(specgram, (n, n), mode=mode) - - kernel = torch.arange(-n, n + 1, 1, device=device, dtype=dtype).repeat(specgram.shape[1], 1, 1) - - output = torch.nn.functional.conv1d(specgram, kernel, groups=specgram.shape[1]) / denom - - # unpack batch - output = output.reshape(shape) - - return output - - -def gain( - waveform: Tensor, - gain_db: float = 1.0 -) -> Tensor: - r"""Apply amplification or attenuation to the whole waveform. - - Args: - waveform (Tensor): Tensor of audio of dimension (..., time). - gain_db (float, optional) Gain adjustment in decibels (dB) (Default: ``1.0``). - - Returns: - Tensor: the whole waveform amplified by gain_db. - """ - if (gain_db == 0): - return waveform - - ratio = 10 ** (gain_db / 20) - - return waveform * ratio - - -def _add_noise_shaping( - dithered_waveform: Tensor, - waveform: Tensor -) -> Tensor: - r"""Noise shaping is calculated by error: - error[n] = dithered[n] - original[n] - noise_shaped_waveform[n] = dithered[n] + error[n-1] - """ - wf_shape = waveform.size() - waveform = waveform.reshape(-1, wf_shape[-1]) - - dithered_shape = dithered_waveform.size() - dithered_waveform = dithered_waveform.reshape(-1, dithered_shape[-1]) - - error = dithered_waveform - waveform - - # add error[n-1] to dithered_waveform[n], so offset the error by 1 index - zeros = torch.zeros(1, dtype=error.dtype, device=error.device) - for index in range(error.size()[0]): - err = error[index] - error_offset = torch.cat((zeros, err)) - error[index] = error_offset[:waveform.size()[1]] - - noise_shaped = dithered_waveform + error - return noise_shaped.reshape(dithered_shape[:-1] + noise_shaped.shape[-1:]) - - -def _apply_probability_distribution( - waveform: Tensor, - density_function: str = "TPDF" -) -> Tensor: - r"""Apply a probability distribution function on a waveform. - - Triangular probability density function (TPDF) dither noise has a - triangular distribution; values in the center of the range have a higher - probability of occurring. - - Rectangular probability density function (RPDF) dither noise has a - uniform distribution; any value in the specified range has the same - probability of occurring. - - Gaussian probability density function (GPDF) has a normal distribution. - The relationship of probabilities of results follows a bell-shaped, - or Gaussian curve, typical of dither generated by analog sources. - Args: - waveform (Tensor): Tensor of audio of dimension (..., time) - probability_density_function (str, optional): The density function of a - continuous random variable (Default: ``"TPDF"``) - Options: Triangular Probability Density Function - `TPDF` - Rectangular Probability Density Function - `RPDF` - Gaussian Probability Density Function - `GPDF` - Returns: - Tensor: waveform dithered with TPDF - """ - - # pack batch - shape = waveform.size() - waveform = waveform.reshape(-1, shape[-1]) - - channel_size = waveform.size()[0] - 1 - time_size = waveform.size()[-1] - 1 - - random_channel = int(torch.randint(channel_size, [1, ]).item()) if channel_size > 0 else 0 - random_time = int(torch.randint(time_size, [1, ]).item()) if time_size > 0 else 0 - - number_of_bits = 16 - up_scaling = 2 ** (number_of_bits - 1) - 2 - signal_scaled = waveform * up_scaling - down_scaling = 2 ** (number_of_bits - 1) - - signal_scaled_dis = waveform - if (density_function == "RPDF"): - RPDF = waveform[random_channel][random_time] - 0.5 - - signal_scaled_dis = signal_scaled + RPDF - elif (density_function == "GPDF"): - # TODO Replace by distribution code once - # https://github.com/pytorch/pytorch/issues/29843 is resolved - # gaussian = torch.distributions.normal.Normal(torch.mean(waveform, -1), 1).sample() - - num_rand_variables = 6 - - gaussian = waveform[random_channel][random_time] - for ws in num_rand_variables * [time_size]: - rand_chan = int(torch.randint(channel_size, [1, ]).item()) - gaussian += waveform[rand_chan][int(torch.randint(ws, [1, ]).item())] - - signal_scaled_dis = signal_scaled + gaussian - else: - # dtype needed for https://github.com/pytorch/pytorch/issues/32358 - TPDF = torch.bartlett_window(time_size + 1, dtype=signal_scaled.dtype, device=signal_scaled.device) - TPDF = TPDF.repeat((channel_size + 1), 1) - signal_scaled_dis = signal_scaled + TPDF - - quantised_signal_scaled = torch.round(signal_scaled_dis) - quantised_signal = quantised_signal_scaled / down_scaling - - # unpack batch - return quantised_signal.reshape(shape[:-1] + quantised_signal.shape[-1:]) - - -def dither( - waveform: Tensor, - density_function: str = "TPDF", - noise_shaping: bool = False -) -> Tensor: - r"""Dither increases the perceived dynamic range of audio stored at a - particular bit-depth by eliminating nonlinear truncation distortion - (i.e. adding minimally perceived noise to mask distortion caused by quantization). - Args: - waveform (Tensor): Tensor of audio of dimension (..., time) - density_function (str, optional): The density function of a continuous random variable (Default: ``"TPDF"``) - Options: Triangular Probability Density Function - `TPDF` - Rectangular Probability Density Function - `RPDF` - Gaussian Probability Density Function - `GPDF` - noise_shaping (bool, optional): a filtering process that shapes the spectral - energy of quantisation error (Default: ``False``) - - Returns: - Tensor: waveform dithered - """ - dithered = _apply_probability_distribution(waveform, density_function=density_function) - - if noise_shaping: - return _add_noise_shaping(dithered, waveform) - else: - return dithered - - -def _compute_nccf( - waveform: Tensor, - sample_rate: int, - frame_time: float, - freq_low: int -) -> Tensor: - r""" - Compute Normalized Cross-Correlation Function (NCCF). - - .. math:: - \phi_i(m) = \frac{\sum_{n=b_i}^{b_i + N-1} w(n) w(m+n)}{\sqrt{E(b_i) E(m+b_i)}}, - - where - :math:`\phi_i(m)` is the NCCF at frame :math:`i` with lag :math:`m`, - :math:`w` is the waveform, - :math:`N` is the length of a frame, - :math:`b_i` is the beginning of frame :math:`i`, - :math:`E(j)` is the energy :math:`\sum_{n=j}^{j+N-1} w^2(n)`. - """ - - EPSILON = 10 ** (-9) - - # Number of lags to check - lags = int(math.ceil(sample_rate / freq_low)) - - frame_size = int(math.ceil(sample_rate * frame_time)) - - waveform_length = waveform.size()[-1] - num_of_frames = int(math.ceil(waveform_length / frame_size)) - - p = lags + num_of_frames * frame_size - waveform_length - waveform = torch.nn.functional.pad(waveform, (0, p)) - - # Compute lags - output_lag = [] - for lag in range(1, lags + 1): - s1 = waveform[..., :-lag].unfold(-1, frame_size, frame_size)[..., :num_of_frames, :] - s2 = waveform[..., lag:].unfold(-1, frame_size, frame_size)[..., :num_of_frames, :] - - output_frames = ( - (s1 * s2).sum(-1) - / (EPSILON + torch.norm(s1, p=2, dim=-1)).pow(2) - / (EPSILON + torch.norm(s2, p=2, dim=-1)).pow(2) - ) - - output_lag.append(output_frames.unsqueeze(-1)) - - nccf = torch.cat(output_lag, -1) - - return nccf - - -def _combine_max( - a: Tuple[Tensor, Tensor], - b: Tuple[Tensor, Tensor], - thresh: float = 0.99 -) -> Tuple[Tensor, Tensor]: - """ - Take value from first if bigger than a multiplicative factor of the second, elementwise. - """ - mask = (a[0] > thresh * b[0]) - values = mask * a[0] + ~mask * b[0] - indices = mask * a[1] + ~mask * b[1] - return values, indices - - -def _find_max_per_frame( - nccf: Tensor, - sample_rate: int, - freq_high: int -) -> Tensor: - r""" - For each frame, take the highest value of NCCF, - apply centered median smoothing, and convert to frequency. - - Note: If the max among all the lags is very close - to the first half of lags, then the latter is taken. - """ - - lag_min = int(math.ceil(sample_rate / freq_high)) - - # Find near enough max that is smallest - - best = torch.max(nccf[..., lag_min:], -1) - - half_size = nccf.shape[-1] // 2 - half = torch.max(nccf[..., lag_min:half_size], -1) - - best = _combine_max(half, best) - indices = best[1] - - # Add back minimal lag - indices += lag_min - # Add 1 empirical calibration offset - indices += 1 - - return indices - - -def _median_smoothing( - indices: Tensor, - win_length: int -) -> Tensor: - r""" - Apply median smoothing to the 1D tensor over the given window. - """ - - # Centered windowed - pad_length = (win_length - 1) // 2 - - # "replicate" padding in any dimension - indices = torch.nn.functional.pad( - indices, (pad_length, 0), mode="constant", value=0. - ) - - indices[..., :pad_length] = torch.cat(pad_length * [indices[..., pad_length].unsqueeze(-1)], dim=-1) - roll = indices.unfold(-1, win_length, 1) - - values, _ = torch.median(roll, -1) - return values - - -def detect_pitch_frequency( - waveform: Tensor, - sample_rate: int, - frame_time: float = 10 ** (-2), - win_length: int = 30, - freq_low: int = 85, - freq_high: int = 3400, -) -> Tensor: - r"""Detect pitch frequency. - - It is implemented using normalized cross-correlation function and median smoothing. - - Args: - waveform (Tensor): Tensor of audio of dimension (..., freq, time) - sample_rate (int): The sample rate of the waveform (Hz) - frame_time (float, optional): Duration of a frame (Default: ``10 ** (-2)``). - win_length (int, optional): The window length for median smoothing (in number of frames) (Default: ``30``). - freq_low (int, optional): Lowest frequency that can be detected (Hz) (Default: ``85``). - freq_high (int, optional): Highest frequency that can be detected (Hz) (Default: ``3400``). - - Returns: - Tensor: Tensor of freq of dimension (..., frame) - """ - # pack batch - shape = list(waveform.size()) - waveform = waveform.reshape([-1] + shape[-1:]) - - nccf = _compute_nccf(waveform, sample_rate, frame_time, freq_low) - indices = _find_max_per_frame(nccf, sample_rate, freq_high) - indices = _median_smoothing(indices, win_length) - - # Convert indices to frequency - EPSILON = 10 ** (-9) - freq = sample_rate / (EPSILON + indices.to(torch.float)) - - # unpack batch - freq = freq.reshape(shape[:-1] + list(freq.shape[-1:])) - - return freq - - -def sliding_window_cmn( - waveform: Tensor, - cmn_window: int = 600, - min_cmn_window: int = 100, - center: bool = False, - norm_vars: bool = False, -) -> Tensor: - r""" - Apply sliding-window cepstral mean (and optionally variance) normalization per utterance. - - Args: - waveform (Tensor): Tensor of audio of dimension (..., freq, time) - cmn_window (int, optional): Window in frames for running average CMN computation (int, default = 600) - min_cmn_window (int, optional): Minimum CMN window used at start of decoding (adds latency only at start). - Only applicable if center == false, ignored if center==true (int, default = 100) - center (bool, optional): If true, use a window centered on the current frame - (to the extent possible, modulo end effects). If false, window is to the left. (bool, default = false) - norm_vars (bool, optional): If true, normalize variance to one. (bool, default = false) - - Returns: - Tensor: Tensor of freq of dimension (..., frame) - """ - input_shape = waveform.shape - num_frames, num_feats = input_shape[-2:] - waveform = waveform.view(-1, num_frames, num_feats) - num_channels = waveform.shape[0] - - dtype = waveform.dtype - device = waveform.device - last_window_start = last_window_end = -1 - cur_sum = torch.zeros(num_channels, num_feats, dtype=dtype, device=device) - cur_sumsq = torch.zeros(num_channels, num_feats, dtype=dtype, device=device) - cmn_waveform = torch.zeros( - num_channels, num_frames, num_feats, dtype=dtype, device=device) - for t in range(num_frames): - window_start = 0 - window_end = 0 - if center: - window_start = t - cmn_window // 2 - window_end = window_start + cmn_window - else: - window_start = t - cmn_window - window_end = t + 1 - if window_start < 0: - window_end -= window_start - window_start = 0 - if not center: - if window_end > t: - window_end = max(t + 1, min_cmn_window) - if window_end > num_frames: - window_start -= (window_end - num_frames) - window_end = num_frames - if window_start < 0: - window_start = 0 - if last_window_start == -1: - input_part = waveform[:, window_start: window_end - window_start, :] - cur_sum += torch.sum(input_part, 1) - if norm_vars: - cur_sumsq += torch.cumsum(input_part ** 2, 1)[:, -1, :] - else: - if window_start > last_window_start: - frame_to_remove = waveform[:, last_window_start, :] - cur_sum -= frame_to_remove - if norm_vars: - cur_sumsq -= (frame_to_remove ** 2) - if window_end > last_window_end: - frame_to_add = waveform[:, last_window_end, :] - cur_sum += frame_to_add - if norm_vars: - cur_sumsq += (frame_to_add ** 2) - window_frames = window_end - window_start - last_window_start = window_start - last_window_end = window_end - cmn_waveform[:, t, :] = waveform[:, t, :] - cur_sum / window_frames - if norm_vars: - if window_frames == 1: - cmn_waveform[:, t, :] = torch.zeros( - num_channels, num_feats, dtype=dtype, device=device) - else: - variance = cur_sumsq - variance = variance / window_frames - variance -= ((cur_sum ** 2) / (window_frames ** 2)) - variance = torch.pow(variance, -0.5) - cmn_waveform[:, t, :] *= variance - - cmn_waveform = cmn_waveform.view(input_shape[:-2] + (num_frames, num_feats)) - if len(input_shape) == 2: - cmn_waveform = cmn_waveform.squeeze(0) - return cmn_waveform - - -def _measure( - measure_len_ws: int, - samples: Tensor, - spectrum: Tensor, - noise_spectrum: Tensor, - spectrum_window: Tensor, - spectrum_start: int, - spectrum_end: int, - cepstrum_window: Tensor, - cepstrum_start: int, - cepstrum_end: int, - noise_reduction_amount: float, - measure_smooth_time_mult: float, - noise_up_time_mult: float, - noise_down_time_mult: float, - index_ns: int, - boot_count: int -) -> float: - - assert spectrum.size()[-1] == noise_spectrum.size()[-1] - - samplesLen_ns = samples.size()[-1] - dft_len_ws = spectrum.size()[-1] - - dftBuf = torch.zeros(dft_len_ws) - - _index_ns = torch.tensor([index_ns] + [ - (index_ns + i) % samplesLen_ns - for i in range(1, measure_len_ws) - ]) - dftBuf[:measure_len_ws] = \ - samples[_index_ns] * spectrum_window[:measure_len_ws] - - # memset(c->dftBuf + i, 0, (p->dft_len_ws - i) * sizeof(*c->dftBuf)); - dftBuf[measure_len_ws:dft_len_ws].zero_() - - # lsx_safe_rdft((int)p->dft_len_ws, 1, c->dftBuf); - _dftBuf = torch.rfft(dftBuf, 1) - - # memset(c->dftBuf, 0, p->spectrum_start * sizeof(*c->dftBuf)); - _dftBuf[:spectrum_start].zero_() - - mult: float = boot_count / (1. + boot_count) \ - if boot_count >= 0 \ - else measure_smooth_time_mult - - _d = complex_norm(_dftBuf[spectrum_start:spectrum_end]) - spectrum[spectrum_start:spectrum_end].mul_(mult).add_(_d * (1 - mult)) - _d = spectrum[spectrum_start:spectrum_end] ** 2 - - _zeros = torch.zeros(spectrum_end - spectrum_start) - _mult = _zeros \ - if boot_count >= 0 \ - else torch.where( - _d > noise_spectrum[spectrum_start:spectrum_end], - torch.tensor(noise_up_time_mult), # if - torch.tensor(noise_down_time_mult) # else - ) - - noise_spectrum[spectrum_start:spectrum_end].mul_(_mult).add_(_d * (1 - _mult)) - _d = torch.sqrt( - torch.max( - _zeros, - _d - noise_reduction_amount * noise_spectrum[spectrum_start:spectrum_end])) - - _cepstrum_Buf: Tensor = torch.zeros(dft_len_ws >> 1) - _cepstrum_Buf[spectrum_start:spectrum_end] = _d * cepstrum_window - _cepstrum_Buf[spectrum_end:dft_len_ws >> 1].zero_() - - # lsx_safe_rdft((int)p->dft_len_ws >> 1, 1, c->dftBuf); - _cepstrum_Buf = torch.rfft(_cepstrum_Buf, 1) - - result: float = float(torch.sum( - complex_norm( - _cepstrum_Buf[cepstrum_start:cepstrum_end], - power=2.0))) - result = \ - math.log(result / (cepstrum_end - cepstrum_start)) \ - if result > 0 \ - else -math.inf - return max(0, 21 + result) - - -def vad( - waveform: Tensor, - sample_rate: int, - trigger_level: float = 7.0, - trigger_time: float = 0.25, - search_time: float = 1.0, - allowed_gap: float = 0.25, - pre_trigger_time: float = 0.0, - # Fine-tuning parameters - boot_time: float = .35, - noise_up_time: float = .1, - noise_down_time: float = .01, - noise_reduction_amount: float = 1.35, - measure_freq: float = 20.0, - measure_duration: Optional[float] = None, - measure_smooth_time: float = .4, - hp_filter_freq: float = 50., - lp_filter_freq: float = 6000., - hp_lifter_freq: float = 150., - lp_lifter_freq: float = 2000., -) -> Tensor: - r"""Voice Activity Detector. Similar to SoX implementation. - Attempts to trim silence and quiet background sounds from the ends of recordings of speech. - The algorithm currently uses a simple cepstral power measurement to detect voice, - so may be fooled by other things, especially music. - - The effect can trim only from the front of the audio, - so in order to trim from the back, the reverse effect must also be used. - - Args: - waveform (Tensor): Tensor of audio of dimension `(..., time)` - sample_rate (int): Sample rate of audio signal. - trigger_level (float, optional): The measurement level used to trigger activity detection. - This may need to be cahnged depending on the noise level, signal level, - and other characteristics of the input audio. (Default: 7.0) - trigger_time (float, optional): The time constant (in seconds) - used to help ignore short bursts of sound. (Default: 0.25) - search_time (float, optional): The amount of audio (in seconds) - to search for quieter/shorter bursts of audio to include prior - to the detected trigger point. (Default: 1.0) - allowed_gap (float, optional): The allowed gap (in seconds) between - quiteter/shorter bursts of audio to include prior - to the detected trigger point. (Default: 0.25) - pre_trigger_time (float, optional): The amount of audio (in seconds) to preserve - before the trigger point and any found quieter/shorter bursts. (Default: 0.0) - boot_time (float, optional) The algorithm (internally) uses adaptive noise - estimation/reduction in order to detect the start of the wanted audio. - This option sets the time for the initial noise estimate. (Default: 0.35) - noise_up_time (float, optional) Time constant used by the adaptive noise estimator - for when the noise level is increasing. (Default: 0.1) - noise_down_time (float, optional) Time constant used by the adaptive noise estimator - for when the noise level is decreasing. (Default: 0.01) - noise_reduction_amount (float, optional) Amount of noise reduction to use in - the detection algorithm (e.g. 0, 0.5, ...). (Default: 1.35) - measure_freq (float, optional) Frequency of the algorithmโ€™s - processing/measurements. (Default: 20.0) - measure_duration: (float, optional) Measurement duration. - (Default: Twice the measurement period; i.e. with overlap.) - measure_smooth_time (float, optional) Time constant used to smooth - spectral measurements. (Default: 0.4) - hp_filter_freq (float, optional) "Brick-wall" frequency of high-pass filter applied - at the input to the detector algorithm. (Default: 50.0) - lp_filter_freq (float, optional) "Brick-wall" frequency of low-pass filter applied - at the input to the detector algorithm. (Default: 6000.0) - hp_lifter_freq (float, optional) "Brick-wall" frequency of high-pass lifter used - in the detector algorithm. (Default: 150.0) - lp_lifter_freq (float, optional) "Brick-wall" frequency of low-pass lifter used - in the detector algorithm. (Default: 2000.0) - - Returns: - Tensor: Tensor of audio of dimension (..., time). - - References: - http://sox.sourceforge.net/sox.html - """ - - measure_duration: float = 2.0 / measure_freq \ - if measure_duration is None \ - else measure_duration - - measure_len_ws = int(sample_rate * measure_duration + .5) - measure_len_ns = measure_len_ws - # for (dft_len_ws = 16; dft_len_ws < measure_len_ws; dft_len_ws <<= 1); - dft_len_ws = 16 - while (dft_len_ws < measure_len_ws): - dft_len_ws *= 2 - - measure_period_ns = int(sample_rate / measure_freq + .5) - measures_len = math.ceil(search_time * measure_freq) - search_pre_trigger_len_ns = measures_len * measure_period_ns - gap_len = int(allowed_gap * measure_freq + .5) - - fixed_pre_trigger_len_ns = int(pre_trigger_time * sample_rate + .5) - samplesLen_ns = fixed_pre_trigger_len_ns + search_pre_trigger_len_ns + measure_len_ns - - spectrum_window = torch.zeros(measure_len_ws) - for i in range(measure_len_ws): - # sox.h:741 define SOX_SAMPLE_MIN (sox_sample_t)SOX_INT_MIN(32) - spectrum_window[i] = 2. / math.sqrt(float(measure_len_ws)) - # lsx_apply_hann(spectrum_window, (int)measure_len_ws); - spectrum_window *= torch.hann_window(measure_len_ws, dtype=torch.float) - - spectrum_start: int = int(hp_filter_freq / sample_rate * dft_len_ws + .5) - spectrum_start: int = max(spectrum_start, 1) - spectrum_end: int = int(lp_filter_freq / sample_rate * dft_len_ws + .5) - spectrum_end: int = min(spectrum_end, dft_len_ws // 2) - - cepstrum_window = torch.zeros(spectrum_end - spectrum_start) - for i in range(spectrum_end - spectrum_start): - cepstrum_window[i] = 2. / math.sqrt(float(spectrum_end) - spectrum_start) - # lsx_apply_hann(cepstrum_window,(int)(spectrum_end - spectrum_start)); - cepstrum_window *= torch.hann_window(spectrum_end - spectrum_start, dtype=torch.float) - - cepstrum_start = math.ceil(sample_rate * .5 / lp_lifter_freq) - cepstrum_end = math.floor(sample_rate * .5 / hp_lifter_freq) - cepstrum_end = min(cepstrum_end, dft_len_ws // 4) - - assert cepstrum_end > cepstrum_start - - noise_up_time_mult = math.exp(-1. / (noise_up_time * measure_freq)) - noise_down_time_mult = math.exp(-1. / (noise_down_time * measure_freq)) - measure_smooth_time_mult = math.exp(-1. / (measure_smooth_time * measure_freq)) - trigger_meas_time_mult = math.exp(-1. / (trigger_time * measure_freq)) - - boot_count_max = int(boot_time * measure_freq - .5) - measure_timer_ns = measure_len_ns - boot_count = measures_index = flushedLen_ns = samplesIndex_ns = 0 - - # pack batch - shape = waveform.size() - waveform = waveform.view(-1, shape[-1]) - - n_channels, ilen = waveform.size() - - mean_meas = torch.zeros(n_channels) - samples = torch.zeros(n_channels, samplesLen_ns) - spectrum = torch.zeros(n_channels, dft_len_ws) - noise_spectrum = torch.zeros(n_channels, dft_len_ws) - measures = torch.zeros(n_channels, measures_len) - - has_triggered: bool = False - num_measures_to_flush: int = 0 - pos: int = 0 - - while (pos < ilen and not has_triggered): - measure_timer_ns -= 1 - for i in range(n_channels): - samples[i, samplesIndex_ns] = waveform[i, pos] - # if (!p->measure_timer_ns) { - if (measure_timer_ns == 0): - index_ns: int = \ - (samplesIndex_ns + samplesLen_ns - measure_len_ns) % samplesLen_ns - meas: float = _measure( - measure_len_ws=measure_len_ws, - samples=samples[i], - spectrum=spectrum[i], - noise_spectrum=noise_spectrum[i], - spectrum_window=spectrum_window, - spectrum_start=spectrum_start, - spectrum_end=spectrum_end, - cepstrum_window=cepstrum_window, - cepstrum_start=cepstrum_start, - cepstrum_end=cepstrum_end, - noise_reduction_amount=noise_reduction_amount, - measure_smooth_time_mult=measure_smooth_time_mult, - noise_up_time_mult=noise_up_time_mult, - noise_down_time_mult=noise_down_time_mult, - index_ns=index_ns, - boot_count=boot_count) - measures[i, measures_index] = meas - mean_meas[i] = mean_meas[i] * trigger_meas_time_mult + meas * (1. - trigger_meas_time_mult) - - has_triggered = has_triggered or (mean_meas[i] >= trigger_level) - if has_triggered: - n: int = measures_len - k: int = measures_index - jTrigger: int = n - jZero: int = n - j: int = 0 - - for j in range(n): - if (measures[i, k] >= trigger_level) and (j <= jTrigger + gap_len): - jZero = jTrigger = j - elif (measures[i, k] == 0) and (jTrigger >= jZero): - jZero = j - k = (k + n - 1) % n - j = min(j, jZero) - # num_measures_to_flush = range_limit(j, num_measures_to_flush, n); - num_measures_to_flush = (min(max(num_measures_to_flush, j), n)) - # end if has_triggered - # end if (measure_timer_ns == 0): - # end for - samplesIndex_ns += 1 - pos += 1 - # end while - if samplesIndex_ns == samplesLen_ns: - samplesIndex_ns = 0 - if measure_timer_ns == 0: - measure_timer_ns = measure_period_ns - measures_index += 1 - measures_index = measures_index % measures_len - if boot_count >= 0: - boot_count = -1 if boot_count == boot_count_max else boot_count + 1 - - if has_triggered: - flushedLen_ns = (measures_len - num_measures_to_flush) * measure_period_ns - samplesIndex_ns = (samplesIndex_ns + flushedLen_ns) % samplesLen_ns - - res = waveform[:, pos - samplesLen_ns + flushedLen_ns:] - # unpack batch - return res.view(shape[:-1] + res.shape[-1:]) diff --git a/torchaudio/functional/__init__.py b/torchaudio/functional/__init__.py new file mode 100644 index 0000000000..3d1aa00f86 --- /dev/null +++ b/torchaudio/functional/__init__.py @@ -0,0 +1,42 @@ +from .functional import ( + amplitude_to_DB, + angle, + complex_norm, + compute_deltas, + create_dct, + create_fb_matrix, + DB_to_amplitude, + detect_pitch_frequency, + griffinlim, + magphase, + mask_along_axis, + mask_along_axis_iid, + mu_law_encoding, + mu_law_decoding, + phase_vocoder, + sliding_window_cmn, + spectrogram, +) +from .filtering import ( + allpass_biquad, + band_biquad, + bandpass_biquad, + bandreject_biquad, + bass_biquad, + biquad, + contrast, + dither, + dcshift, + deemph_biquad, + equalizer_biquad, + flanger, + gain, + highpass_biquad, + lfilter, + lowpass_biquad, + overdrive, + phaser, + riaa_biquad, + treble_biquad, + vad, +) diff --git a/torchaudio/functional/filtering.py b/torchaudio/functional/filtering.py new file mode 100644 index 0000000000..aa9f95f2e0 --- /dev/null +++ b/torchaudio/functional/filtering.py @@ -0,0 +1,1469 @@ +import math +from typing import Optional + +import torch +from torch import Tensor + +import torchaudio._internal.fft + + +def _dB2Linear(x: float) -> float: + return math.exp(x * math.log(10) / 20.0) + + +def _generate_wave_table( + wave_type: str, + data_type: str, + table_size: int, + min: float, + max: float, + phase: float, + device: torch.device, +) -> Tensor: + r"""A helper fucntion for phaser. Generates a table with given parameters + + Args: + wave_type (str): SINE or TRIANGULAR + data_type (str): desired data_type ( `INT` or `FLOAT` ) + table_size (int): desired table size + min (float): desired min value + max (float): desired max value + phase (float): desired phase + device (torch.device): Torch device on which table must be generated + Returns: + Tensor: A 1D tensor with wave table values + """ + + phase_offset = int(phase / math.pi / 2 * table_size + 0.5) + + t = torch.arange(table_size, device=device, dtype=torch.int32) + + point = (t + phase_offset) % table_size + + d = torch.zeros_like(point, device=device, dtype=torch.float64) + + if wave_type == "SINE": + d = (torch.sin(point.to(torch.float64) / table_size * 2 * math.pi) + 1) / 2 + elif wave_type == "TRIANGLE": + d = point.to(torch.float64) * 2 / table_size + value = 4 * point // table_size + d[value == 0] = d[value == 0] + 0.5 + d[value == 1] = 1.5 - d[value == 1] + d[value == 2] = 1.5 - d[value == 2] + d[value == 3] = d[value == 3] - 1.5 + + d = d * (max - min) + min + + if data_type == "INT": + mask = d < 0 + d[mask] = d[mask] - 0.5 + d[~mask] = d[~mask] + 0.5 + d = d.to(torch.int32) + elif data_type == "FLOAT": + d = d.to(torch.float32) + + return d + + +def allpass_biquad( + waveform: Tensor, sample_rate: int, central_freq: float, Q: float = 0.707 +) -> Tensor: + r"""Design two-pole all-pass filter. Similar to SoX implementation. + + Args: + waveform(torch.Tensor): audio waveform of dimension of `(..., time)` + sample_rate (int): sampling rate of the waveform, e.g. 44100 (Hz) + central_freq (float): central frequency (in Hz) + Q (float, optional): https://en.wikipedia.org/wiki/Q_factor (Default: ``0.707``) + + Returns: + Tensor: Waveform of dimension of `(..., time)` + + References: + http://sox.sourceforge.net/sox.html + https://www.w3.org/2011/audio/audio-eq-cookbook.html#APF + """ + w0 = 2 * math.pi * central_freq / sample_rate + alpha = math.sin(w0) / 2 / Q + + b0 = 1 - alpha + b1 = -2 * math.cos(w0) + b2 = 1 + alpha + a0 = 1 + alpha + a1 = -2 * math.cos(w0) + a2 = 1 - alpha + return biquad(waveform, b0, b1, b2, a0, a1, a2) + + +def band_biquad( + waveform: Tensor, + sample_rate: int, + central_freq: float, + Q: float = 0.707, + noise: bool = False, +) -> Tensor: + r"""Design two-pole band filter. Similar to SoX implementation. + + Args: + waveform (Tensor): audio waveform of dimension of `(..., time)` + sample_rate (int): sampling rate of the waveform, e.g. 44100 (Hz) + central_freq (float): central frequency (in Hz) + Q (float, optional): https://en.wikipedia.org/wiki/Q_factor (Default: ``0.707``). + noise (bool, optional) : If ``True``, uses the alternate mode for un-pitched audio (e.g. percussion). + If ``False``, uses mode oriented to pitched audio, i.e. voice, singing, + or instrumental music (Default: ``False``). + + Returns: + Tensor: Waveform of dimension of `(..., time)` + + References: + http://sox.sourceforge.net/sox.html + https://www.w3.org/2011/audio/audio-eq-cookbook.html#APF + """ + w0 = 2 * math.pi * central_freq / sample_rate + bw_Hz = central_freq / Q + + a0 = 1.0 + a2 = math.exp(-2 * math.pi * bw_Hz / sample_rate) + a1 = -4 * a2 / (1 + a2) * math.cos(w0) + + b0 = math.sqrt(1 - a1 * a1 / (4 * a2)) * (1 - a2) + + if noise: + mult = math.sqrt(((1 + a2) * (1 + a2) - a1 * a1) * (1 - a2) / (1 + a2)) / b0 + b0 *= mult + + b1 = 0.0 + b2 = 0.0 + + return biquad(waveform, b0, b1, b2, a0, a1, a2) + + +def bandpass_biquad( + waveform: Tensor, + sample_rate: int, + central_freq: float, + Q: float = 0.707, + const_skirt_gain: bool = False, +) -> Tensor: + r"""Design two-pole band-pass filter. Similar to SoX implementation. + + Args: + waveform (Tensor): audio waveform of dimension of `(..., time)` + sample_rate (int): sampling rate of the waveform, e.g. 44100 (Hz) + central_freq (float): central frequency (in Hz) + Q (float, optional): https://en.wikipedia.org/wiki/Q_factor (Default: ``0.707``) + const_skirt_gain (bool, optional) : If ``True``, uses a constant skirt gain (peak gain = Q). + If ``False``, uses a constant 0dB peak gain. (Default: ``False``) + + Returns: + Tensor: Waveform of dimension of `(..., time)` + + References: + http://sox.sourceforge.net/sox.html + https://www.w3.org/2011/audio/audio-eq-cookbook.html#APF + """ + w0 = 2 * math.pi * central_freq / sample_rate + alpha = math.sin(w0) / 2 / Q + + temp = math.sin(w0) / 2 if const_skirt_gain else alpha + b0 = temp + b1 = 0.0 + b2 = -temp + a0 = 1 + alpha + a1 = -2 * math.cos(w0) + a2 = 1 - alpha + return biquad(waveform, b0, b1, b2, a0, a1, a2) + + +def bandreject_biquad( + waveform: Tensor, sample_rate: int, central_freq: float, Q: float = 0.707 +) -> Tensor: + r"""Design two-pole band-reject filter. Similar to SoX implementation. + + Args: + waveform (Tensor): audio waveform of dimension of `(..., time)` + sample_rate (int): sampling rate of the waveform, e.g. 44100 (Hz) + central_freq (float): central frequency (in Hz) + Q (float, optional): https://en.wikipedia.org/wiki/Q_factor (Default: ``0.707``) + + Returns: + Tensor: Waveform of dimension of `(..., time)` + + References: + http://sox.sourceforge.net/sox.html + https://www.w3.org/2011/audio/audio-eq-cookbook.html#APF + """ + w0 = 2 * math.pi * central_freq / sample_rate + alpha = math.sin(w0) / 2 / Q + + b0 = 1.0 + b1 = -2 * math.cos(w0) + b2 = 1.0 + a0 = 1 + alpha + a1 = -2 * math.cos(w0) + a2 = 1 - alpha + return biquad(waveform, b0, b1, b2, a0, a1, a2) + + +def bass_biquad( + waveform: Tensor, + sample_rate: int, + gain: float, + central_freq: float = 100, + Q: float = 0.707, +) -> Tensor: + r"""Design a bass tone-control effect. Similar to SoX implementation. + + Args: + waveform (Tensor): audio waveform of dimension of `(..., time)` + sample_rate (int): sampling rate of the waveform, e.g. 44100 (Hz) + gain (float): desired gain at the boost (or attenuation) in dB. + central_freq (float, optional): central frequency (in Hz). (Default: ``100``) + Q (float, optional): https://en.wikipedia.org/wiki/Q_factor (Default: ``0.707``). + + Returns: + Tensor: Waveform of dimension of `(..., time)` + + References: + http://sox.sourceforge.net/sox.html + https://www.w3.org/2011/audio/audio-eq-cookbook.html#APF + """ + w0 = 2 * math.pi * central_freq / sample_rate + alpha = math.sin(w0) / 2 / Q + A = math.exp(gain / 40 * math.log(10)) + + temp1 = 2 * math.sqrt(A) * alpha + temp2 = (A - 1) * math.cos(w0) + temp3 = (A + 1) * math.cos(w0) + + b0 = A * ((A + 1) - temp2 + temp1) + b1 = 2 * A * ((A - 1) - temp3) + b2 = A * ((A + 1) - temp2 - temp1) + a0 = (A + 1) + temp2 + temp1 + a1 = -2 * ((A - 1) + temp3) + a2 = (A + 1) + temp2 - temp1 + + return biquad(waveform, b0 / a0, b1 / a0, b2 / a0, a0 / a0, a1 / a0, a2 / a0) + + +def biquad( + waveform: Tensor, b0: float, b1: float, b2: float, a0: float, a1: float, a2: float +) -> Tensor: + r"""Perform a biquad filter of input tensor. Initial conditions set to 0. + https://en.wikipedia.org/wiki/Digital_biquad_filter + + Args: + waveform (Tensor): audio waveform of dimension of `(..., time)` + b0 (float): numerator coefficient of current input, x[n] + b1 (float): numerator coefficient of input one time step ago x[n-1] + b2 (float): numerator coefficient of input two time steps ago x[n-2] + a0 (float): denominator coefficient of current output y[n], typically 1 + a1 (float): denominator coefficient of current output y[n-1] + a2 (float): denominator coefficient of current output y[n-2] + + Returns: + Tensor: Waveform with dimension of `(..., time)` + """ + + device = waveform.device + dtype = waveform.dtype + + output_waveform = lfilter( + waveform, + torch.tensor([a0, a1, a2], dtype=dtype, device=device), + torch.tensor([b0, b1, b2], dtype=dtype, device=device), + ) + return output_waveform + + +def contrast(waveform: Tensor, enhancement_amount: float = 75.0) -> Tensor: + r"""Apply contrast effect. Similar to SoX implementation. + Comparable with compression, this effect modifies an audio signal to make it sound louder + + Args: + waveform (Tensor): audio waveform of dimension of `(..., time)` + enhancement_amount (float): controls the amount of the enhancement + Allowed range of values for enhancement_amount : 0-100 + Note that enhancement_amount = 0 still gives a significant contrast enhancement + + Returns: + Tensor: Waveform of dimension of `(..., time)` + + References: + http://sox.sourceforge.net/sox.html + """ + + if not 0 <= enhancement_amount <= 100: + raise ValueError("Allowed range of values for enhancement_amount : 0-100") + + contrast = enhancement_amount / 750.0 + + temp1 = waveform * (math.pi / 2) + temp2 = contrast * torch.sin(temp1 * 4) + output_waveform = torch.sin(temp1 + temp2) + + return output_waveform + + +def dcshift( + waveform: Tensor, shift: float, limiter_gain: Optional[float] = None +) -> Tensor: + r"""Apply a DC shift to the audio. Similar to SoX implementation. + This can be useful to remove a DC offset + (caused perhaps by a hardware problem in the recording chain) from the audio + + Args: + waveform (Tensor): audio waveform of dimension of `(..., time)` + shift (float): indicates the amount to shift the audio + Allowed range of values for shift : -2.0 to +2.0 + limiter_gain (float): It is used only on peaks to prevent clipping + It should have a value much less than 1 (e.g. 0.05 or 0.02) + + Returns: + Tensor: Waveform of dimension of `(..., time)` + + References: + http://sox.sourceforge.net/sox.html + """ + output_waveform = waveform + limiter_threshold = 0.0 + + if limiter_gain is not None: + limiter_threshold = 1.0 - (abs(shift) - limiter_gain) + + if limiter_gain is not None and shift > 0: + mask = waveform > limiter_threshold + temp = ( + (waveform[mask] - limiter_threshold) + * limiter_gain + / (1 - limiter_threshold) + ) + output_waveform[mask] = (temp + limiter_threshold + shift).clamp( + max=limiter_threshold + ) + output_waveform[~mask] = (waveform[~mask] + shift).clamp(min=-1, max=1) + elif limiter_gain is not None and shift < 0: + mask = waveform < -limiter_threshold + temp = ( + (waveform[mask] + limiter_threshold) + * limiter_gain + / (1 - limiter_threshold) + ) + output_waveform[mask] = (temp - limiter_threshold + shift).clamp( + min=-limiter_threshold + ) + output_waveform[~mask] = (waveform[~mask] + shift).clamp(min=-1, max=1) + else: + output_waveform = (waveform + shift).clamp(min=-1, max=1) + + return output_waveform + + +def deemph_biquad(waveform: Tensor, sample_rate: int) -> Tensor: + r"""Apply ISO 908 CD de-emphasis (shelving) IIR filter. Similar to SoX implementation. + + Args: + waveform (Tensor): audio waveform of dimension of `(..., time)` + sample_rate (int): sampling rate of the waveform, Allowed sample rate ``44100`` or ``48000`` + + Returns: + Tensor: Waveform of dimension of `(..., time)` + + References: + http://sox.sourceforge.net/sox.html + https://www.w3.org/2011/audio/audio-eq-cookbook.html#APF + """ + + if sample_rate == 44100: + central_freq = 5283 + width_slope = 0.4845 + gain = -9.477 + elif sample_rate == 48000: + central_freq = 5356 + width_slope = 0.479 + gain = -9.62 + else: + raise ValueError("Sample rate must be 44100 (audio-CD) or 48000 (DAT)") + + w0 = 2 * math.pi * central_freq / sample_rate + A = math.exp(gain / 40.0 * math.log(10)) + alpha = math.sin(w0) / 2 * math.sqrt((A + 1 / A) * (1 / width_slope - 1) + 2) + + temp1 = 2 * math.sqrt(A) * alpha + temp2 = (A - 1) * math.cos(w0) + temp3 = (A + 1) * math.cos(w0) + + b0 = A * ((A + 1) + temp2 + temp1) + b1 = -2 * A * ((A - 1) + temp3) + b2 = A * ((A + 1) + temp2 - temp1) + a0 = (A + 1) - temp2 + temp1 + a1 = 2 * ((A - 1) - temp3) + a2 = (A + 1) - temp2 - temp1 + + return biquad(waveform, b0, b1, b2, a0, a1, a2) + + +def _add_noise_shaping(dithered_waveform: Tensor, waveform: Tensor) -> Tensor: + r"""Noise shaping is calculated by error: + error[n] = dithered[n] - original[n] + noise_shaped_waveform[n] = dithered[n] + error[n-1] + """ + wf_shape = waveform.size() + waveform = waveform.reshape(-1, wf_shape[-1]) + + dithered_shape = dithered_waveform.size() + dithered_waveform = dithered_waveform.reshape(-1, dithered_shape[-1]) + + error = dithered_waveform - waveform + + # add error[n-1] to dithered_waveform[n], so offset the error by 1 index + zeros = torch.zeros(1, dtype=error.dtype, device=error.device) + for index in range(error.size()[0]): + err = error[index] + error_offset = torch.cat((zeros, err)) + error[index] = error_offset[: waveform.size()[1]] + + noise_shaped = dithered_waveform + error + return noise_shaped.reshape(dithered_shape[:-1] + noise_shaped.shape[-1:]) + + +def _apply_probability_distribution( + waveform: Tensor, density_function: str = "TPDF" +) -> Tensor: + r"""Apply a probability distribution function on a waveform. + + Triangular probability density function (TPDF) dither noise has a + triangular distribution; values in the center of the range have a higher + probability of occurring. + + Rectangular probability density function (RPDF) dither noise has a + uniform distribution; any value in the specified range has the same + probability of occurring. + + Gaussian probability density function (GPDF) has a normal distribution. + The relationship of probabilities of results follows a bell-shaped, + or Gaussian curve, typical of dither generated by analog sources. + Args: + waveform (Tensor): Tensor of audio of dimension (..., time) + probability_density_function (str, optional): The density function of a + continuous random variable (Default: ``"TPDF"``) + Options: Triangular Probability Density Function - `TPDF` + Rectangular Probability Density Function - `RPDF` + Gaussian Probability Density Function - `GPDF` + Returns: + Tensor: waveform dithered with TPDF + """ + + # pack batch + shape = waveform.size() + waveform = waveform.reshape(-1, shape[-1]) + + channel_size = waveform.size()[0] - 1 + time_size = waveform.size()[-1] - 1 + + random_channel = ( + int( + torch.randint( + channel_size, + [ + 1, + ], + ).item() + ) + if channel_size > 0 + else 0 + ) + random_time = ( + int( + torch.randint( + time_size, + [ + 1, + ], + ).item() + ) + if time_size > 0 + else 0 + ) + + number_of_bits = 16 + up_scaling = 2 ** (number_of_bits - 1) - 2 + signal_scaled = waveform * up_scaling + down_scaling = 2 ** (number_of_bits - 1) + + signal_scaled_dis = waveform + if density_function == "RPDF": + RPDF = waveform[random_channel][random_time] - 0.5 + + signal_scaled_dis = signal_scaled + RPDF + elif density_function == "GPDF": + # TODO Replace by distribution code once + # https://github.com/pytorch/pytorch/issues/29843 is resolved + # gaussian = torch.distributions.normal.Normal(torch.mean(waveform, -1), 1).sample() + + num_rand_variables = 6 + + gaussian = waveform[random_channel][random_time] + for ws in num_rand_variables * [time_size]: + rand_chan = int( + torch.randint( + channel_size, + [ + 1, + ], + ).item() + ) + gaussian += waveform[rand_chan][ + int( + torch.randint( + ws, + [ + 1, + ], + ).item() + ) + ] + + signal_scaled_dis = signal_scaled + gaussian + else: + # dtype needed for https://github.com/pytorch/pytorch/issues/32358 + TPDF = torch.bartlett_window( + time_size + 1, dtype=signal_scaled.dtype, device=signal_scaled.device + ) + TPDF = TPDF.repeat((channel_size + 1), 1) + signal_scaled_dis = signal_scaled + TPDF + + quantised_signal_scaled = torch.round(signal_scaled_dis) + quantised_signal = quantised_signal_scaled / down_scaling + + # unpack batch + return quantised_signal.reshape(shape[:-1] + quantised_signal.shape[-1:]) + + +def dither( + waveform: Tensor, density_function: str = "TPDF", noise_shaping: bool = False +) -> Tensor: + r"""Dither increases the perceived dynamic range of audio stored at a + particular bit-depth by eliminating nonlinear truncation distortion + (i.e. adding minimally perceived noise to mask distortion caused by quantization). + + Args: + waveform (Tensor): Tensor of audio of dimension (..., time) + density_function (str, optional): + The density function of a continuous random variable. One of + ``"TPDF"`` (Triangular Probability Density Function), + ``"RPDF"`` (Rectangular Probability Density Function) or + ``"GPDF"`` (Gaussian Probability Density Function) (Default: ``"TPDF"``). + noise_shaping (bool, optional): a filtering process that shapes the spectral + energy of quantisation error (Default: ``False``) + + Returns: + Tensor: waveform dithered + """ + dithered = _apply_probability_distribution( + waveform, density_function=density_function + ) + + if noise_shaping: + return _add_noise_shaping(dithered, waveform) + else: + return dithered + + +def equalizer_biquad( + waveform: Tensor, + sample_rate: int, + center_freq: float, + gain: float, + Q: float = 0.707, +) -> Tensor: + r"""Design biquad peaking equalizer filter and perform filtering. Similar to SoX implementation. + + Args: + waveform (Tensor): audio waveform of dimension of `(..., time)` + sample_rate (int): sampling rate of the waveform, e.g. 44100 (Hz) + center_freq (float): filter's central frequency + gain (float): desired gain at the boost (or attenuation) in dB + Q (float, optional): https://en.wikipedia.org/wiki/Q_factor (Default: ``0.707``) + + Returns: + Tensor: Waveform of dimension of `(..., time)` + """ + w0 = 2 * math.pi * center_freq / sample_rate + A = math.exp(gain / 40.0 * math.log(10)) + alpha = math.sin(w0) / 2 / Q + + b0 = 1 + alpha * A + b1 = -2 * math.cos(w0) + b2 = 1 - alpha * A + a0 = 1 + alpha / A + a1 = -2 * math.cos(w0) + a2 = 1 - alpha / A + return biquad(waveform, b0, b1, b2, a0, a1, a2) + + +def flanger( + waveform: Tensor, + sample_rate: int, + delay: float = 0.0, + depth: float = 2.0, + regen: float = 0.0, + width: float = 71.0, + speed: float = 0.5, + phase: float = 25.0, + modulation: str = "sinusoidal", + interpolation: str = "linear", +) -> Tensor: + r"""Apply a flanger effect to the audio. Similar to SoX implementation. + + Args: + waveform (Tensor): audio waveform of dimension of `(..., channel, time)` . + Max 4 channels allowed + sample_rate (int): sampling rate of the waveform, e.g. 44100 (Hz) + delay (float): desired delay in milliseconds(ms) + Allowed range of values are 0 to 30 + depth (float): desired delay depth in milliseconds(ms) + Allowed range of values are 0 to 10 + regen (float): desired regen(feeback gain) in dB + Allowed range of values are -95 to 95 + width (float): desired width(delay gain) in dB + Allowed range of values are 0 to 100 + speed (float): modulation speed in Hz + Allowed range of values are 0.1 to 10 + phase (float): percentage phase-shift for multi-channel + Allowed range of values are 0 to 100 + modulation (str): Use either "sinusoidal" or "triangular" modulation. (Default: ``sinusoidal``) + interpolation (str): Use either "linear" or "quadratic" for delay-line interpolation. (Default: ``linear``) + + Returns: + Tensor: Waveform of dimension of `(..., channel, time)` + + References: + http://sox.sourceforge.net/sox.html + + Scott Lehman, Effects Explained, + https://web.archive.org/web/20051125072557/http://www.harmony-central.com/Effects/effects-explained.html + """ + + if modulation not in ("sinusoidal", "triangular"): + raise ValueError("Only 'sinusoidal' or 'triangular' modulation allowed") + + if interpolation not in ("linear", "quadratic"): + raise ValueError("Only 'linear' or 'quadratic' interpolation allowed") + + actual_shape = waveform.shape + device, dtype = waveform.device, waveform.dtype + + if actual_shape[-2] > 4: + raise ValueError("Max 4 channels allowed") + + # convert to 3D (batch, channels, time) + waveform = waveform.view(-1, actual_shape[-2], actual_shape[-1]) + + # Scaling + feedback_gain = regen / 100 + delay_gain = width / 100 + channel_phase = phase / 100 + delay_min = delay / 1000 + delay_depth = depth / 1000 + + n_channels = waveform.shape[-2] + + if modulation == "sinusoidal": + wave_type = "SINE" + else: + wave_type = "TRIANGLE" + + # Balance output: + in_gain = 1.0 / (1 + delay_gain) + delay_gain = delay_gain / (1 + delay_gain) + + # Balance feedback loop: + delay_gain = delay_gain * (1 - abs(feedback_gain)) + + delay_buf_length = int((delay_min + delay_depth) * sample_rate + 0.5) + delay_buf_length = delay_buf_length + 2 + + delay_bufs = torch.zeros( + waveform.shape[0], n_channels, delay_buf_length, dtype=dtype, device=device + ) + delay_last = torch.zeros(waveform.shape[0], n_channels, dtype=dtype, device=device) + + lfo_length = int(sample_rate / speed) + + table_min = math.floor(delay_min * sample_rate + 0.5) + table_max = delay_buf_length - 2.0 + + lfo = _generate_wave_table( + wave_type=wave_type, + data_type="FLOAT", + table_size=lfo_length, + min=float(table_min), + max=float(table_max), + phase=3 * math.pi / 2, + device=device, + ) + + output_waveform = torch.zeros_like(waveform, dtype=dtype, device=device) + + delay_buf_pos = 0 + lfo_pos = 0 + channel_idxs = torch.arange(0, n_channels, device=device) + + for i in range(waveform.shape[-1]): + + delay_buf_pos = (delay_buf_pos + delay_buf_length - 1) % delay_buf_length + + cur_channel_phase = (channel_idxs * lfo_length * channel_phase + 0.5).to( + torch.int64 + ) + delay_tensor = lfo[(lfo_pos + cur_channel_phase) % lfo_length] + frac_delay = torch.frac(delay_tensor) + delay_tensor = torch.floor(delay_tensor) + + int_delay = delay_tensor.to(torch.int64) + + temp = waveform[:, :, i] + + delay_bufs[:, :, delay_buf_pos] = temp + delay_last * feedback_gain + + delayed_0 = delay_bufs[ + :, channel_idxs, (delay_buf_pos + int_delay) % delay_buf_length + ] + + int_delay = int_delay + 1 + + delayed_1 = delay_bufs[ + :, channel_idxs, (delay_buf_pos + int_delay) % delay_buf_length + ] + + int_delay = int_delay + 1 + + if interpolation == "linear": + delayed = delayed_0 + (delayed_1 - delayed_0) * frac_delay + else: + delayed_2 = delay_bufs[ + :, channel_idxs, (delay_buf_pos + int_delay) % delay_buf_length + ] + + int_delay = int_delay + 1 + + delayed_2 = delayed_2 - delayed_0 + delayed_1 = delayed_1 - delayed_0 + a = delayed_2 * 0.5 - delayed_1 + b = delayed_1 * 2 - delayed_2 * 0.5 + + delayed = delayed_0 + (a * frac_delay + b) * frac_delay + + delay_last = delayed + output_waveform[:, :, i] = waveform[:, :, i] * in_gain + delayed * delay_gain + + lfo_pos = (lfo_pos + 1) % lfo_length + + return output_waveform.clamp(min=-1, max=1).view(actual_shape) + + +def gain(waveform: Tensor, gain_db: float = 1.0) -> Tensor: + r"""Apply amplification or attenuation to the whole waveform. + + Args: + waveform (Tensor): Tensor of audio of dimension (..., time). + gain_db (float, optional) Gain adjustment in decibels (dB) (Default: ``1.0``). + + Returns: + Tensor: the whole waveform amplified by gain_db. + """ + if gain_db == 0: + return waveform + + ratio = 10 ** (gain_db / 20) + + return waveform * ratio + + +def highpass_biquad( + waveform: Tensor, sample_rate: int, cutoff_freq: float, Q: float = 0.707 +) -> Tensor: + r"""Design biquad highpass filter and perform filtering. Similar to SoX implementation. + + Args: + waveform (Tensor): audio waveform of dimension of `(..., time)` + sample_rate (int): sampling rate of the waveform, e.g. 44100 (Hz) + cutoff_freq (float): filter cutoff frequency + Q (float, optional): https://en.wikipedia.org/wiki/Q_factor (Default: ``0.707``) + + Returns: + Tensor: Waveform dimension of `(..., time)` + """ + w0 = 2 * math.pi * cutoff_freq / sample_rate + alpha = math.sin(w0) / 2.0 / Q + + b0 = (1 + math.cos(w0)) / 2 + b1 = -1 - math.cos(w0) + b2 = b0 + a0 = 1 + alpha + a1 = -2 * math.cos(w0) + a2 = 1 - alpha + return biquad(waveform, b0, b1, b2, a0, a1, a2) + + +def lfilter( + waveform: Tensor, + a_coeffs: Tensor, + b_coeffs: Tensor, + clamp: bool = True, +) -> Tensor: + r"""Perform an IIR filter by evaluating difference equation. + + Args: + waveform (Tensor): audio waveform of dimension of ``(..., time)``. Must be normalized to -1 to 1. + a_coeffs (Tensor): denominator coefficients of difference equation of dimension of ``(n_order + 1)``. + Lower delays coefficients are first, e.g. ``[a0, a1, a2, ...]``. + Must be same size as b_coeffs (pad with 0's as necessary). + b_coeffs (Tensor): numerator coefficients of difference equation of dimension of ``(n_order + 1)``. + Lower delays coefficients are first, e.g. ``[b0, b1, b2, ...]``. + Must be same size as a_coeffs (pad with 0's as necessary). + clamp (bool, optional): If ``True``, clamp the output signal to be in the range [-1, 1] (Default: ``True``) + + Returns: + Tensor: Waveform with dimension of ``(..., time)``. + """ + # pack batch + shape = waveform.size() + waveform = waveform.reshape(-1, shape[-1]) + + assert a_coeffs.size(0) == b_coeffs.size(0) + assert len(waveform.size()) == 2 + assert waveform.device == a_coeffs.device + assert b_coeffs.device == a_coeffs.device + + device = waveform.device + dtype = waveform.dtype + n_channel, n_sample = waveform.size() + n_order = a_coeffs.size(0) + n_sample_padded = n_sample + n_order - 1 + assert n_order > 0 + + # Pad the input and create output + padded_waveform = torch.zeros( + n_channel, n_sample_padded, dtype=dtype, device=device + ) + padded_waveform[:, n_order - 1:] = waveform + padded_output_waveform = torch.zeros( + n_channel, n_sample_padded, dtype=dtype, device=device + ) + + # Set up the coefficients matrix + # Flip coefficients' order + a_coeffs_flipped = a_coeffs.flip(0) + b_coeffs_flipped = b_coeffs.flip(0) + + # calculate windowed_input_signal in parallel + # create indices of original with shape (n_channel, n_order, n_sample) + window_idxs = torch.arange(n_sample, device=device).unsqueeze(0) + torch.arange( + n_order, device=device + ).unsqueeze(1) + window_idxs = window_idxs.repeat(n_channel, 1, 1) + window_idxs += ( + torch.arange(n_channel, device=device).unsqueeze(-1).unsqueeze(-1) + * n_sample_padded + ) + window_idxs = window_idxs.long() + # (n_order, ) matmul (n_channel, n_order, n_sample) -> (n_channel, n_sample) + input_signal_windows = torch.matmul( + b_coeffs_flipped, torch.take(padded_waveform, window_idxs) + ) + + input_signal_windows.div_(a_coeffs[0]) + a_coeffs_flipped.div_(a_coeffs[0]) + for i_sample, o0 in enumerate(input_signal_windows.t()): + windowed_output_signal = padded_output_waveform[ + :, i_sample:i_sample + n_order + ] + o0.addmv_(windowed_output_signal, a_coeffs_flipped, alpha=-1) + padded_output_waveform[:, i_sample + n_order - 1] = o0 + + output = padded_output_waveform[:, n_order - 1:] + + if clamp: + output = torch.clamp(output, min=-1.0, max=1.0) + + # unpack batch + output = output.reshape(shape[:-1] + output.shape[-1:]) + + return output + + +def lowpass_biquad( + waveform: Tensor, sample_rate: int, cutoff_freq: float, Q: float = 0.707 +) -> Tensor: + r"""Design biquad lowpass filter and perform filtering. Similar to SoX implementation. + + Args: + waveform (torch.Tensor): audio waveform of dimension of `(..., time)` + sample_rate (int): sampling rate of the waveform, e.g. 44100 (Hz) + cutoff_freq (float): filter cutoff frequency + Q (float, optional): https://en.wikipedia.org/wiki/Q_factor (Default: ``0.707``) + + Returns: + Tensor: Waveform of dimension of `(..., time)` + """ + w0 = 2 * math.pi * cutoff_freq / sample_rate + alpha = math.sin(w0) / 2 / Q + + b0 = (1 - math.cos(w0)) / 2 + b1 = 1 - math.cos(w0) + b2 = b0 + a0 = 1 + alpha + a1 = -2 * math.cos(w0) + a2 = 1 - alpha + return biquad(waveform, b0, b1, b2, a0, a1, a2) + + +def overdrive(waveform: Tensor, gain: float = 20, colour: float = 20) -> Tensor: + r"""Apply a overdrive effect to the audio. Similar to SoX implementation. + This effect applies a non linear distortion to the audio signal. + + Args: + waveform (Tensor): audio waveform of dimension of `(..., time)` + gain (float): desired gain at the boost (or attenuation) in dB + Allowed range of values are 0 to 100 + colour (float): controls the amount of even harmonic content in the over-driven output + Allowed range of values are 0 to 100 + + Returns: + Tensor: Waveform of dimension of `(..., time)` + + References: + http://sox.sourceforge.net/sox.html + """ + actual_shape = waveform.shape + device, dtype = waveform.device, waveform.dtype + + # convert to 2D (..,time) + waveform = waveform.view(-1, actual_shape[-1]) + + gain = _dB2Linear(gain) + colour = colour / 200 + last_in = torch.zeros(waveform.shape[:-1], dtype=dtype, device=device) + last_out = torch.zeros(waveform.shape[:-1], dtype=dtype, device=device) + + temp = waveform * gain + colour + + mask1 = temp < -1 + temp[mask1] = torch.tensor(-2.0 / 3.0, dtype=dtype, device=device) + # Wrapping the constant with Tensor is required for Torchscript + + mask2 = temp > 1 + temp[mask2] = torch.tensor(2.0 / 3.0, dtype=dtype, device=device) + + mask3 = ~mask1 & ~mask2 + temp[mask3] = temp[mask3] - (temp[mask3] ** 3) * (1.0 / 3) + + output_waveform = torch.zeros_like(waveform, dtype=dtype, device=device) + + # TODO: Implement a torch CPP extension + for i in range(waveform.shape[-1]): + last_out = temp[:, i] - last_in + 0.995 * last_out + last_in = temp[:, i] + output_waveform[:, i] = waveform[:, i] * 0.5 + last_out * 0.75 + + return output_waveform.clamp(min=-1, max=1).view(actual_shape) + + +def phaser( + waveform: Tensor, + sample_rate: int, + gain_in: float = 0.4, + gain_out: float = 0.74, + delay_ms: float = 3.0, + decay: float = 0.4, + mod_speed: float = 0.5, + sinusoidal: bool = True, +) -> Tensor: + r"""Apply a phasing effect to the audio. Similar to SoX implementation. + + Args: + waveform (Tensor): audio waveform of dimension of `(..., time)` + sample_rate (int): sampling rate of the waveform, e.g. 44100 (Hz) + gain_in (float): desired input gain at the boost (or attenuation) in dB + Allowed range of values are 0 to 1 + gain_out (float): desired output gain at the boost (or attenuation) in dB + Allowed range of values are 0 to 1e9 + delay_ms (float): desired delay in milli seconds + Allowed range of values are 0 to 5.0 + decay (float): desired decay relative to gain-in + Allowed range of values are 0 to 0.99 + mod_speed (float): modulation speed in Hz + Allowed range of values are 0.1 to 2 + sinusoidal (bool): If ``True``, uses sinusoidal modulation (preferable for multiple instruments) + If ``False``, uses triangular modulation (gives single instruments a sharper phasing effect) + (Default: ``True``) + + Returns: + Tensor: Waveform of dimension of `(..., time)` + + References: + http://sox.sourceforge.net/sox.html + Scott Lehman, Effects Explained, http://harmony-central.com/Effects/effects-explained.html + """ + actual_shape = waveform.shape + device, dtype = waveform.device, waveform.dtype + + # convert to 2D (channels,time) + waveform = waveform.view(-1, actual_shape[-1]) + + delay_buf_len = int((delay_ms * 0.001 * sample_rate) + 0.5) + delay_buf = torch.zeros( + waveform.shape[0], delay_buf_len, dtype=dtype, device=device + ) + + mod_buf_len = int(sample_rate / mod_speed + 0.5) + + if sinusoidal: + wave_type = "SINE" + else: + wave_type = "TRIANGLE" + + mod_buf = _generate_wave_table( + wave_type=wave_type, + data_type="INT", + table_size=mod_buf_len, + min=1.0, + max=float(delay_buf_len), + phase=math.pi / 2, + device=device, + ) + + delay_pos = 0 + mod_pos = 0 + + output_waveform_pre_gain_list = [] + waveform = waveform * gain_in + delay_buf = delay_buf * decay + waveform_list = [waveform[:, i] for i in range(waveform.size(1))] + delay_buf_list = [delay_buf[:, i] for i in range(delay_buf.size(1))] + mod_buf_list = [mod_buf[i] for i in range(mod_buf.size(0))] + + for i in range(waveform.shape[-1]): + idx = int((delay_pos + mod_buf_list[mod_pos]) % delay_buf_len) + mod_pos = (mod_pos + 1) % mod_buf_len + delay_pos = (delay_pos + 1) % delay_buf_len + temp = (waveform_list[i]) + (delay_buf_list[idx]) + delay_buf_list[delay_pos] = temp * decay + output_waveform_pre_gain_list.append(temp) + + output_waveform = torch.stack(output_waveform_pre_gain_list, dim=1).to( + dtype=dtype, device=device + ) + output_waveform.mul_(gain_out) + + return output_waveform.clamp(min=-1, max=1).view(actual_shape) + + +def riaa_biquad(waveform: Tensor, sample_rate: int) -> Tensor: + r"""Apply RIAA vinyl playback equalisation. Similar to SoX implementation. + + Args: + waveform (Tensor): audio waveform of dimension of `(..., time)` + sample_rate (int): sampling rate of the waveform, e.g. 44100 (Hz). + Allowed sample rates in Hz : ``44100``,``48000``,``88200``,``96000`` + + Returns: + Tensor: Waveform of dimension of `(..., time)` + + References: + http://sox.sourceforge.net/sox.html + https://www.w3.org/2011/audio/audio-eq-cookbook.html#APF + """ + + if sample_rate == 44100: + zeros = [-0.2014898, 0.9233820] + poles = [0.7083149, 0.9924091] + + elif sample_rate == 48000: + zeros = [-0.1766069, 0.9321590] + poles = [0.7396325, 0.9931330] + + elif sample_rate == 88200: + zeros = [-0.1168735, 0.9648312] + poles = [0.8590646, 0.9964002] + + elif sample_rate == 96000: + zeros = [-0.1141486, 0.9676817] + poles = [0.8699137, 0.9966946] + + else: + raise ValueError("Sample rate must be 44.1k, 48k, 88.2k, or 96k") + + # polynomial coefficients with roots zeros[0] and zeros[1] + b0 = 1.0 + b1 = -(zeros[0] + zeros[1]) + b2 = zeros[0] * zeros[1] + + # polynomial coefficients with roots poles[0] and poles[1] + a0 = 1.0 + a1 = -(poles[0] + poles[1]) + a2 = poles[0] * poles[1] + + # Normalise to 0dB at 1kHz + y = 2 * math.pi * 1000 / sample_rate + b_re = b0 + b1 * math.cos(-y) + b2 * math.cos(-2 * y) + a_re = a0 + a1 * math.cos(-y) + a2 * math.cos(-2 * y) + b_im = b1 * math.sin(-y) + b2 * math.sin(-2 * y) + a_im = a1 * math.sin(-y) + a2 * math.sin(-2 * y) + g = 1 / math.sqrt((b_re ** 2 + b_im ** 2) / (a_re ** 2 + a_im ** 2)) + + b0 *= g + b1 *= g + b2 *= g + + return biquad(waveform, b0, b1, b2, a0, a1, a2) + + +def treble_biquad( + waveform: Tensor, + sample_rate: int, + gain: float, + central_freq: float = 3000, + Q: float = 0.707, +) -> Tensor: + r"""Design a treble tone-control effect. Similar to SoX implementation. + + Args: + waveform (Tensor): audio waveform of dimension of `(..., time)` + sample_rate (int): sampling rate of the waveform, e.g. 44100 (Hz) + gain (float): desired gain at the boost (or attenuation) in dB. + central_freq (float, optional): central frequency (in Hz). (Default: ``3000``) + Q (float, optional): https://en.wikipedia.org/wiki/Q_factor (Default: ``0.707``). + + Returns: + Tensor: Waveform of dimension of `(..., time)` + + References: + http://sox.sourceforge.net/sox.html + https://www.w3.org/2011/audio/audio-eq-cookbook.html#APF + """ + w0 = 2 * math.pi * central_freq / sample_rate + alpha = math.sin(w0) / 2 / Q + A = math.exp(gain / 40 * math.log(10)) + + temp1 = 2 * math.sqrt(A) * alpha + temp2 = (A - 1) * math.cos(w0) + temp3 = (A + 1) * math.cos(w0) + + b0 = A * ((A + 1) + temp2 + temp1) + b1 = -2 * A * ((A - 1) + temp3) + b2 = A * ((A + 1) + temp2 - temp1) + a0 = (A + 1) - temp2 + temp1 + a1 = 2 * ((A - 1) - temp3) + a2 = (A + 1) - temp2 - temp1 + + return biquad(waveform, b0, b1, b2, a0, a1, a2) + + +def _measure( + measure_len_ws: int, + samples: Tensor, + spectrum: Tensor, + noise_spectrum: Tensor, + spectrum_window: Tensor, + spectrum_start: int, + spectrum_end: int, + cepstrum_window: Tensor, + cepstrum_start: int, + cepstrum_end: int, + noise_reduction_amount: float, + measure_smooth_time_mult: float, + noise_up_time_mult: float, + noise_down_time_mult: float, + index_ns: int, + boot_count: int, +) -> float: + + assert spectrum.size()[-1] == noise_spectrum.size()[-1] + + samplesLen_ns = samples.size()[-1] + dft_len_ws = spectrum.size()[-1] + + dftBuf = torch.zeros(dft_len_ws) + + _index_ns = torch.tensor( + [index_ns] + [(index_ns + i) % samplesLen_ns for i in range(1, measure_len_ws)] + ) + dftBuf[:measure_len_ws] = samples[_index_ns] * spectrum_window[:measure_len_ws] + + # memset(c->dftBuf + i, 0, (p->dft_len_ws - i) * sizeof(*c->dftBuf)); + dftBuf[measure_len_ws:dft_len_ws].zero_() + + # lsx_safe_rdft((int)p->dft_len_ws, 1, c->dftBuf); + _dftBuf = torchaudio._internal.fft.rfft(dftBuf) + + # memset(c->dftBuf, 0, p->spectrum_start * sizeof(*c->dftBuf)); + _dftBuf[:spectrum_start].zero_() + + mult: float = ( + boot_count / (1.0 + boot_count) if boot_count >= 0 else measure_smooth_time_mult + ) + + _d = _dftBuf[spectrum_start:spectrum_end].abs() + spectrum[spectrum_start:spectrum_end].mul_(mult).add_(_d * (1 - mult)) + _d = spectrum[spectrum_start:spectrum_end] ** 2 + + _zeros = torch.zeros(spectrum_end - spectrum_start) + _mult = ( + _zeros + if boot_count >= 0 + else torch.where( + _d > noise_spectrum[spectrum_start:spectrum_end], + torch.tensor(noise_up_time_mult), # if + torch.tensor(noise_down_time_mult), # else + ) + ) + + noise_spectrum[spectrum_start:spectrum_end].mul_(_mult).add_(_d * (1 - _mult)) + _d = torch.sqrt( + torch.max( + _zeros, + _d - noise_reduction_amount * noise_spectrum[spectrum_start:spectrum_end], + ) + ) + + _cepstrum_Buf: Tensor = torch.zeros(dft_len_ws >> 1) + _cepstrum_Buf[spectrum_start:spectrum_end] = _d * cepstrum_window + _cepstrum_Buf[spectrum_end:dft_len_ws >> 1].zero_() + + # lsx_safe_rdft((int)p->dft_len_ws >> 1, 1, c->dftBuf); + _cepstrum_Buf = torchaudio._internal.fft.rfft(_cepstrum_Buf) + + result: float = float( + torch.sum(_cepstrum_Buf[cepstrum_start:cepstrum_end].abs().pow(2)) + ) + result = ( + math.log(result / (cepstrum_end - cepstrum_start)) if result > 0 else -math.inf + ) + return max(0, 21 + result) + + +def vad( + waveform: Tensor, + sample_rate: int, + trigger_level: float = 7.0, + trigger_time: float = 0.25, + search_time: float = 1.0, + allowed_gap: float = 0.25, + pre_trigger_time: float = 0.0, + # Fine-tuning parameters + boot_time: float = 0.35, + noise_up_time: float = 0.1, + noise_down_time: float = 0.01, + noise_reduction_amount: float = 1.35, + measure_freq: float = 20.0, + measure_duration: Optional[float] = None, + measure_smooth_time: float = 0.4, + hp_filter_freq: float = 50.0, + lp_filter_freq: float = 6000.0, + hp_lifter_freq: float = 150.0, + lp_lifter_freq: float = 2000.0, +) -> Tensor: + r"""Voice Activity Detector. Similar to SoX implementation. + Attempts to trim silence and quiet background sounds from the ends of recordings of speech. + The algorithm currently uses a simple cepstral power measurement to detect voice, + so may be fooled by other things, especially music. + + The effect can trim only from the front of the audio, + so in order to trim from the back, the reverse effect must also be used. + + Args: + waveform (Tensor): Tensor of audio of dimension `(..., time)` + sample_rate (int): Sample rate of audio signal. + trigger_level (float, optional): The measurement level used to trigger activity detection. + This may need to be cahnged depending on the noise level, signal level, + and other characteristics of the input audio. (Default: 7.0) + trigger_time (float, optional): The time constant (in seconds) + used to help ignore short bursts of sound. (Default: 0.25) + search_time (float, optional): The amount of audio (in seconds) + to search for quieter/shorter bursts of audio to include prior + to the detected trigger point. (Default: 1.0) + allowed_gap (float, optional): The allowed gap (in seconds) between + quiteter/shorter bursts of audio to include prior + to the detected trigger point. (Default: 0.25) + pre_trigger_time (float, optional): The amount of audio (in seconds) to preserve + before the trigger point and any found quieter/shorter bursts. (Default: 0.0) + boot_time (float, optional) The algorithm (internally) uses adaptive noise + estimation/reduction in order to detect the start of the wanted audio. + This option sets the time for the initial noise estimate. (Default: 0.35) + noise_up_time (float, optional) Time constant used by the adaptive noise estimator + for when the noise level is increasing. (Default: 0.1) + noise_down_time (float, optional) Time constant used by the adaptive noise estimator + for when the noise level is decreasing. (Default: 0.01) + noise_reduction_amount (float, optional) Amount of noise reduction to use in + the detection algorithm (e.g. 0, 0.5, ...). (Default: 1.35) + measure_freq (float, optional) Frequency of the algorithmโ€™s + processing/measurements. (Default: 20.0) + measure_duration: (float, optional) Measurement duration. + (Default: Twice the measurement period; i.e. with overlap.) + measure_smooth_time (float, optional) Time constant used to smooth + spectral measurements. (Default: 0.4) + hp_filter_freq (float, optional) "Brick-wall" frequency of high-pass filter applied + at the input to the detector algorithm. (Default: 50.0) + lp_filter_freq (float, optional) "Brick-wall" frequency of low-pass filter applied + at the input to the detector algorithm. (Default: 6000.0) + hp_lifter_freq (float, optional) "Brick-wall" frequency of high-pass lifter used + in the detector algorithm. (Default: 150.0) + lp_lifter_freq (float, optional) "Brick-wall" frequency of low-pass lifter used + in the detector algorithm. (Default: 2000.0) + + Returns: + Tensor: Tensor of audio of dimension (..., time). + + References: + http://sox.sourceforge.net/sox.html + """ + + measure_duration: float = ( + 2.0 / measure_freq if measure_duration is None else measure_duration + ) + + measure_len_ws = int(sample_rate * measure_duration + 0.5) + measure_len_ns = measure_len_ws + # for (dft_len_ws = 16; dft_len_ws < measure_len_ws; dft_len_ws <<= 1); + dft_len_ws = 16 + while dft_len_ws < measure_len_ws: + dft_len_ws *= 2 + + measure_period_ns = int(sample_rate / measure_freq + 0.5) + measures_len = math.ceil(search_time * measure_freq) + search_pre_trigger_len_ns = measures_len * measure_period_ns + gap_len = int(allowed_gap * measure_freq + 0.5) + + fixed_pre_trigger_len_ns = int(pre_trigger_time * sample_rate + 0.5) + samplesLen_ns = ( + fixed_pre_trigger_len_ns + search_pre_trigger_len_ns + measure_len_ns + ) + + spectrum_window = torch.zeros(measure_len_ws) + for i in range(measure_len_ws): + # sox.h:741 define SOX_SAMPLE_MIN (sox_sample_t)SOX_INT_MIN(32) + spectrum_window[i] = 2.0 / math.sqrt(float(measure_len_ws)) + # lsx_apply_hann(spectrum_window, (int)measure_len_ws); + spectrum_window *= torch.hann_window(measure_len_ws, dtype=torch.float) + + spectrum_start: int = int(hp_filter_freq / sample_rate * dft_len_ws + 0.5) + spectrum_start: int = max(spectrum_start, 1) + spectrum_end: int = int(lp_filter_freq / sample_rate * dft_len_ws + 0.5) + spectrum_end: int = min(spectrum_end, dft_len_ws // 2) + + cepstrum_window = torch.zeros(spectrum_end - spectrum_start) + for i in range(spectrum_end - spectrum_start): + cepstrum_window[i] = 2.0 / math.sqrt(float(spectrum_end) - spectrum_start) + # lsx_apply_hann(cepstrum_window,(int)(spectrum_end - spectrum_start)); + cepstrum_window *= torch.hann_window( + spectrum_end - spectrum_start, dtype=torch.float + ) + + cepstrum_start = math.ceil(sample_rate * 0.5 / lp_lifter_freq) + cepstrum_end = math.floor(sample_rate * 0.5 / hp_lifter_freq) + cepstrum_end = min(cepstrum_end, dft_len_ws // 4) + + assert cepstrum_end > cepstrum_start + + noise_up_time_mult = math.exp(-1.0 / (noise_up_time * measure_freq)) + noise_down_time_mult = math.exp(-1.0 / (noise_down_time * measure_freq)) + measure_smooth_time_mult = math.exp(-1.0 / (measure_smooth_time * measure_freq)) + trigger_meas_time_mult = math.exp(-1.0 / (trigger_time * measure_freq)) + + boot_count_max = int(boot_time * measure_freq - 0.5) + measure_timer_ns = measure_len_ns + boot_count = measures_index = flushedLen_ns = samplesIndex_ns = 0 + + # pack batch + shape = waveform.size() + waveform = waveform.view(-1, shape[-1]) + + n_channels, ilen = waveform.size() + + mean_meas = torch.zeros(n_channels) + samples = torch.zeros(n_channels, samplesLen_ns) + spectrum = torch.zeros(n_channels, dft_len_ws) + noise_spectrum = torch.zeros(n_channels, dft_len_ws) + measures = torch.zeros(n_channels, measures_len) + + has_triggered: bool = False + num_measures_to_flush: int = 0 + pos: int = 0 + + while pos < ilen and not has_triggered: + measure_timer_ns -= 1 + for i in range(n_channels): + samples[i, samplesIndex_ns] = waveform[i, pos] + # if (!p->measure_timer_ns) { + if measure_timer_ns == 0: + index_ns: int = ( + samplesIndex_ns + samplesLen_ns - measure_len_ns + ) % samplesLen_ns + meas: float = _measure( + measure_len_ws=measure_len_ws, + samples=samples[i], + spectrum=spectrum[i], + noise_spectrum=noise_spectrum[i], + spectrum_window=spectrum_window, + spectrum_start=spectrum_start, + spectrum_end=spectrum_end, + cepstrum_window=cepstrum_window, + cepstrum_start=cepstrum_start, + cepstrum_end=cepstrum_end, + noise_reduction_amount=noise_reduction_amount, + measure_smooth_time_mult=measure_smooth_time_mult, + noise_up_time_mult=noise_up_time_mult, + noise_down_time_mult=noise_down_time_mult, + index_ns=index_ns, + boot_count=boot_count, + ) + measures[i, measures_index] = meas + mean_meas[i] = mean_meas[i] * trigger_meas_time_mult + meas * ( + 1.0 - trigger_meas_time_mult + ) + + has_triggered = has_triggered or (mean_meas[i] >= trigger_level) + if has_triggered: + n: int = measures_len + k: int = measures_index + jTrigger: int = n + jZero: int = n + j: int = 0 + + for j in range(n): + if (measures[i, k] >= trigger_level) and ( + j <= jTrigger + gap_len + ): + jZero = jTrigger = j + elif (measures[i, k] == 0) and (jTrigger >= jZero): + jZero = j + k = (k + n - 1) % n + j = min(j, jZero) + # num_measures_to_flush = range_limit(j, num_measures_to_flush, n); + num_measures_to_flush = min(max(num_measures_to_flush, j), n) + # end if has_triggered + # end if (measure_timer_ns == 0): + # end for + samplesIndex_ns += 1 + pos += 1 + # end while + if samplesIndex_ns == samplesLen_ns: + samplesIndex_ns = 0 + if measure_timer_ns == 0: + measure_timer_ns = measure_period_ns + measures_index += 1 + measures_index = measures_index % measures_len + if boot_count >= 0: + boot_count = -1 if boot_count == boot_count_max else boot_count + 1 + + if has_triggered: + flushedLen_ns = (measures_len - num_measures_to_flush) * measure_period_ns + samplesIndex_ns = (samplesIndex_ns + flushedLen_ns) % samplesLen_ns + + res = waveform[:, pos - samplesLen_ns + flushedLen_ns:] + # unpack batch + return res.view(shape[:-1] + res.shape[-1:]) diff --git a/torchaudio/functional/functional.py b/torchaudio/functional/functional.py new file mode 100644 index 0000000000..b967904f2a --- /dev/null +++ b/torchaudio/functional/functional.py @@ -0,0 +1,912 @@ +# -*- coding: utf-8 -*- + +import math +from typing import Optional, Tuple +import warnings + +import torch +from torch import Tensor + +__all__ = [ + "spectrogram", + "griffinlim", + "amplitude_to_DB", + "DB_to_amplitude", + "compute_deltas", + "create_fb_matrix", + "create_dct", + "compute_deltas", + "detect_pitch_frequency", + "DB_to_amplitude", + "mu_law_encoding", + "mu_law_decoding", + "complex_norm", + "angle", + "magphase", + "phase_vocoder", + "detect_pitch_frequency", + 'mask_along_axis', + 'mask_along_axis_iid', + 'sliding_window_cmn', +] + + +def spectrogram( + waveform: Tensor, + pad: int, + window: Tensor, + n_fft: int, + hop_length: int, + win_length: int, + power: Optional[float], + normalized: bool +) -> Tensor: + r"""Create a spectrogram or a batch of spectrograms from a raw audio signal. + The spectrogram can be either magnitude-only or complex. + + Args: + waveform (Tensor): Tensor of audio of dimension (..., time) + pad (int): Two sided padding of signal + window (Tensor): Window tensor that is applied/multiplied to each frame/window + n_fft (int): Size of FFT + hop_length (int): Length of hop between STFT windows + win_length (int): Window size + power (float or None): Exponent for the magnitude spectrogram, + (must be > 0) e.g., 1 for energy, 2 for power, etc. + If None, then the complex spectrum is returned instead. + normalized (bool): Whether to normalize by magnitude after stft + + Returns: + Tensor: Dimension (..., freq, time), freq is + ``n_fft // 2 + 1`` and ``n_fft`` is the number of + Fourier bins, and time is the number of window hops (n_frame). + """ + + if pad > 0: + # TODO add "with torch.no_grad():" back when JIT supports it + waveform = torch.nn.functional.pad(waveform, (pad, pad), "constant") + + # pack batch + shape = waveform.size() + waveform = waveform.reshape(-1, shape[-1]) + + # default values are consistent with librosa.core.spectrum._spectrogram + spec_f = torch.stft( + waveform, n_fft, hop_length, win_length, window, True, "reflect", False, True + ) + + # unpack batch + spec_f = spec_f.reshape(shape[:-1] + spec_f.shape[-3:]) + + if normalized: + spec_f /= window.pow(2.).sum().sqrt() + if power is not None: + spec_f = complex_norm(spec_f, power=power) + + return spec_f + + +def griffinlim( + specgram: Tensor, + window: Tensor, + n_fft: int, + hop_length: int, + win_length: int, + power: float, + normalized: bool, + n_iter: int, + momentum: float, + length: Optional[int], + rand_init: bool +) -> Tensor: + r"""Compute waveform from a linear scale magnitude spectrogram using the Griffin-Lim transformation. + Implementation ported from `librosa`. + + .. [1] McFee, Brian, Colin Raffel, Dawen Liang, Daniel PW Ellis, Matt McVicar, Eric Battenberg, and Oriol Nieto. + "librosa: Audio and music signal analysis in python." + In Proceedings of the 14th python in science conference, pp. 18-25. 2015. + + .. [2] Perraudin, N., Balazs, P., & Sรธndergaard, P. L. + "A fast Griffin-Lim algorithm," + IEEE Workshop on Applications of Signal Processing to Audio and Acoustics (pp. 1-4), + Oct. 2013. + + .. [3] D. W. Griffin and J. S. Lim, + "Signal estimation from modified short-time Fourier transform," + IEEE Trans. ASSP, vol.32, no.2, pp.236โ€“243, Apr. 1984. + + Args: + specgram (Tensor): A magnitude-only STFT spectrogram of dimension (..., freq, frames) + where freq is ``n_fft // 2 + 1``. + window (Tensor): Window tensor that is applied/multiplied to each frame/window + n_fft (int): Size of FFT, creates ``n_fft // 2 + 1`` bins + hop_length (int): Length of hop between STFT windows. ( + Default: ``win_length // 2``) + win_length (int): Window size. (Default: ``n_fft``) + power (float): Exponent for the magnitude spectrogram, + (must be > 0) e.g., 1 for energy, 2 for power, etc. + normalized (bool): Whether to normalize by magnitude after stft. + n_iter (int): Number of iteration for phase recovery process. + momentum (float): The momentum parameter for fast Griffin-Lim. + Setting this to 0 recovers the original Griffin-Lim method. + Values near 1 can lead to faster convergence, but above 1 may not converge. + length (int or None): Array length of the expected output. + rand_init (bool): Initializes phase randomly if True, to zero otherwise. + + Returns: + torch.Tensor: waveform of (..., time), where time equals the ``length`` parameter if given. + """ + assert momentum < 1, 'momentum={} > 1 can be unstable'.format(momentum) + assert momentum >= 0, 'momentum={} < 0'.format(momentum) + + # pack batch + shape = specgram.size() + specgram = specgram.reshape([-1] + list(shape[-2:])) + + specgram = specgram.pow(1 / power) + + # randomly initialize the phase + batch, freq, frames = specgram.size() + if rand_init: + angles = 2 * math.pi * torch.rand(batch, freq, frames) + else: + angles = torch.zeros(batch, freq, frames) + angles = torch.stack([angles.cos(), angles.sin()], dim=-1) \ + .to(dtype=specgram.dtype, device=specgram.device) + specgram = specgram.unsqueeze(-1).expand_as(angles) + + # And initialize the previous iterate to 0 + rebuilt = torch.tensor(0.) + + for _ in range(n_iter): + # Store the previous iterate + tprev = rebuilt + + # Invert with our current estimate of the phases + inverse = torch.istft(specgram * angles, + n_fft=n_fft, + hop_length=hop_length, + win_length=win_length, + window=window, + length=length).float() + + # Rebuild the spectrogram + rebuilt = torch.stft(inverse, n_fft, hop_length, win_length, window, + True, 'reflect', False, True) + + # Update our phase estimates + angles = rebuilt + if momentum: + angles = angles - tprev.mul_(momentum / (1 + momentum)) + angles = angles.div(complex_norm(angles).add(1e-16).unsqueeze(-1).expand_as(angles)) + + # Return the final phase estimates + waveform = torch.istft(specgram * angles, + n_fft=n_fft, + hop_length=hop_length, + win_length=win_length, + window=window, + length=length) + + # unpack batch + waveform = waveform.reshape(shape[:-2] + waveform.shape[-1:]) + + return waveform + + +def amplitude_to_DB( + x: Tensor, + multiplier: float, + amin: float, + db_multiplier: float, + top_db: Optional[float] = None +) -> Tensor: + r"""Turn a tensor from the power/amplitude scale to the decibel scale. + + This output depends on the maximum value in the input tensor, and so + may return different values for an audio clip split into snippets vs. a + a full clip. + + Args: + x (Tensor): Input tensor before being converted to decibel scale + multiplier (float): Use 10. for power and 20. for amplitude + amin (float): Number to clamp ``x`` + db_multiplier (float): Log10(max(reference value and amin)) + top_db (float or None, optional): Minimum negative cut-off in decibels. A reasonable number + is 80. (Default: ``None``) + + Returns: + Tensor: Output tensor in decibel scale + """ + x_db = multiplier * torch.log10(torch.clamp(x, min=amin)) + x_db -= multiplier * db_multiplier + + if top_db is not None: + x_db = x_db.clamp(min=x_db.max().item() - top_db) + + return x_db + + +def DB_to_amplitude( + x: Tensor, + ref: float, + power: float +) -> Tensor: + r"""Turn a tensor from the decibel scale to the power/amplitude scale. + + Args: + x (Tensor): Input tensor before being converted to power/amplitude scale. + ref (float): Reference which the output will be scaled by. + power (float): If power equals 1, will compute DB to power. If 0.5, will compute DB to amplitude. + + Returns: + Tensor: Output tensor in power/amplitude scale. + """ + return ref * torch.pow(torch.pow(10.0, 0.1 * x), power) + + +def create_fb_matrix( + n_freqs: int, + f_min: float, + f_max: float, + n_mels: int, + sample_rate: int, + norm: Optional[str] = None +) -> Tensor: + r"""Create a frequency bin conversion matrix. + + Args: + n_freqs (int): Number of frequencies to highlight/apply + f_min (float): Minimum frequency (Hz) + f_max (float): Maximum frequency (Hz) + n_mels (int): Number of mel filterbanks + sample_rate (int): Sample rate of the audio waveform + norm (Optional[str]): If 'slaney', divide the triangular mel weights by the width of the mel band + (area normalization). (Default: ``None``) + + Returns: + Tensor: Triangular filter banks (fb matrix) of size (``n_freqs``, ``n_mels``) + meaning number of frequencies to highlight/apply to x the number of filterbanks. + Each column is a filterbank so that assuming there is a matrix A of + size (..., ``n_freqs``), the applied result would be + ``A * create_fb_matrix(A.size(-1), ...)``. + """ + + if norm is not None and norm != "slaney": + raise ValueError("norm must be one of None or 'slaney'") + + # freq bins + # Equivalent filterbank construction by Librosa + all_freqs = torch.linspace(0, sample_rate // 2, n_freqs) + + # calculate mel freq bins + # hertz to mel(f) is 2595. * math.log10(1. + (f / 700.)) + m_min = 2595.0 * math.log10(1.0 + (f_min / 700.0)) + m_max = 2595.0 * math.log10(1.0 + (f_max / 700.0)) + m_pts = torch.linspace(m_min, m_max, n_mels + 2) + # mel to hertz(mel) is 700. * (10**(mel / 2595.) - 1.) + f_pts = 700.0 * (10 ** (m_pts / 2595.0) - 1.0) + # calculate the difference between each mel point and each stft freq point in hertz + f_diff = f_pts[1:] - f_pts[:-1] # (n_mels + 1) + slopes = f_pts.unsqueeze(0) - all_freqs.unsqueeze(1) # (n_freqs, n_mels + 2) + # create overlapping triangles + zero = torch.zeros(1) + down_slopes = (-1.0 * slopes[:, :-2]) / f_diff[:-1] # (n_freqs, n_mels) + up_slopes = slopes[:, 2:] / f_diff[1:] # (n_freqs, n_mels) + fb = torch.max(zero, torch.min(down_slopes, up_slopes)) + + if norm is not None and norm == "slaney": + # Slaney-style mel is scaled to be approx constant energy per channel + enorm = 2.0 / (f_pts[2:n_mels + 2] - f_pts[:n_mels]) + fb *= enorm.unsqueeze(0) + + if (fb.max(dim=0).values == 0.).any(): + warnings.warn( + "At least one mel filterbank has all zero values. " + f"The value for `n_mels` ({n_mels}) may be set too high. " + f"Or, the value for `n_freqs` ({n_freqs}) may be set too low." + ) + + return fb + + +def create_dct( + n_mfcc: int, + n_mels: int, + norm: Optional[str] +) -> Tensor: + r"""Create a DCT transformation matrix with shape (``n_mels``, ``n_mfcc``), + normalized depending on norm. + + Args: + n_mfcc (int): Number of mfc coefficients to retain + n_mels (int): Number of mel filterbanks + norm (str or None): Norm to use (either 'ortho' or None) + + Returns: + Tensor: The transformation matrix, to be right-multiplied to + row-wise data of size (``n_mels``, ``n_mfcc``). + """ + # http://en.wikipedia.org/wiki/Discrete_cosine_transform#DCT-II + n = torch.arange(float(n_mels)) + k = torch.arange(float(n_mfcc)).unsqueeze(1) + dct = torch.cos(math.pi / float(n_mels) * (n + 0.5) * k) # size (n_mfcc, n_mels) + if norm is None: + dct *= 2.0 + else: + assert norm == "ortho" + dct[0] *= 1.0 / math.sqrt(2.0) + dct *= math.sqrt(2.0 / float(n_mels)) + return dct.t() + + +def mu_law_encoding( + x: Tensor, + quantization_channels: int +) -> Tensor: + r"""Encode signal based on mu-law companding. For more info see the + `Wikipedia Entry `_ + + This algorithm assumes the signal has been scaled to between -1 and 1 and + returns a signal encoded with values from 0 to quantization_channels - 1. + + Args: + x (Tensor): Input tensor + quantization_channels (int): Number of channels + + Returns: + Tensor: Input after mu-law encoding + """ + mu = quantization_channels - 1.0 + if not x.is_floating_point(): + x = x.to(torch.float) + mu = torch.tensor(mu, dtype=x.dtype) + x_mu = torch.sign(x) * torch.log1p(mu * torch.abs(x)) / torch.log1p(mu) + x_mu = ((x_mu + 1) / 2 * mu + 0.5).to(torch.int64) + return x_mu + + +def mu_law_decoding( + x_mu: Tensor, + quantization_channels: int +) -> Tensor: + r"""Decode mu-law encoded signal. For more info see the + `Wikipedia Entry `_ + + This expects an input with values between 0 and quantization_channels - 1 + and returns a signal scaled between -1 and 1. + + Args: + x_mu (Tensor): Input tensor + quantization_channels (int): Number of channels + + Returns: + Tensor: Input after mu-law decoding + """ + mu = quantization_channels - 1.0 + if not x_mu.is_floating_point(): + x_mu = x_mu.to(torch.float) + mu = torch.tensor(mu, dtype=x_mu.dtype) + x = ((x_mu) / mu) * 2 - 1.0 + x = torch.sign(x) * (torch.exp(torch.abs(x) * torch.log1p(mu)) - 1.0) / mu + return x + + +def complex_norm( + complex_tensor: Tensor, + power: float = 1.0 +) -> Tensor: + r"""Compute the norm of complex tensor input. + + Args: + complex_tensor (Tensor): Tensor shape of `(..., complex=2)` + power (float): Power of the norm. (Default: `1.0`). + + Returns: + Tensor: Power of the normed input tensor. Shape of `(..., )` + """ + + # Replace by torch.norm once issue is fixed + # https://github.com/pytorch/pytorch/issues/34279 + return complex_tensor.pow(2.).sum(-1).pow(0.5 * power) + + +def angle( + complex_tensor: Tensor +) -> Tensor: + r"""Compute the angle of complex tensor input. + + Args: + complex_tensor (Tensor): Tensor shape of `(..., complex=2)` + + Return: + Tensor: Angle of a complex tensor. Shape of `(..., )` + """ + return torch.atan2(complex_tensor[..., 1], complex_tensor[..., 0]) + + +def magphase( + complex_tensor: Tensor, + power: float = 1.0 +) -> Tuple[Tensor, Tensor]: + r"""Separate a complex-valued spectrogram with shape `(..., 2)` into its magnitude and phase. + + Args: + complex_tensor (Tensor): Tensor shape of `(..., complex=2)` + power (float): Power of the norm. (Default: `1.0`) + + Returns: + (Tensor, Tensor): The magnitude and phase of the complex tensor + """ + mag = complex_norm(complex_tensor, power) + phase = angle(complex_tensor) + return mag, phase + + +def phase_vocoder( + complex_specgrams: Tensor, + rate: float, + phase_advance: Tensor +) -> Tensor: + r"""Given a STFT tensor, speed up in time without modifying pitch by a + factor of ``rate``. + + Args: + complex_specgrams (Tensor): Dimension of `(..., freq, time, complex=2)` + rate (float): Speed-up factor + phase_advance (Tensor): Expected phase advance in each bin. Dimension of (freq, 1) + + Returns: + Tensor: Complex Specgrams Stretch with dimension of `(..., freq, ceil(time/rate), complex=2)` + + Example + >>> freq, hop_length = 1025, 512 + >>> # (channel, freq, time, complex=2) + >>> complex_specgrams = torch.randn(2, freq, 300, 2) + >>> rate = 1.3 # Speed up by 30% + >>> phase_advance = torch.linspace( + >>> 0, math.pi * hop_length, freq)[..., None] + >>> x = phase_vocoder(complex_specgrams, rate, phase_advance) + >>> x.shape # with 231 == ceil(300 / 1.3) + torch.Size([2, 1025, 231, 2]) + """ + + # pack batch + shape = complex_specgrams.size() + complex_specgrams = complex_specgrams.reshape([-1] + list(shape[-3:])) + + time_steps = torch.arange(0, + complex_specgrams.size(-2), + rate, + device=complex_specgrams.device, + dtype=complex_specgrams.dtype) + + alphas = time_steps % 1.0 + phase_0 = angle(complex_specgrams[..., :1, :]) + + # Time Padding + complex_specgrams = torch.nn.functional.pad(complex_specgrams, [0, 0, 0, 2]) + + # (new_bins, freq, 2) + complex_specgrams_0 = complex_specgrams.index_select(-2, time_steps.long()) + complex_specgrams_1 = complex_specgrams.index_select(-2, (time_steps + 1).long()) + + angle_0 = angle(complex_specgrams_0) + angle_1 = angle(complex_specgrams_1) + + norm_0 = torch.norm(complex_specgrams_0, p=2, dim=-1) + norm_1 = torch.norm(complex_specgrams_1, p=2, dim=-1) + + phase = angle_1 - angle_0 - phase_advance + phase = phase - 2 * math.pi * torch.round(phase / (2 * math.pi)) + + # Compute Phase Accum + phase = phase + phase_advance + phase = torch.cat([phase_0, phase[..., :-1]], dim=-1) + phase_acc = torch.cumsum(phase, -1) + + mag = alphas * norm_1 + (1 - alphas) * norm_0 + + real_stretch = mag * torch.cos(phase_acc) + imag_stretch = mag * torch.sin(phase_acc) + + complex_specgrams_stretch = torch.stack([real_stretch, imag_stretch], dim=-1) + + # unpack batch + complex_specgrams_stretch = complex_specgrams_stretch.reshape(shape[:-3] + complex_specgrams_stretch.shape[1:]) + + return complex_specgrams_stretch + + +def mask_along_axis_iid( + specgrams: Tensor, + mask_param: int, + mask_value: float, + axis: int +) -> Tensor: + r""" + Apply a mask along ``axis``. Mask will be applied from indices ``[v_0, v_0 + v)``, where + ``v`` is sampled from ``uniform(0, mask_param)``, and ``v_0`` from ``uniform(0, max_v - v)``. + + Args: + specgrams (Tensor): Real spectrograms (batch, channel, freq, time) + mask_param (int): Number of columns to be masked will be uniformly sampled from [0, mask_param] + mask_value (float): Value to assign to the masked columns + axis (int): Axis to apply masking on (2 -> frequency, 3 -> time) + + Returns: + Tensor: Masked spectrograms of dimensions (batch, channel, freq, time) + """ + + if axis != 2 and axis != 3: + raise ValueError('Only Frequency and Time masking are supported') + + device = specgrams.device + dtype = specgrams.dtype + + value = torch.rand(specgrams.shape[:2], device=device, dtype=dtype) * mask_param + min_value = torch.rand(specgrams.shape[:2], device=device, dtype=dtype) * (specgrams.size(axis) - value) + + # Create broadcastable mask + mask_start = min_value[..., None, None] + mask_end = (min_value + value)[..., None, None] + mask = torch.arange(0, specgrams.size(axis), device=device, dtype=dtype) + + # Per batch example masking + specgrams = specgrams.transpose(axis, -1) + specgrams.masked_fill_((mask >= mask_start) & (mask < mask_end), mask_value) + specgrams = specgrams.transpose(axis, -1) + + return specgrams + + +def mask_along_axis( + specgram: Tensor, + mask_param: int, + mask_value: float, + axis: int +) -> Tensor: + r""" + Apply a mask along ``axis``. Mask will be applied from indices ``[v_0, v_0 + v)``, where + ``v`` is sampled from ``uniform(0, mask_param)``, and ``v_0`` from ``uniform(0, max_v - v)``. + All examples will have the same mask interval. + + Args: + specgram (Tensor): Real spectrogram (channel, freq, time) + mask_param (int): Number of columns to be masked will be uniformly sampled from [0, mask_param] + mask_value (float): Value to assign to the masked columns + axis (int): Axis to apply masking on (1 -> frequency, 2 -> time) + + Returns: + Tensor: Masked spectrogram of dimensions (channel, freq, time) + """ + + # pack batch + shape = specgram.size() + specgram = specgram.reshape([-1] + list(shape[-2:])) + + value = torch.rand(1) * mask_param + min_value = torch.rand(1) * (specgram.size(axis) - value) + + mask_start = (min_value.long()).squeeze() + mask_end = (min_value.long() + value.long()).squeeze() + + assert mask_end - mask_start < mask_param + if axis == 1: + specgram[:, mask_start:mask_end] = mask_value + elif axis == 2: + specgram[:, :, mask_start:mask_end] = mask_value + else: + raise ValueError('Only Frequency and Time masking are supported') + + # unpack batch + specgram = specgram.reshape(shape[:-2] + specgram.shape[-2:]) + + return specgram + + +def compute_deltas( + specgram: Tensor, + win_length: int = 5, + mode: str = "replicate" +) -> Tensor: + r"""Compute delta coefficients of a tensor, usually a spectrogram: + + .. math:: + d_t = \frac{\sum_{n=1}^{\text{N}} n (c_{t+n} - c_{t-n})}{2 \sum_{n=1}^{\text{N}} n^2} + + where :math:`d_t` is the deltas at time :math:`t`, + :math:`c_t` is the spectrogram coeffcients at time :math:`t`, + :math:`N` is ``(win_length-1)//2``. + + Args: + specgram (Tensor): Tensor of audio of dimension (..., freq, time) + win_length (int, optional): The window length used for computing delta (Default: ``5``) + mode (str, optional): Mode parameter passed to padding (Default: ``"replicate"``) + + Returns: + Tensor: Tensor of deltas of dimension (..., freq, time) + + Example + >>> specgram = torch.randn(1, 40, 1000) + >>> delta = compute_deltas(specgram) + >>> delta2 = compute_deltas(delta) + """ + device = specgram.device + dtype = specgram.dtype + + # pack batch + shape = specgram.size() + specgram = specgram.reshape(1, -1, shape[-1]) + + assert win_length >= 3 + + n = (win_length - 1) // 2 + + # twice sum of integer squared + denom = n * (n + 1) * (2 * n + 1) / 3 + + specgram = torch.nn.functional.pad(specgram, (n, n), mode=mode) + + kernel = torch.arange(-n, n + 1, 1, device=device, dtype=dtype).repeat(specgram.shape[1], 1, 1) + + output = torch.nn.functional.conv1d(specgram, kernel, groups=specgram.shape[1]) / denom + + # unpack batch + output = output.reshape(shape) + + return output + + +def _compute_nccf( + waveform: Tensor, + sample_rate: int, + frame_time: float, + freq_low: int +) -> Tensor: + r""" + Compute Normalized Cross-Correlation Function (NCCF). + + .. math:: + \phi_i(m) = \frac{\sum_{n=b_i}^{b_i + N-1} w(n) w(m+n)}{\sqrt{E(b_i) E(m+b_i)}}, + + where + :math:`\phi_i(m)` is the NCCF at frame :math:`i` with lag :math:`m`, + :math:`w` is the waveform, + :math:`N` is the length of a frame, + :math:`b_i` is the beginning of frame :math:`i`, + :math:`E(j)` is the energy :math:`\sum_{n=j}^{j+N-1} w^2(n)`. + """ + + EPSILON = 10 ** (-9) + + # Number of lags to check + lags = int(math.ceil(sample_rate / freq_low)) + + frame_size = int(math.ceil(sample_rate * frame_time)) + + waveform_length = waveform.size()[-1] + num_of_frames = int(math.ceil(waveform_length / frame_size)) + + p = lags + num_of_frames * frame_size - waveform_length + waveform = torch.nn.functional.pad(waveform, (0, p)) + + # Compute lags + output_lag = [] + for lag in range(1, lags + 1): + s1 = waveform[..., :-lag].unfold(-1, frame_size, frame_size)[..., :num_of_frames, :] + s2 = waveform[..., lag:].unfold(-1, frame_size, frame_size)[..., :num_of_frames, :] + + output_frames = ( + (s1 * s2).sum(-1) + / (EPSILON + torch.norm(s1, p=2, dim=-1)).pow(2) + / (EPSILON + torch.norm(s2, p=2, dim=-1)).pow(2) + ) + + output_lag.append(output_frames.unsqueeze(-1)) + + nccf = torch.cat(output_lag, -1) + + return nccf + + +def _combine_max( + a: Tuple[Tensor, Tensor], + b: Tuple[Tensor, Tensor], + thresh: float = 0.99 +) -> Tuple[Tensor, Tensor]: + """ + Take value from first if bigger than a multiplicative factor of the second, elementwise. + """ + mask = (a[0] > thresh * b[0]) + values = mask * a[0] + ~mask * b[0] + indices = mask * a[1] + ~mask * b[1] + return values, indices + + +def _find_max_per_frame( + nccf: Tensor, + sample_rate: int, + freq_high: int +) -> Tensor: + r""" + For each frame, take the highest value of NCCF, + apply centered median smoothing, and convert to frequency. + + Note: If the max among all the lags is very close + to the first half of lags, then the latter is taken. + """ + + lag_min = int(math.ceil(sample_rate / freq_high)) + + # Find near enough max that is smallest + + best = torch.max(nccf[..., lag_min:], -1) + + half_size = nccf.shape[-1] // 2 + half = torch.max(nccf[..., lag_min:half_size], -1) + + best = _combine_max(half, best) + indices = best[1] + + # Add back minimal lag + indices += lag_min + # Add 1 empirical calibration offset + indices += 1 + + return indices + + +def _median_smoothing( + indices: Tensor, + win_length: int +) -> Tensor: + r""" + Apply median smoothing to the 1D tensor over the given window. + """ + + # Centered windowed + pad_length = (win_length - 1) // 2 + + # "replicate" padding in any dimension + indices = torch.nn.functional.pad( + indices, (pad_length, 0), mode="constant", value=0. + ) + + indices[..., :pad_length] = torch.cat(pad_length * [indices[..., pad_length].unsqueeze(-1)], dim=-1) + roll = indices.unfold(-1, win_length, 1) + + values, _ = torch.median(roll, -1) + return values + + +def detect_pitch_frequency( + waveform: Tensor, + sample_rate: int, + frame_time: float = 10 ** (-2), + win_length: int = 30, + freq_low: int = 85, + freq_high: int = 3400, +) -> Tensor: + r"""Detect pitch frequency. + + It is implemented using normalized cross-correlation function and median smoothing. + + Args: + waveform (Tensor): Tensor of audio of dimension (..., freq, time) + sample_rate (int): The sample rate of the waveform (Hz) + frame_time (float, optional): Duration of a frame (Default: ``10 ** (-2)``). + win_length (int, optional): The window length for median smoothing (in number of frames) (Default: ``30``). + freq_low (int, optional): Lowest frequency that can be detected (Hz) (Default: ``85``). + freq_high (int, optional): Highest frequency that can be detected (Hz) (Default: ``3400``). + + Returns: + Tensor: Tensor of freq of dimension (..., frame) + """ + # pack batch + shape = list(waveform.size()) + waveform = waveform.reshape([-1] + shape[-1:]) + + nccf = _compute_nccf(waveform, sample_rate, frame_time, freq_low) + indices = _find_max_per_frame(nccf, sample_rate, freq_high) + indices = _median_smoothing(indices, win_length) + + # Convert indices to frequency + EPSILON = 10 ** (-9) + freq = sample_rate / (EPSILON + indices.to(torch.float)) + + # unpack batch + freq = freq.reshape(shape[:-1] + list(freq.shape[-1:])) + + return freq + + +def sliding_window_cmn( + waveform: Tensor, + cmn_window: int = 600, + min_cmn_window: int = 100, + center: bool = False, + norm_vars: bool = False, +) -> Tensor: + r""" + Apply sliding-window cepstral mean (and optionally variance) normalization per utterance. + + Args: + waveform (Tensor): Tensor of audio of dimension (..., freq, time) + cmn_window (int, optional): Window in frames for running average CMN computation (int, default = 600) + min_cmn_window (int, optional): Minimum CMN window used at start of decoding (adds latency only at start). + Only applicable if center == false, ignored if center==true (int, default = 100) + center (bool, optional): If true, use a window centered on the current frame + (to the extent possible, modulo end effects). If false, window is to the left. (bool, default = false) + norm_vars (bool, optional): If true, normalize variance to one. (bool, default = false) + + Returns: + Tensor: Tensor of freq of dimension (..., frame) + """ + input_shape = waveform.shape + num_frames, num_feats = input_shape[-2:] + waveform = waveform.view(-1, num_frames, num_feats) + num_channels = waveform.shape[0] + + dtype = waveform.dtype + device = waveform.device + last_window_start = last_window_end = -1 + cur_sum = torch.zeros(num_channels, num_feats, dtype=dtype, device=device) + cur_sumsq = torch.zeros(num_channels, num_feats, dtype=dtype, device=device) + cmn_waveform = torch.zeros( + num_channels, num_frames, num_feats, dtype=dtype, device=device) + for t in range(num_frames): + window_start = 0 + window_end = 0 + if center: + window_start = t - cmn_window // 2 + window_end = window_start + cmn_window + else: + window_start = t - cmn_window + window_end = t + 1 + if window_start < 0: + window_end -= window_start + window_start = 0 + if not center: + if window_end > t: + window_end = max(t + 1, min_cmn_window) + if window_end > num_frames: + window_start -= (window_end - num_frames) + window_end = num_frames + if window_start < 0: + window_start = 0 + if last_window_start == -1: + input_part = waveform[:, window_start: window_end - window_start, :] + cur_sum += torch.sum(input_part, 1) + if norm_vars: + cur_sumsq += torch.cumsum(input_part ** 2, 1)[:, -1, :] + else: + if window_start > last_window_start: + frame_to_remove = waveform[:, last_window_start, :] + cur_sum -= frame_to_remove + if norm_vars: + cur_sumsq -= (frame_to_remove ** 2) + if window_end > last_window_end: + frame_to_add = waveform[:, last_window_end, :] + cur_sum += frame_to_add + if norm_vars: + cur_sumsq += (frame_to_add ** 2) + window_frames = window_end - window_start + last_window_start = window_start + last_window_end = window_end + cmn_waveform[:, t, :] = waveform[:, t, :] - cur_sum / window_frames + if norm_vars: + if window_frames == 1: + cmn_waveform[:, t, :] = torch.zeros( + num_channels, num_feats, dtype=dtype, device=device) + else: + variance = cur_sumsq + variance = variance / window_frames + variance -= ((cur_sum ** 2) / (window_frames ** 2)) + variance = torch.pow(variance, -0.5) + cmn_waveform[:, t, :] *= variance + + cmn_waveform = cmn_waveform.view(input_shape[:-2] + (num_frames, num_feats)) + if len(input_shape) == 2: + cmn_waveform = cmn_waveform.squeeze(0) + return cmn_waveform From d14991a3745b687e02560a26e2a679755816b1df Mon Sep 17 00:00:00 2001 From: Moto Hira Date: Mon, 16 Nov 2020 13:23:59 -0800 Subject: [PATCH 22/73] Import torchaudio #1034 70f429a Summary: Import torchaudio #1027 0cf4b8a Reviewed By: vincentqb, cpuhrsch Differential Revision: D24958707 fbshipit-source-id: d06dd6b59197cc2c16bec5a9012cbf33a172b6b3 --- .circleci/build_docs/build_docs.sh | 13 ++ .circleci/build_docs/commit_docs.sh | 31 +++++ .circleci/build_docs/install_wheels.sh | 12 ++ .circleci/config.yml | 113 ++++++++++-------- .circleci/config.yml.in | 49 +++++++- .circleci/regenerate.py | 38 +++++- .circleci/unittest/linux/scripts/setup_env.sh | 16 ++- .../unittest/windows/scripts/setup_env.sh | 14 ++- README.md | 4 +- .../datasets/cmuarctic_test.py | 12 +- .../datasets/commonvoice_test.py | 12 +- .../datasets/gtzan_test.py | 40 +++++-- .../datasets/ljspeech_test.py | 12 +- .../torchaudio_unittest/datasets/vctk_test.py | 12 +- .../datasets/yesno_test.py | 12 +- torchaudio/datasets/cmuarctic.py | 10 +- torchaudio/datasets/commonvoice.py | 10 +- torchaudio/datasets/gtzan.py | 11 +- torchaudio/datasets/ljspeech.py | 10 +- torchaudio/datasets/vctk.py | 10 +- torchaudio/datasets/yesno.py | 10 +- torchaudio/transforms.py | 4 +- 22 files changed, 347 insertions(+), 108 deletions(-) create mode 100755 .circleci/build_docs/build_docs.sh create mode 100755 .circleci/build_docs/commit_docs.sh create mode 100755 .circleci/build_docs/install_wheels.sh diff --git a/.circleci/build_docs/build_docs.sh b/.circleci/build_docs/build_docs.sh new file mode 100755 index 0000000000..2864a72974 --- /dev/null +++ b/.circleci/build_docs/build_docs.sh @@ -0,0 +1,13 @@ +#!/usr/bin/env bash + +set -ex +# shellcheck disable=SC1091 +source ./packaging/pkg_helpers.bash +export NO_CUDA_PACKAGE=1 +setup_env 0.8.0 +setup_wheel_python + +pushd docs +pip install -r requirements.txt +make html +popd diff --git a/.circleci/build_docs/commit_docs.sh b/.circleci/build_docs/commit_docs.sh new file mode 100755 index 0000000000..7ac380029f --- /dev/null +++ b/.circleci/build_docs/commit_docs.sh @@ -0,0 +1,31 @@ +#!/usr/bin/env bash + +set -ex + + +if [ "$2" == "" ]; then + echo call as "$0" "" "" + echo where src is the built documentation and + echo branch should be "master" or "1.7" or so + exit 1 +fi + +src=$1 +target=$2 + +set -ex +echo "committing docs from ${src} to ${target}" + +git checkout gh-pages +rm -rf docs/"${target}"/* +cp -r "${src}"/build/html/* docs/"${target}" +if [ "${target}" == "master" ]; then + rm -rf docs/_static/* + cp -r "${src}"/build/html/_static/* docs/_static +fi +git add docs || true +git config user.email "soumith+bot@pytorch.org" +git config user.name "pytorchbot" +# If there aren't changes, don't make a commit; push is no-op +git commit -m "auto-generating sphinx docs" || true +git push -u origin gh-pages diff --git a/.circleci/build_docs/install_wheels.sh b/.circleci/build_docs/install_wheels.sh new file mode 100755 index 0000000000..3e15154092 --- /dev/null +++ b/.circleci/build_docs/install_wheels.sh @@ -0,0 +1,12 @@ +#!/usr/bin/env bash + +set -ex + +# shellcheck disable=SC1091 +source ./packaging/pkg_helpers.bash +export NO_CUDA_PACKAGE=1 +setup_env 0.8.0 +setup_wheel_python +setup_pip_pytorch_version +# pytorch is already installed +pip install --no-deps ~/workspace/torchaudio* diff --git a/.circleci/config.yml b/.circleci/config.yml index 1f6d664d7e..7fb19c0276 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -61,7 +61,7 @@ binary_common: &binary_common python_version: description: "Python version to build against (e.g., 3.8)" type: string - environment: + environment: &environment PYTHON_VERSION: << parameters.python_version >> BUILD_VERSION: << parameters.build_version >> PYTORCH_VERSION: << parameters.pytorch_version >> @@ -432,6 +432,7 @@ jobs: image: ubuntu-1604-cuda-10.1:201909-23 resource_class: gpu.small environment: + <<: *environment image_name: "pytorch/torchaudio_unittest_base:manylinux-cuda10.1" steps: - checkout @@ -444,9 +445,12 @@ jobs: keys: - env-v3-linux-{{ arch }}-py<< parameters.python_version >>-{{ checksum ".circleci/unittest/linux/scripts/setup_env.sh" }}-{{ checksum "third_party/CMakeLists.txt" }}-{{ checksum ".cachekey" }} + - run: + name: Pull Docker image + command: docker pull --quiet "${image_name}" - run: name: Setup - command: docker run -t --gpus all -v $PWD:$PWD -w $PWD "${image_name}" .circleci/unittest/linux/scripts/setup_env.sh + command: docker run -t --gpus all -e PYTHON_VERSION -v $PWD:$PWD -w $PWD "${image_name}" .circleci/unittest/linux/scripts/setup_env.sh - save_cache: key: env-v3-linux-{{ arch }}-py<< parameters.python_version >>-{{ checksum ".circleci/unittest/linux/scripts/setup_env.sh" }}-{{ checksum "third_party/CMakeLists.txt" }}-{{ checksum ".cachekey" }} @@ -509,6 +513,7 @@ jobs: executor: name: windows-gpu environment: + <<: *environment CUDA_VERSION: "10.1" steps: - checkout @@ -649,6 +654,46 @@ jobs: command: | .circleci/torchscript_bc_test/setup_master_envs.sh .circleci/torchscript_bc_test/validate_objects.sh + build_docs: + <<: *binary_common + docker: + - image: "pytorch/manylinux-cuda100" + resource_class: 2xlarge+ + steps: + - attach_workspace: + at: ~/workspace + - designate_upload_channel + - checkout + - run: + name: Install pytorch-audio + command: .circleci/build_docs/install_wheels.sh + - run: + name: Build docs + command: .circleci/build_docs/build_docs.sh + - persist_to_workspace: + root: docs + paths: + - "*" + + upload_docs: + <<: *binary_common + docker: + - image: "pytorch/manylinux-cuda100" + resource_class: 2xlarge+ + steps: + - attach_workspace: + at: ~/workspace + - designate_upload_channel + - checkout + - run: + name: Upload docs + command: | + set -ex + echo $PWD + ls ~/workspace + tag=${CIRCLE_TAG:1:5} + target=${tag:-master} + .circleci/build_docs/commit_docs.sh ~/workspace $target workflows: build: @@ -734,6 +779,22 @@ workflows: - binary_windows_conda: name: binary_windows_conda_py3.8 python_version: '3.8' + - build_docs: + name: build_docs + python_version: '3.8' + requires: + - binary_linux_wheel_py3.8 + - upload_docs: + filters: + branches: + only: + - nightly + tags: + only: /v[0-9]+(\.[0-9]+)*-rc[0-9]+/ + name: upload_docs + python_version: '3.8' + requires: + - build_docs unittest: jobs: - torchscript_bc_test: @@ -760,40 +821,16 @@ workflows: requires: - download_third_parties_nix - unittest_linux_gpu: - filters: - branches: - only: - - master - - nightly - - release/* - tags: - only: /v[0-9]+(\.[0-9]+)*-rc[0-9]+/ name: unittest_linux_gpu_py3.6 python_version: '3.6' requires: - download_third_parties_nix - unittest_linux_gpu: - filters: - branches: - only: - - master - - nightly - - release/* - tags: - only: /v[0-9]+(\.[0-9]+)*-rc[0-9]+/ name: unittest_linux_gpu_py3.7 python_version: '3.7' requires: - download_third_parties_nix - unittest_linux_gpu: - filters: - branches: - only: - - master - - nightly - - release/* - tags: - only: /v[0-9]+(\.[0-9]+)*-rc[0-9]+/ name: unittest_linux_gpu_py3.8 python_version: '3.8' requires: @@ -808,36 +845,12 @@ workflows: name: unittest_windows_cpu_py3.8 python_version: '3.8' - unittest_windows_gpu: - filters: - branches: - only: - - master - - nightly - - release/* - tags: - only: /v[0-9]+(\.[0-9]+)*-rc[0-9]+/ name: unittest_windows_gpu_py3.6 python_version: '3.6' - unittest_windows_gpu: - filters: - branches: - only: - - master - - nightly - - release/* - tags: - only: /v[0-9]+(\.[0-9]+)*-rc[0-9]+/ name: unittest_windows_gpu_py3.7 python_version: '3.7' - unittest_windows_gpu: - filters: - branches: - only: - - master - - nightly - - release/* - tags: - only: /v[0-9]+(\.[0-9]+)*-rc[0-9]+/ name: unittest_windows_gpu_py3.8 python_version: '3.8' - unittest_macos_cpu: diff --git a/.circleci/config.yml.in b/.circleci/config.yml.in index b9fccbaf30..60006ff9c7 100644 --- a/.circleci/config.yml.in +++ b/.circleci/config.yml.in @@ -61,7 +61,7 @@ binary_common: &binary_common python_version: description: "Python version to build against (e.g., 3.8)" type: string - environment: + environment: &environment PYTHON_VERSION: << parameters.python_version >> BUILD_VERSION: << parameters.build_version >> PYTORCH_VERSION: << parameters.pytorch_version >> @@ -432,6 +432,7 @@ jobs: image: ubuntu-1604-cuda-10.1:201909-23 resource_class: gpu.small environment: + <<: *environment image_name: "pytorch/torchaudio_unittest_base:manylinux-cuda10.1" steps: - checkout @@ -444,9 +445,12 @@ jobs: keys: - env-v3-linux-{{ arch }}-py<< parameters.python_version >>-{{ checksum ".circleci/unittest/linux/scripts/setup_env.sh" }}-{{ checksum "third_party/CMakeLists.txt" }}-{{ checksum ".cachekey" }} {% endraw %} + - run: + name: Pull Docker image + command: docker pull --quiet "${image_name}" - run: name: Setup - command: docker run -t --gpus all -v $PWD:$PWD -w $PWD "${image_name}" .circleci/unittest/linux/scripts/setup_env.sh + command: docker run -t --gpus all -e PYTHON_VERSION -v $PWD:$PWD -w $PWD "${image_name}" .circleci/unittest/linux/scripts/setup_env.sh - save_cache: {% raw %} key: env-v3-linux-{{ arch }}-py<< parameters.python_version >>-{{ checksum ".circleci/unittest/linux/scripts/setup_env.sh" }}-{{ checksum "third_party/CMakeLists.txt" }}-{{ checksum ".cachekey" }} @@ -509,6 +513,7 @@ jobs: executor: name: windows-gpu environment: + <<: *environment CUDA_VERSION: "10.1" steps: - checkout @@ -649,6 +654,46 @@ jobs: command: | .circleci/torchscript_bc_test/setup_master_envs.sh .circleci/torchscript_bc_test/validate_objects.sh + build_docs: + <<: *binary_common + docker: + - image: "pytorch/manylinux-cuda100" + resource_class: 2xlarge+ + steps: + - attach_workspace: + at: ~/workspace + - designate_upload_channel + - checkout + - run: + name: Install pytorch-audio + command: .circleci/build_docs/install_wheels.sh + - run: + name: Build docs + command: .circleci/build_docs/build_docs.sh + - persist_to_workspace: + root: docs + paths: + - "*" + + upload_docs: + <<: *binary_common + docker: + - image: "pytorch/manylinux-cuda100" + resource_class: 2xlarge+ + steps: + - attach_workspace: + at: ~/workspace + - designate_upload_channel + - checkout + - run: + name: Upload docs + command: | + set -ex + echo $PWD + ls ~/workspace + tag=${CIRCLE_TAG:1:5} + target=${tag:-master} + .circleci/build_docs/commit_docs.sh ~/workspace $target workflows: build: diff --git a/.circleci/regenerate.py b/.circleci/regenerate.py index 419db311c1..e89ea4e914 100755 --- a/.circleci/regenerate.py +++ b/.circleci/regenerate.py @@ -21,6 +21,8 @@ PYTHON_VERSIONS = ["3.6", "3.7", "3.8"] +DOC_VERSION = ('linux', '3.8') + def build_workflows(prefix='', upload=False, filter_branch=None, indentation=6): w = [] @@ -30,6 +32,11 @@ def build_workflows(prefix='', upload=False, filter_branch=None, indentation=6): for python_version in PYTHON_VERSIONS: w += build_workflow_pair(btype, os_type, python_version, filter_branch, prefix, upload) + if not filter_branch: + # Build on every pull request, but upload only on nightly and tags + w += build_doc_job(None) + w += upload_doc_job('nightly') + return indent(indentation, w) @@ -68,6 +75,30 @@ def build_workflow_pair(btype, os_type, python_version, filter_branch, prefix='' return w +def build_doc_job(filter_branch): + job = { + "name": "build_docs", + "python_version": "3.8", + "requires": ["binary_linux_wheel_py3.8"], + } + + if filter_branch: + job["filters"] = gen_filter_branch_tree(filter_branch) + return [{"build_docs": job}] + + +def upload_doc_job(filter_branch): + job = { + "name": "upload_docs", + "python_version": "3.8", + "requires": ["build_docs"], + } + + if filter_branch: + job["filters"] = gen_filter_branch_tree(filter_branch) + return [{"upload_docs": job}] + + def generate_base_workflow(base_workflow_name, python_version, filter_branch, os_type, btype): d = { @@ -81,7 +112,7 @@ def generate_base_workflow(base_workflow_name, python_version, filter_branch, os if filter_branch: d["filters"] = gen_filter_branch_tree(filter_branch) - return {"binary_{os_type}_{btype}".format(os_type=os_type, btype=btype): d} + return {f"binary_{os_type}_{btype}": d} def gen_filter_branch_tree(*branches): @@ -147,9 +178,6 @@ def unittest_workflows(indentation=6): "python_version": python_version, } - if device_type == 'gpu': - job['filters'] = gen_filter_branch_tree('master', 'nightly', 'release/*') - if os_type != "windows": job['requires'] = ['download_third_parties_nix'] @@ -157,7 +185,7 @@ def unittest_workflows(indentation=6): if i == 0 and os_type == "linux" and device_type == "cpu": jobs.append({ - f"stylecheck": { + "stylecheck": { "name": f"stylecheck_py{python_version}", "python_version": python_version, } diff --git a/.circleci/unittest/linux/scripts/setup_env.sh b/.circleci/unittest/linux/scripts/setup_env.sh index 6e203dea27..26292a00d5 100755 --- a/.circleci/unittest/linux/scripts/setup_env.sh +++ b/.circleci/unittest/linux/scripts/setup_env.sh @@ -21,20 +21,26 @@ esac # 1. Install conda at ./conda if [ ! -d "${conda_dir}" ]; then printf "* Installing conda\n" - wget -O miniconda.sh "http://repo.continuum.io/miniconda/Miniconda3-latest-${os}-x86_64.sh" + wget --quiet -O miniconda.sh "http://repo.continuum.io/miniconda/Miniconda3-latest-${os}-x86_64.sh" bash ./miniconda.sh -b -f -p "${conda_dir}" + eval "$("${conda_dir}/bin/conda" shell.bash hook)" + conda update --quiet -y conda + printf "* Updating the base Python version to %s\n" "${PYTHON_VERSION}" + conda install --quiet -y python="${PYTHON_VERSION}" +else + eval "$("${conda_dir}/bin/conda" shell.bash hook)" fi -eval "$(${conda_dir}/bin/conda shell.bash hook)" + # 2. Create test environment at ./env if [ ! -d "${env_dir}" ]; then - printf "* Creating a test environment\n" - conda create --prefix "${env_dir}" -y python="$PYTHON_VERSION" + printf "* Creating a test environment with PYTHON_VERSION=%s\n" "${PYTHON_VERSION}\n" + conda create --prefix "${env_dir}" -y python="${PYTHON_VERSION}" fi conda activate "${env_dir}" # 3. Install minimal build tools -pip install cmake ninja +pip --quiet install cmake ninja # 4. Buld codecs mkdir -p third_party/build diff --git a/.circleci/unittest/windows/scripts/setup_env.sh b/.circleci/unittest/windows/scripts/setup_env.sh index 71b556d2bd..929a98cb8f 100644 --- a/.circleci/unittest/windows/scripts/setup_env.sh +++ b/.circleci/unittest/windows/scripts/setup_env.sh @@ -19,17 +19,21 @@ if [ ! -d "${conda_dir}" ]; then printf "* Installing conda\n" export tmp_conda="$(echo $conda_dir | tr '/' '\\')" export miniconda_exe="$(echo $root_dir | tr '/' '\\')\\miniconda.exe" - curl --output miniconda.exe https://repo.anaconda.com/miniconda/Miniconda3-latest-Windows-x86_64.exe -O + curl --silent --output miniconda.exe https://repo.anaconda.com/miniconda/Miniconda3-latest-Windows-x86_64.exe -O "$this_dir/install_conda.bat" unset tmp_conda unset miniconda_exe + eval "$("${conda_dir}/Scripts/conda.exe" 'shell.bash' 'hook')" + conda update --quiet -y conda + printf "* Updating the base Python version to %s\n" "${PYTHON_VERSION}" + conda install --quiet -y python="$PYTHON_VERSION" +else + eval "$("${conda_dir}/Scripts/conda.exe" 'shell.bash' 'hook')" fi -eval "$(${conda_dir}/Scripts/conda.exe 'shell.bash' 'hook')" - # 2. Create test environment at ./env if [ ! -d "${env_dir}" ]; then - printf "* Creating a test environment\n" - conda create --prefix "${env_dir}" -y python="$PYTHON_VERSION" + printf "* Creating a test environment with PYTHON_VERSION=%s\n" "${PYTHON_VERSION}" + conda create --prefix "${env_dir}" -y python="${PYTHON_VERSION}" fi conda activate "${env_dir}" diff --git a/README.md b/README.md index 861af2a04b..9bef876136 100644 --- a/README.md +++ b/README.md @@ -10,8 +10,8 @@ the audio domain. By supporting PyTorch, torchaudio follows the same philosophy of providing strong GPU acceleration, having a focus on trainable features through the autograd system, and having consistent style (tensor names and dimension names). Therefore, it is primarily a machine learning library and not a general signal -processing library. The benefits of Pytorch is be seen in torchaudio through -having all the computations be through Pytorch operations which makes it easy +processing library. The benefits of PyTorch is be seen in torchaudio through +having all the computations be through PyTorch operations which makes it easy to use and feel like a natural extension. - [Support audio I/O (Load files, Save files)](http://pytorch.org/audio/) diff --git a/test/torchaudio_unittest/datasets/cmuarctic_test.py b/test/torchaudio_unittest/datasets/cmuarctic_test.py index 578b0ec385..f8f7969c25 100644 --- a/test/torchaudio_unittest/datasets/cmuarctic_test.py +++ b/test/torchaudio_unittest/datasets/cmuarctic_test.py @@ -1,4 +1,5 @@ import os +from pathlib import Path from torchaudio.datasets import cmuarctic @@ -54,8 +55,7 @@ def setUpClass(cls): txt.write(f'( {utterance_id} "{utterance}" )\n') seed += 1 - def test_cmuarctic(self): - dataset = cmuarctic.CMUARCTIC(self.root_dir) + def _test_cmuarctic(self, dataset): n_ite = 0 for i, (waveform, sample_rate, utterance, utterance_id) in enumerate(dataset): expected_sample = self.samples[i] @@ -65,3 +65,11 @@ def test_cmuarctic(self): self.assertEqual(expected_sample[0], waveform, atol=5e-5, rtol=1e-8) n_ite += 1 assert n_ite == len(self.samples) + + def test_cmuarctic_str(self): + dataset = cmuarctic.CMUARCTIC(self.root_dir) + self._test_cmuarctic(dataset) + + def test_cmuarctic_path(self): + dataset = cmuarctic.CMUARCTIC(Path(self.root_dir)) + self._test_cmuarctic(dataset) diff --git a/test/torchaudio_unittest/datasets/commonvoice_test.py b/test/torchaudio_unittest/datasets/commonvoice_test.py index 3eedebec70..731c4e07cc 100644 --- a/test/torchaudio_unittest/datasets/commonvoice_test.py +++ b/test/torchaudio_unittest/datasets/commonvoice_test.py @@ -1,6 +1,7 @@ import os import csv import random +from pathlib import Path from torchaudio.datasets import commonvoice from torchaudio_unittest.common_utils import ( @@ -59,8 +60,7 @@ def setUpClass(cls): # Append data entry cls.data.append((normalize_wav(data), cls.sample_rate, dict(zip(cls._headers, content)))) - def test_commonvoice(self): - dataset = commonvoice.COMMONVOICE(self.root_dir) + def _test_commonvoice(self, dataset): n_ite = 0 for i, (waveform, sample_rate, dictionary) in enumerate(dataset): expected_dictionary = self.data[i][2] @@ -70,3 +70,11 @@ def test_commonvoice(self): assert dictionary == expected_dictionary n_ite += 1 assert n_ite == len(self.data) + + def test_commonvoice_str(self): + dataset = commonvoice.COMMONVOICE(self.root_dir) + self._test_commonvoice(dataset) + + def test_commonvoice_path(self): + dataset = commonvoice.COMMONVOICE(Path(self.root_dir)) + self._test_commonvoice(dataset) diff --git a/test/torchaudio_unittest/datasets/gtzan_test.py b/test/torchaudio_unittest/datasets/gtzan_test.py index 3236535fad..763e0a866f 100644 --- a/test/torchaudio_unittest/datasets/gtzan_test.py +++ b/test/torchaudio_unittest/datasets/gtzan_test.py @@ -1,4 +1,5 @@ import os +from pathlib import Path from torchaudio.datasets import gtzan @@ -54,9 +55,7 @@ def test_no_subset(self): n_ite += 1 assert n_ite == len(self.samples) - def test_training(self): - dataset = gtzan.GTZAN(self.root_dir, subset='training') - + def _test_training(self, dataset): n_ite = 0 for i, (waveform, sample_rate, label) in enumerate(dataset): self.assertEqual(waveform, self.training[i][0], atol=5e-5, rtol=1e-8) @@ -65,9 +64,7 @@ def test_training(self): n_ite += 1 assert n_ite == len(self.training) - def test_validation(self): - dataset = gtzan.GTZAN(self.root_dir, subset='validation') - + def _test_validation(self, dataset): n_ite = 0 for i, (waveform, sample_rate, label) in enumerate(dataset): self.assertEqual(waveform, self.validation[i][0], atol=5e-5, rtol=1e-8) @@ -76,9 +73,7 @@ def test_validation(self): n_ite += 1 assert n_ite == len(self.validation) - def test_testing(self): - dataset = gtzan.GTZAN(self.root_dir, subset='testing') - + def _test_testing(self, dataset): n_ite = 0 for i, (waveform, sample_rate, label) in enumerate(dataset): self.assertEqual(waveform, self.testing[i][0], atol=5e-5, rtol=1e-8) @@ -86,3 +81,30 @@ def test_testing(self): assert label == self.testing[i][2] n_ite += 1 assert n_ite == len(self.testing) + + def test_training_str(self): + train_dataset = gtzan.GTZAN(self.root_dir, subset='training') + self._test_training(train_dataset) + + def test_validation_str(self): + val_dataset = gtzan.GTZAN(self.root_dir, subset='validation') + self._test_validation(val_dataset) + + def test_testing_str(self): + test_dataset = gtzan.GTZAN(self.root_dir, subset='testing') + self._test_testing(test_dataset) + + def test_training_path(self): + root_dir = Path(self.root_dir) + train_dataset = gtzan.GTZAN(root_dir, subset='training') + self._test_training(train_dataset) + + def test_validation_path(self): + root_dir = Path(self.root_dir) + val_dataset = gtzan.GTZAN(root_dir, subset='validation') + self._test_validation(val_dataset) + + def test_testing_path(self): + root_dir = Path(self.root_dir) + test_dataset = gtzan.GTZAN(root_dir, subset='testing') + self._test_testing(test_dataset) diff --git a/test/torchaudio_unittest/datasets/ljspeech_test.py b/test/torchaudio_unittest/datasets/ljspeech_test.py index 7c1128c31b..33458fd6e1 100644 --- a/test/torchaudio_unittest/datasets/ljspeech_test.py +++ b/test/torchaudio_unittest/datasets/ljspeech_test.py @@ -1,5 +1,6 @@ import csv import os +from pathlib import Path from torchaudio.datasets import ljspeech @@ -57,8 +58,7 @@ def setUpClass(cls): save_wav(path, data, sample_rate) cls.data.append(normalize_wav(data)) - def test_ljspeech(self): - dataset = ljspeech.LJSPEECH(self.root_dir) + def _test_ljspeech(self, dataset): n_ite = 0 for i, (waveform, sample_rate, transcript, normalized_transcript) in enumerate( dataset @@ -72,3 +72,11 @@ def test_ljspeech(self): assert normalized_transcript == expected_normalized_transcript n_ite += 1 assert n_ite == len(self.data) + + def test_ljspeech_str(self): + dataset = ljspeech.LJSPEECH(self.root_dir) + self._test_ljspeech(dataset) + + def test_ljspeech_path(self): + dataset = ljspeech.LJSPEECH(Path(self.root_dir)) + self._test_ljspeech(dataset) diff --git a/test/torchaudio_unittest/datasets/vctk_test.py b/test/torchaudio_unittest/datasets/vctk_test.py index 26b14f5d04..76bbf29936 100644 --- a/test/torchaudio_unittest/datasets/vctk_test.py +++ b/test/torchaudio_unittest/datasets/vctk_test.py @@ -1,4 +1,5 @@ import os +from pathlib import Path from torchaudio.datasets import vctk @@ -77,8 +78,7 @@ def setUpClass(cls): seed += 1 - def test_vctk(self): - dataset = vctk.VCTK_092(self.root_dir, audio_ext=".wav") + def _test_vctk(self, dataset): num_samples = 0 for i, (data, sample_rate, utterance, speaker_id, utterance_id) in enumerate(dataset): self.assertEqual(data, self.samples[i][0], atol=5e-5, rtol=1e-8) @@ -89,3 +89,11 @@ def test_vctk(self): num_samples += 1 assert num_samples == len(self.samples) + + def test_vctk_str(self): + dataset = vctk.VCTK_092(self.root_dir, audio_ext=".wav") + self._test_vctk(dataset) + + def test_vctk_path(self): + dataset = vctk.VCTK_092(Path(self.root_dir), audio_ext=".wav") + self._test_vctk(dataset) diff --git a/test/torchaudio_unittest/datasets/yesno_test.py b/test/torchaudio_unittest/datasets/yesno_test.py index a8a8a04276..6b094aaece 100644 --- a/test/torchaudio_unittest/datasets/yesno_test.py +++ b/test/torchaudio_unittest/datasets/yesno_test.py @@ -1,4 +1,5 @@ import os +from pathlib import Path from torchaudio.datasets import yesno @@ -36,8 +37,7 @@ def setUpClass(cls): save_wav(path, data, 8000) cls.data.append(normalize_wav(data)) - def test_yesno(self): - dataset = yesno.YESNO(self.root_dir) + def _test_yesno(self, dataset): n_ite = 0 for i, (waveform, sample_rate, label) in enumerate(dataset): expected_label = self.labels[i] @@ -47,3 +47,11 @@ def test_yesno(self): assert label == expected_label n_ite += 1 assert n_ite == len(self.data) + + def test_yesno_str(self): + dataset = yesno.YESNO(self.root_dir) + self._test_yesno(dataset) + + def test_yesno_path(self): + dataset = yesno.YESNO(Path(self.root_dir)) + self._test_yesno(dataset) diff --git a/torchaudio/datasets/cmuarctic.py b/torchaudio/datasets/cmuarctic.py index 7ea4ca4dae..f8674127fd 100644 --- a/torchaudio/datasets/cmuarctic.py +++ b/torchaudio/datasets/cmuarctic.py @@ -1,5 +1,6 @@ import os -from typing import Tuple +from pathlib import Path +from typing import Tuple, Union import torchaudio from torch import Tensor @@ -79,7 +80,7 @@ class CMUARCTIC(Dataset): """Create a Dataset for CMU_ARCTIC. Args: - root (str): Path to the directory where the dataset is found or downloaded. + root (str or Path): Path to the directory where the dataset is found or downloaded. url (str, optional): The URL to download the dataset from or the type of the dataset to dowload. (default: ``"aew"``) @@ -98,7 +99,7 @@ class CMUARCTIC(Dataset): _folder_audio = "wav" def __init__(self, - root: str, + root: Union[str, Path], url: str = URL, folder_in_archive: str = FOLDER_IN_ARCHIVE, download: bool = False) -> None: @@ -130,6 +131,9 @@ def __init__(self, url = os.path.join(base_url, url + ext_archive) + # Get string representation of 'root' in case Path object is passed + root = os.fspath(root) + basename = os.path.basename(url) root = os.path.join(root, folder_in_archive) if not os.path.isdir(root): diff --git a/torchaudio/datasets/commonvoice.py b/torchaudio/datasets/commonvoice.py index 825cf3e9ab..963777cf38 100644 --- a/torchaudio/datasets/commonvoice.py +++ b/torchaudio/datasets/commonvoice.py @@ -1,5 +1,6 @@ import os -from typing import List, Dict, Tuple +from pathlib import Path +from typing import List, Dict, Tuple, Union import torchaudio from torchaudio.datasets.utils import download_url, extract_archive, unicode_csv_reader @@ -103,7 +104,7 @@ class COMMONVOICE(Dataset): """Create a Dataset for CommonVoice. Args: - root (str): Path to the directory where the dataset is found or downloaded. + root (str or Path): Path to the directory where the dataset is found or downloaded. tsv (str, optional): The name of the tsv file used to construct the metadata. (default: ``"train.tsv"``) url (str, optional): The URL to download the dataset from, or the language of @@ -129,7 +130,7 @@ class COMMONVOICE(Dataset): _folder_audio = "clips" def __init__(self, - root: str, + root: Union[str, Path], tsv: str = TSV, url: str = URL, folder_in_archive: str = FOLDER_IN_ARCHIVE, @@ -186,6 +187,9 @@ def __init__(self, base_url = "https://voice-prod-bundler-ee1969a6ce8178826482b88e843c335139bd3fb4.s3.amazonaws.com" url = os.path.join(base_url, version, language + ext_archive) + # Get string representation of 'root' in case Path object is passed + root = os.fspath(root) + basename = os.path.basename(url) archive = os.path.join(root, basename) diff --git a/torchaudio/datasets/gtzan.py b/torchaudio/datasets/gtzan.py index 160898c73d..4c91894be1 100644 --- a/torchaudio/datasets/gtzan.py +++ b/torchaudio/datasets/gtzan.py @@ -1,6 +1,7 @@ import os import warnings -from typing import Any, Tuple, Optional +from pathlib import Path +from typing import Any, Tuple, Optional, Union import torchaudio from torch import Tensor @@ -1005,7 +1006,7 @@ class GTZAN(Dataset): this dataset to publish results. Args: - root (str): Path to the directory where the dataset is found or downloaded. + root (str or Path): Path to the directory where the dataset is found or downloaded. url (str, optional): The URL to download the dataset from. (default: ``"http://opihi.cs.uvic.ca/sound/genres.tar.gz"``) folder_in_archive (str, optional): The top-level directory of the dataset. @@ -1020,7 +1021,7 @@ class GTZAN(Dataset): def __init__( self, - root: str, + root: Union[str, Path], url: str = URL, folder_in_archive: str = FOLDER_IN_ARCHIVE, download: bool = False, @@ -1028,6 +1029,10 @@ def __init__( ) -> None: # super(GTZAN, self).__init__() + + # Get string representation of 'root' in case Path object is passed + root = os.fspath(root) + self.root = root self.url = url self.folder_in_archive = folder_in_archive diff --git a/torchaudio/datasets/ljspeech.py b/torchaudio/datasets/ljspeech.py index 28c3a5dfc8..2d653fbf46 100644 --- a/torchaudio/datasets/ljspeech.py +++ b/torchaudio/datasets/ljspeech.py @@ -1,6 +1,7 @@ import os import csv -from typing import List, Tuple +from typing import List, Tuple, Union +from pathlib import Path import torchaudio from torchaudio.datasets.utils import download_url, extract_archive, unicode_csv_reader @@ -36,7 +37,7 @@ class LJSPEECH(Dataset): """Create a Dataset for LJSpeech-1.1. Args: - root (str): Path to the directory where the dataset is found or downloaded. + root (str or Path): Path to the directory where the dataset is found or downloaded. url (str, optional): The URL to download the dataset from. (default: ``"https://data.keithito.com/data/speech/LJSpeech-1.1.tar.bz2"``) folder_in_archive (str, optional): @@ -49,11 +50,14 @@ class LJSPEECH(Dataset): _ext_archive = '.tar.bz2' def __init__(self, - root: str, + root: Union[str, Path], url: str = URL, folder_in_archive: str = FOLDER_IN_ARCHIVE, download: bool = False) -> None: + # Get string representation of 'root' in case Path object is passed + root = os.fspath(root) + basename = os.path.basename(url) archive = os.path.join(root, basename) diff --git a/torchaudio/datasets/vctk.py b/torchaudio/datasets/vctk.py index a8fca59df2..9bf843f685 100644 --- a/torchaudio/datasets/vctk.py +++ b/torchaudio/datasets/vctk.py @@ -1,6 +1,7 @@ import os import warnings -from typing import Any, Tuple +from typing import Any, Tuple, Union +from pathlib import Path import torchaudio from torch import Tensor @@ -57,7 +58,7 @@ class VCTK(Dataset): For more information about the dataset visit: https://datashare.is.ed.ac.uk/handle/10283/3443 Args: - root (str): Path to the directory where the dataset is found or downloaded. + root (str or Path): Path to the directory where the dataset is found or downloaded. url (str, optional): Not used as the dataset is no longer publicly available. folder_in_archive (str, optional): The top-level directory of the dataset. (default: ``"VCTK-Corpus"``) @@ -77,7 +78,7 @@ class VCTK(Dataset): _except_folder = "p315" def __init__(self, - root: str, + root: Union[str, Path], url: str = URL, folder_in_archive: str = FOLDER_IN_ARCHIVE, download: bool = False, @@ -103,6 +104,9 @@ def __init__(self, self.transform = transform self.target_transform = target_transform + # Get string representation of 'root' in case Path object is passed + root = os.fspath(root) + archive = os.path.basename(url) archive = os.path.join(root, archive) self._path = os.path.join(root, folder_in_archive) diff --git a/torchaudio/datasets/yesno.py b/torchaudio/datasets/yesno.py index 5a20539e28..182d224ba4 100644 --- a/torchaudio/datasets/yesno.py +++ b/torchaudio/datasets/yesno.py @@ -1,6 +1,7 @@ import os import warnings -from typing import Any, List, Tuple +from typing import Any, List, Tuple, Union +from pathlib import Path import torchaudio from torch import Tensor @@ -34,7 +35,7 @@ class YESNO(Dataset): """Create a Dataset for YesNo. Args: - root (str): Path to the directory where the dataset is found or downloaded. + root (str or Path): Path to the directory where the dataset is found or downloaded. url (str, optional): The URL to download the dataset from. (default: ``"http://www.openslr.org/resources/1/waves_yesno.tar.gz"``) folder_in_archive (str, optional): @@ -48,7 +49,7 @@ class YESNO(Dataset): _ext_audio = ".wav" def __init__(self, - root: str, + root: Union[str, Path], url: str = URL, folder_in_archive: str = FOLDER_IN_ARCHIVE, download: bool = False, @@ -65,6 +66,9 @@ def __init__(self, self.transform = transform self.target_transform = target_transform + # Get string representation of 'root' in case Path object is passed + root = os.fspath(root) + archive = os.path.basename(url) archive = os.path.join(root, archive) self._path = os.path.join(root, folder_in_archive) diff --git a/torchaudio/transforms.py b/torchaudio/transforms.py index 2e7e4f37ee..3306491b21 100644 --- a/torchaudio/transforms.py +++ b/torchaudio/transforms.py @@ -1002,7 +1002,7 @@ def __init__(self, self.pre_trigger_time = pre_trigger_time self.boot_time = boot_time self.noise_up_time = noise_up_time - self.noise_down_time = noise_up_time + self.noise_down_time = noise_down_time self.noise_reduction_amount = noise_reduction_amount self.measure_freq = measure_freq self.measure_duration = measure_duration @@ -1027,7 +1027,7 @@ def forward(self, waveform: Tensor) -> Tensor: pre_trigger_time=self.pre_trigger_time, boot_time=self.boot_time, noise_up_time=self.noise_up_time, - noise_down_time=self.noise_up_time, + noise_down_time=self.noise_down_time, noise_reduction_amount=self.noise_reduction_amount, measure_freq=self.measure_freq, measure_duration=self.measure_duration, From 7eead14b2c99c777fa45b9999813599c98fee1b7 Mon Sep 17 00:00:00 2001 From: Moto Hira Date: Tue, 8 Dec 2020 09:54:35 -0800 Subject: [PATCH 23/73] Import torchaudio #1066 4406a6b Summary: Import up to #1066 Reviewed By: cpuhrsch Differential Revision: D25373068 fbshipit-source-id: 890d36a25259b93428b3037c3123ff5a2cacfa04 --- .circleci/build_docs/commit_docs.sh | 14 +- .circleci/config.yml | 11 ++ .circleci/config.yml.in | 10 + .circleci/regenerate.py | 5 +- README.md | 48 ++--- build_tools/setup_helpers/extension.py | 2 + docs/source/datasets.rst | 2 +- docs/source/functional.rst | 10 + .../datasets/librispeech_test.py | 17 +- .../datasets/libritts_test.py | 12 +- .../datasets/speechcommands_test.py | 79 ++------ .../datasets/tedlium_test.py | 49 ++--- .../datasets/utils_test.py | 4 +- .../sox_effect/dataset_test.py | 34 ++++ .../sox_effect/sox_effect_test.py | 26 ++- .../sox_io_backend/info_test.py | 30 +++ .../sox_io_backend/load_test.py | 61 ++++++ .../sox_io_backend/save_test.py | 75 ++++++++ third_party/CMakeLists.txt | 14 +- torchaudio/backend/sox_io_backend.py | 10 +- torchaudio/csrc/sox_effects.cpp | 11 +- torchaudio/csrc/sox_effects.h | 4 +- torchaudio/csrc/sox_io.cpp | 40 ++-- torchaudio/csrc/sox_io.h | 8 +- torchaudio/csrc/sox_utils.cpp | 22 ++- torchaudio/datasets/commonvoice.py | 177 ++++++++++-------- torchaudio/datasets/librispeech.py | 10 +- torchaudio/datasets/libritts.py | 10 +- torchaudio/datasets/speechcommands.py | 10 +- torchaudio/datasets/tedlium.py | 15 +- torchaudio/functional/filtering.py | 3 +- torchaudio/functional/functional.py | 16 +- torchaudio/sox_effects/sox_effects.py | 8 +- torchaudio/utils/sox_utils.py | 9 +- 34 files changed, 569 insertions(+), 287 deletions(-) diff --git a/.circleci/build_docs/commit_docs.sh b/.circleci/build_docs/commit_docs.sh index 7ac380029f..9e9548936a 100755 --- a/.circleci/build_docs/commit_docs.sh +++ b/.circleci/build_docs/commit_docs.sh @@ -13,17 +13,19 @@ fi src=$1 target=$2 -set -ex echo "committing docs from ${src} to ${target}" git checkout gh-pages -rm -rf docs/"${target}"/* -cp -r "${src}"/build/html/* docs/"${target}" +mkdir -p ./"${target}" +rm -rf ./"${target}"/* +cp -r "${src}/build/html/"* ./"$target" if [ "${target}" == "master" ]; then - rm -rf docs/_static/* - cp -r "${src}"/build/html/_static/* docs/_static + mkdir -p ./_static + rm -rf ./_static/* + cp -r "${src}/build/html/_static/"* ./_static + git add --all ./_static || true fi -git add docs || true +git add --all ./"${target}" || true git config user.email "soumith+bot@pytorch.org" git config user.name "pytorchbot" # If there aren't changes, don't make a commit; push is no-op diff --git a/.circleci/config.yml b/.circleci/config.yml index 7fb19c0276..f0ee6764b1 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -684,6 +684,16 @@ jobs: - attach_workspace: at: ~/workspace - designate_upload_channel + - run: + name: Generate netrc + command: | + # set credentials for https pushing + # requires the org-member context + cat > ~/.netrc \< ~/.netrc \< (channel, freq, time) -* `AmplitudeToDB`: (channel, freq, time) -> (channel, freq, time) -* `MelScale`: (channel, freq, time) -> (channel, mel, time) -* `MelSpectrogram`: (channel, time) -> (channel, mel, time) -* `MFCC`: (channel, time) -> (channel, mfcc, time) -* `MuLawEncode`: (channel, time) -> (channel, time) -* `MuLawDecode`: (channel, time) -> (channel, time) -* `Resample`: (channel, time) -> (channel, time) -* `Fade`: (channel, time) -> (channel, time) -* `Vol`: (channel, time) -> (channel, time) +* `Spectrogram`: (channels, time) -> (channels, freq, time) +* `AmplitudeToDB`: (channels, freq, time) -> (channels, freq, time) +* `MelScale`: (channels, freq, time) -> (channels, mel, time) +* `MelSpectrogram`: (channels, time) -> (channels, mel, time) +* `MFCC`: (channels, time) -> (channel, mfcc, time) +* `MuLawEncode`: (channels, time) -> (channels, time) +* `MuLawDecode`: (channels, time) -> (channels, time) +* `Resample`: (channels, time) -> (channels, time) +* `Fade`: (channels, time) -> (channels, time) +* `Vol`: (channels, time) -> (channels, time) Complex numbers are supported via tensors of dimension (..., 2), and torchaudio provides `complex_norm` and `angle` to convert such a tensor into its magnitude and phase. Here, and in the documentation, we use an ellipsis "..." as a placeholder for the rest of the dimensions of a tensor, e.g. optional batching and channel dimensions. diff --git a/build_tools/setup_helpers/extension.py b/build_tools/setup_helpers/extension.py index b9fb30e114..8e6cd337cb 100644 --- a/build_tools/setup_helpers/extension.py +++ b/build_tools/setup_helpers/extension.py @@ -89,6 +89,8 @@ def _get_extra_objects(): 'libvorbisfile.a', 'libvorbis.a', 'libogg.a', + 'libopencore-amrnb.a', + 'libopencore-amrwb.a', ] for lib in libs: objs.append(str(_TP_INSTALL_DIR / 'lib' / lib)) diff --git a/docs/source/datasets.rst b/docs/source/datasets.rst index 2ceb93a440..2fbb2c7929 100644 --- a/docs/source/datasets.rst +++ b/docs/source/datasets.rst @@ -2,7 +2,7 @@ torchaudio.datasets ==================== All datasets are subclasses of :class:`torch.utils.data.Dataset` -i.e, they have ``__getitem__`` and ``__len__`` methods implemented. +and have ``__getitem__`` and ``__len__`` methods implemented. Hence, they can all be passed to a :class:`torch.utils.data.DataLoader` which can load multiple samples parallelly using ``torch.multiprocessing`` workers. For example: :: diff --git a/docs/source/functional.rst b/docs/source/functional.rst index a0f3a272cf..ebed60de6b 100644 --- a/docs/source/functional.rst +++ b/docs/source/functional.rst @@ -124,11 +124,21 @@ vad .. autofunction:: spectrogram +:hidden:`griffinlim` +~~~~~~~~~~~~~~~~~~~~~~~~~ + +.. autofunction:: griffinlim + :hidden:`amplitude_to_DB` ~~~~~~~~~~~~~~~~~~~~~~~~~ .. autofunction:: amplitude_to_DB +:hidden:`DB_to_amplitude` +~~~~~~~~~~~~~~~~~~~~~~~~~ + +.. autofunction:: DB_to_amplitude + :hidden:`create_fb_matrix` ~~~~~~~~~~~~~~~~~~~~~~~~~~ diff --git a/test/torchaudio_unittest/datasets/librispeech_test.py b/test/torchaudio_unittest/datasets/librispeech_test.py index 669b428876..b0eabb767c 100644 --- a/test/torchaudio_unittest/datasets/librispeech_test.py +++ b/test/torchaudio_unittest/datasets/librispeech_test.py @@ -1,4 +1,5 @@ import os +from pathlib import Path from torchaudio.datasets import librispeech @@ -91,11 +92,7 @@ def tearDownClass(cls): # In case of test failure librispeech.LIBRISPEECH._ext_audio = '.flac' - def test_librispeech(self): - librispeech.LIBRISPEECH._ext_audio = '.wav' - dataset = librispeech.LIBRISPEECH(self.root_dir) - print(dataset._path) - + def _test_librispeech(self, dataset): num_samples = 0 for i, ( data, sample_rate, utterance, speaker_id, chapter_id, utterance_id @@ -110,3 +107,13 @@ def test_librispeech(self): assert num_samples == len(self.samples) librispeech.LIBRISPEECH._ext_audio = '.flac' + + def test_librispeech_str(self): + librispeech.LIBRISPEECH._ext_audio = '.wav' + dataset = librispeech.LIBRISPEECH(self.root_dir) + self._test_librispeech(dataset) + + def test_librispeech_path(self): + librispeech.LIBRISPEECH._ext_audio = '.wav' + dataset = librispeech.LIBRISPEECH(Path(self.root_dir)) + self._test_librispeech(dataset) diff --git a/test/torchaudio_unittest/datasets/libritts_test.py b/test/torchaudio_unittest/datasets/libritts_test.py index 639098446b..04d47e95f4 100644 --- a/test/torchaudio_unittest/datasets/libritts_test.py +++ b/test/torchaudio_unittest/datasets/libritts_test.py @@ -1,4 +1,5 @@ import os +from pathlib import Path from torchaudio.datasets.libritts import LIBRITTS @@ -47,8 +48,7 @@ def setUpClass(cls): with open(path_normalized, 'w') as file_: file_.write(cls.normalized_text) - def test_libritts(self): - dataset = LIBRITTS(self.root_dir) + def _test_libritts(self, dataset): n_ites = 0 for i, (waveform, sample_rate, @@ -69,3 +69,11 @@ def test_libritts(self): assert utterance_id == f'{"_".join(str(u) for u in expected_ids[-4:])}' n_ites += 1 assert n_ites == len(self.utterance_ids) + + def test_libritts_str(self): + dataset = LIBRITTS(self.root_dir) + self._test_libritts(dataset) + + def test_libritts_path(self): + dataset = LIBRITTS(Path(self.root_dir)) + self._test_libritts(dataset) diff --git a/test/torchaudio_unittest/datasets/speechcommands_test.py b/test/torchaudio_unittest/datasets/speechcommands_test.py index 5a331bdeca..6351d41b27 100644 --- a/test/torchaudio_unittest/datasets/speechcommands_test.py +++ b/test/torchaudio_unittest/datasets/speechcommands_test.py @@ -1,4 +1,5 @@ import os +from pathlib import Path from torchaudio.datasets import speechcommands @@ -105,85 +106,39 @@ def setUpClass(cls): test.write(f'{label}/{filename}\n') cls.test_samples.append(sample) - def testSpeechCommands(self): - dataset = speechcommands.SPEECHCOMMANDS(self.root_dir) - + def _testSpeechCommands(self, dataset, data_samples): num_samples = 0 for i, (data, sample_rate, label, speaker_id, utterance_number) in enumerate( dataset ): - self.assertEqual(data, self.samples[i][0], atol=5e-5, rtol=1e-8) - assert sample_rate == self.samples[i][1] - assert label == self.samples[i][2] - assert speaker_id == self.samples[i][3] - assert utterance_number == self.samples[i][4] + self.assertEqual(data, data_samples[i][0], atol=5e-5, rtol=1e-8) + assert sample_rate == data_samples[i][1] + assert label == data_samples[i][2] + assert speaker_id == data_samples[i][3] + assert utterance_number == data_samples[i][4] num_samples += 1 - assert num_samples == len(self.samples) + assert num_samples == len(data_samples) - def testSpeechCommandsNone(self): - dataset = speechcommands.SPEECHCOMMANDS(self.root_dir, subset=None) - - num_samples = 0 - for i, (data, sample_rate, label, speaker_id, utterance_number) in enumerate( - dataset - ): - self.assertEqual(data, self.samples[i][0], atol=5e-5, rtol=1e-8) - assert sample_rate == self.samples[i][1] - assert label == self.samples[i][2] - assert speaker_id == self.samples[i][3] - assert utterance_number == self.samples[i][4] - num_samples += 1 + def testSpeechCommands_str(self): + dataset = speechcommands.SPEECHCOMMANDS(self.root_dir) + self._testSpeechCommands(dataset, self.samples) - assert num_samples == len(self.samples) + def testSpeechCommands_path(self): + dataset = speechcommands.SPEECHCOMMANDS(Path(self.root_dir)) + self._testSpeechCommands(dataset, self.samples) def testSpeechCommandsSubsetTrain(self): dataset = speechcommands.SPEECHCOMMANDS(self.root_dir, subset="training") - - num_samples = 0 - for i, (data, sample_rate, label, speaker_id, utterance_number) in enumerate( - dataset - ): - self.assertEqual(data, self.train_samples[i][0], atol=5e-5, rtol=1e-8) - assert sample_rate == self.train_samples[i][1] - assert label == self.train_samples[i][2] - assert speaker_id == self.train_samples[i][3] - assert utterance_number == self.train_samples[i][4] - num_samples += 1 - - assert num_samples == len(self.train_samples) + self._testSpeechCommands(dataset, self.train_samples) def testSpeechCommandsSubsetValid(self): dataset = speechcommands.SPEECHCOMMANDS(self.root_dir, subset="validation") - - num_samples = 0 - for i, (data, sample_rate, label, speaker_id, utterance_number) in enumerate( - dataset - ): - self.assertEqual(data, self.valid_samples[i][0], atol=5e-5, rtol=1e-8) - assert sample_rate == self.valid_samples[i][1] - assert label == self.valid_samples[i][2] - assert speaker_id == self.valid_samples[i][3] - assert utterance_number == self.valid_samples[i][4] - num_samples += 1 - - assert num_samples == len(self.valid_samples) + self._testSpeechCommands(dataset, self.valid_samples) def testSpeechCommandsSubsetTest(self): dataset = speechcommands.SPEECHCOMMANDS(self.root_dir, subset="testing") - - num_samples = 0 - for i, (data, sample_rate, label, speaker_id, utterance_number) in enumerate( - dataset - ): - self.assertEqual(data, self.test_samples[i][0], atol=5e-5, rtol=1e-8) - assert sample_rate == self.test_samples[i][1] - assert label == self.test_samples[i][2] - assert speaker_id == self.test_samples[i][3] - assert utterance_number == self.test_samples[i][4] - num_samples += 1 - - assert num_samples == len(self.test_samples) + self._testSpeechCommands(dataset, self.test_samples) def testSpeechCommandsSum(self): dataset_all = speechcommands.SPEECHCOMMANDS(self.root_dir) diff --git a/test/torchaudio_unittest/datasets/tedlium_test.py b/test/torchaudio_unittest/datasets/tedlium_test.py index f5becb53ab..3ea4d25eab 100644 --- a/test/torchaudio_unittest/datasets/tedlium_test.py +++ b/test/torchaudio_unittest/datasets/tedlium_test.py @@ -1,6 +1,7 @@ import os import platform import unittest +from pathlib import Path from torchaudio.datasets import tedlium @@ -93,9 +94,7 @@ def setUpClass(cls): cls.samples[release].append(sample) seed += 1 - def test_tedlium_release1(self): - release = "release1" - dataset = tedlium.TEDLIUM(self.root_dir, release=release) + def _test_tedlium(self, dataset, release): num_samples = 0 for i, (data, sample_rate, transcript, talk_id, speaker_id, identifier) in enumerate(dataset): self.assertEqual(data, self.samples[release][i][0], atol=5e-5, rtol=1e-8) @@ -113,45 +112,25 @@ def test_tedlium_release1(self): phoenemes = [f"{key} {' '.join(value)}" for key, value in phoneme_dict.items()] assert phoenemes == PHONEME - def test_tedlium_release2(self): - release = "release2" + def test_tedlium_release1_str(self): + release = "release1" dataset = tedlium.TEDLIUM(self.root_dir, release=release) - num_samples = 0 - for i, (data, sample_rate, transcript, talk_id, speaker_id, identifier) in enumerate(dataset): - self.assertEqual(data, self.samples[release][i][0], atol=5e-5, rtol=1e-8) - assert sample_rate == self.samples[release][i][1] - assert transcript == self.samples[release][i][2] - assert talk_id == self.samples[release][i][3] - assert speaker_id == self.samples[release][i][4] - assert identifier == self.samples[release][i][5] - num_samples += 1 + self._test_tedlium(dataset, release) - assert num_samples == len(self.samples[release]) + def test_tedlium_release1_path(self): + release = "release1" + dataset = tedlium.TEDLIUM(Path(self.root_dir), release=release) + self._test_tedlium(dataset, release) - dataset._dict_path = os.path.join(dataset._path, f"{release}.dic") - phoneme_dict = dataset.phoneme_dict - phoenemes = [f"{key} {' '.join(value)}" for key, value in phoneme_dict.items()] - assert phoenemes == PHONEME + def test_tedlium_release2(self): + release = "release2" + dataset = tedlium.TEDLIUM(self.root_dir, release=release) + self._test_tedlium(dataset, release) def test_tedlium_release3(self): release = "release3" dataset = tedlium.TEDLIUM(self.root_dir, release=release) - num_samples = 0 - for i, (data, sample_rate, transcript, talk_id, speaker_id, identifier) in enumerate(dataset): - self.assertEqual(data, self.samples[release][i][0], atol=5e-5, rtol=1e-8) - assert sample_rate == self.samples[release][i][1] - assert transcript == self.samples[release][i][2] - assert talk_id == self.samples[release][i][3] - assert speaker_id == self.samples[release][i][4] - assert identifier == self.samples[release][i][5] - num_samples += 1 - - assert num_samples == len(self.samples[release]) - - dataset._dict_path = os.path.join(dataset._path, f"{release}.dic") - phoneme_dict = dataset.phoneme_dict - phoenemes = [f"{key} {' '.join(value)}" for key, value in phoneme_dict.items()] - assert phoenemes == PHONEME + self._test_tedlium(dataset, release) class TestTedliumSoundfile(Tedlium, TorchaudioTestCase): diff --git a/test/torchaudio_unittest/datasets/utils_test.py b/test/torchaudio_unittest/datasets/utils_test.py index f75ae2319c..a9e13a1e38 100644 --- a/test/torchaudio_unittest/datasets/utils_test.py +++ b/test/torchaudio_unittest/datasets/utils_test.py @@ -54,7 +54,7 @@ class TestIterator(TorchaudioTestCase): path = get_asset_path() def test_disckcache_iterator(self): - data = COMMONVOICE(self.path, url="tatar") + data = COMMONVOICE(self.path, version="cv-corpus-4-2019-12-10", language="tatar") data = dataset_utils.diskcache_iterator(data) # Save data[0] @@ -62,7 +62,7 @@ def test_disckcache_iterator(self): data[0] def test_bg_iterator(self): - data = COMMONVOICE(self.path, url="tatar") + data = COMMONVOICE(self.path, version="cv-corpus-4-2019-12-10", language="tatar") data = dataset_utils.bg_iterator(data, 5) for _ in data: pass diff --git a/test/torchaudio_unittest/sox_effect/dataset_test.py b/test/torchaudio_unittest/sox_effect/dataset_test.py index 647e4d2a81..7e89960186 100644 --- a/test/torchaudio_unittest/sox_effect/dataset_test.py +++ b/test/torchaudio_unittest/sox_effect/dataset_test.py @@ -2,6 +2,7 @@ import platform from unittest import skipIf from typing import List, Tuple +from concurrent.futures import ProcessPoolExecutor import numpy as np import torch @@ -122,3 +123,36 @@ def test_apply_effects_tensor(self): ) for batch in loader: assert batch.shape == (32, 2, 2 * sample_rate) + + +def speed(path): + wav, sample_rate = torchaudio.backend.sox_io_backend.load(path) + effects = [ + ['speed', '1.03756523535464655'], + ['rate', f'{sample_rate}'], + ] + return torchaudio.sox_effects.apply_effects_tensor(wav, sample_rate, effects)[0] + + +@skipIfNoExtension +class TestProcessPoolExecutor(TempDirMixin, PytorchTestCase): + backend = "sox_io" + + def setUp(self): + sample_rate = 16000 + self.flist = [] + for i in range(10): + path = self.get_temp_path(f'{i}.wav') + data = get_whitenoise(n_channels=1, sample_rate=sample_rate, duration=1, dtype='float') + save_wav(path, data, sample_rate) + self.flist.append(path) + + def test_executor(self): + """Test that apply_effects_tensor with speed + rate does not crush + + https://github.com/pytorch/audio/issues/1021 + """ + executor = ProcessPoolExecutor(1) + futures = [executor.submit(speed, path) for path in self.flist] + for future in futures: + future.result() diff --git a/test/torchaudio_unittest/sox_effect/sox_effect_test.py b/test/torchaudio_unittest/sox_effect/sox_effect_test.py index 27740ca576..c5b57eaf5f 100644 --- a/test/torchaudio_unittest/sox_effect/sox_effect_test.py +++ b/test/torchaudio_unittest/sox_effect/sox_effect_test.py @@ -1,4 +1,5 @@ import itertools +from pathlib import Path from torchaudio import sox_effects from parameterized import parameterized @@ -104,7 +105,7 @@ def test_apply_no_effect(self, dtype, sample_rate, num_channels, channels_first) load_params("sox_effect_test_args.json"), name_func=lambda f, i, p: f'{f.__name__}_{i}_{p.args[0]["effects"][0][0]}', ) - def test_apply_effects(self, args): + def test_apply_effects_str(self, args): """`apply_effects_file` should return identical data as sox command""" dtype = 'int32' channels_first = True @@ -127,6 +128,29 @@ def test_apply_effects(self, args): assert sr == expected_sr self.assertEqual(found, expected) + def test_apply_effects_path(self): + """`apply_effects_file` should return identical data as sox command when file path is given as a Path Object""" + dtype = 'int32' + channels_first = True + effects = [["hilbert"]] + num_channels = 2 + input_sr = 8000 + output_sr = 8000 + + input_path = self.get_temp_path('input.wav') + reference_path = self.get_temp_path('reference.wav') + data = get_wav_data(dtype, num_channels, channels_first=channels_first) + save_wav(input_path, data, input_sr, channels_first=channels_first) + sox_utils.run_sox_effect( + input_path, reference_path, effects, output_sample_rate=output_sr) + + expected, expected_sr = load_wav(reference_path) + found, sr = sox_effects.apply_effects_file( + Path(input_path), effects, normalize=False, channels_first=channels_first) + + assert sr == expected_sr + self.assertEqual(found, expected) + @skipIfNoExtension class TestFileFormats(TempDirMixin, PytorchTestCase): diff --git a/test/torchaudio_unittest/sox_io_backend/info_test.py b/test/torchaudio_unittest/sox_io_backend/info_test.py index b16203cfd3..9b928f3ae0 100644 --- a/test/torchaudio_unittest/sox_io_backend/info_test.py +++ b/test/torchaudio_unittest/sox_io_backend/info_test.py @@ -122,6 +122,36 @@ def test_sphere(self, sample_rate, num_channels): assert info.num_frames == sample_rate * duration assert info.num_channels == num_channels + @parameterized.expand(list(itertools.product( + ['float32', 'int32', 'int16', 'uint8'], + [8000, 16000], + [1, 2], + )), name_func=name_func) + def test_amb(self, dtype, sample_rate, num_channels): + """`sox_io_backend.info` can check amb file correctly""" + duration = 1 + path = self.get_temp_path('data.amb') + sox_utils.gen_audio_file( + path, sample_rate, num_channels, + bit_depth=sox_utils.get_bit_depth(dtype), duration=duration) + info = sox_io_backend.info(path) + assert info.sample_rate == sample_rate + assert info.num_frames == sample_rate * duration + assert info.num_channels == num_channels + + def test_amr_nb(self): + """`sox_io_backend.info` can check amr-nb file correctly""" + duration = 1 + num_channels = 1 + sample_rate = 8000 + path = self.get_temp_path('data.amr-nb') + sox_utils.gen_audio_file( + path, sample_rate=sample_rate, num_channels=num_channels, bit_depth=16, duration=duration) + info = sox_io_backend.info(path) + assert info.sample_rate == sample_rate + assert info.num_frames == sample_rate * duration + assert info.num_channels == num_channels + @skipIfNoExtension class TestInfoOpus(PytorchTestCase): diff --git a/test/torchaudio_unittest/sox_io_backend/load_test.py b/test/torchaudio_unittest/sox_io_backend/load_test.py index 59bcaea386..156ad9ad3e 100644 --- a/test/torchaudio_unittest/sox_io_backend/load_test.py +++ b/test/torchaudio_unittest/sox_io_backend/load_test.py @@ -142,6 +142,53 @@ def assert_sphere(self, sample_rate, num_channels, duration): assert sr == sample_rate self.assertEqual(data, data_ref, atol=4e-05, rtol=1.3e-06) + def assert_amb(self, dtype, sample_rate, num_channels, normalize, duration): + """`sox_io_backend.load` can load amb format. + + This test takes the same strategy as mp3 to compare the result + """ + path = self.get_temp_path('1.original.amb') + ref_path = self.get_temp_path('2.reference.wav') + + # 1. Generate amb with sox + sox_utils.gen_audio_file( + path, sample_rate, num_channels, + encoding=sox_utils.get_encoding(dtype), + bit_depth=sox_utils.get_bit_depth(dtype), duration=duration) + # 2. Convert to wav with sox + sox_utils.convert_audio_file(path, ref_path) + # 3. Load amb with torchaudio + data, sr = sox_io_backend.load(path, normalize=normalize) + # 4. Load wav with scipy + data_ref = load_wav(ref_path, normalize=normalize)[0] + # 5. Compare + assert sr == sample_rate + self.assertEqual(data, data_ref, atol=4e-05, rtol=1.3e-06) + + def assert_amr_nb(self, duration): + """`sox_io_backend.load` can load amr-nb format. + + This test takes the same strategy as mp3 to compare the result + """ + sample_rate = 8000 + num_channels = 1 + path = self.get_temp_path('1.original.amr-nb') + ref_path = self.get_temp_path('2.reference.wav') + + # 1. Generate amr-nb with sox + sox_utils.gen_audio_file( + path, sample_rate, num_channels, + bit_depth=32, duration=duration) + # 2. Convert to wav with sox + sox_utils.convert_audio_file(path, ref_path) + # 3. Load amr-nb with torchaudio + data, sr = sox_io_backend.load(path) + # 4. Load wav with scipy + data_ref = load_wav(ref_path)[0] + # 5. Compare + assert sr == sample_rate + self.assertEqual(data, data_ref, atol=4e-05, rtol=1.3e-06) + @skipIfNoExec('sox') @skipIfNoExtension @@ -260,6 +307,20 @@ def test_sphere(self, sample_rate, num_channels): """`sox_io_backend.load` can load sph format correctly.""" self.assert_sphere(sample_rate, num_channels, duration=1) + @parameterized.expand(list(itertools.product( + ['float32', 'int32', 'int16'], + [8000, 16000], + [1, 2], + [False, True], + )), name_func=name_func) + def test_amb(self, dtype, sample_rate, num_channels, normalize): + """`sox_io_backend.load` can load sph format correctly.""" + self.assert_amb(dtype, sample_rate, num_channels, normalize, duration=1) + + def test_amr_nb(self): + """`sox_io_backend.load` can load amr_nb format correctly.""" + self.assert_amr_nb(duration=1) + @skipIfNoExec('sox') @skipIfNoExtension diff --git a/test/torchaudio_unittest/sox_io_backend/save_test.py b/test/torchaudio_unittest/sox_io_backend/save_test.py index deed1aa1ad..b0ee25e01c 100644 --- a/test/torchaudio_unittest/sox_io_backend/save_test.py +++ b/test/torchaudio_unittest/sox_io_backend/save_test.py @@ -200,6 +200,68 @@ def assert_sphere(self, sample_rate, num_channels, duration): self.assertEqual(found, expected) + def assert_amb(self, dtype, sample_rate, num_channels, duration): + """`sox_io_backend.save` can save amb format. + + This test takes the same strategy as mp3 to compare the result + """ + src_path = self.get_temp_path('1.reference.wav') + amb_path = self.get_temp_path('2.1.torchaudio.amb') + wav_path = self.get_temp_path('2.2.torchaudio.wav') + amb_path_sox = self.get_temp_path('3.1.sox.amb') + wav_path_sox = self.get_temp_path('3.2.sox.wav') + + # 1. Generate original wav + data = get_wav_data(dtype, num_channels, normalize=False, num_frames=duration * sample_rate) + save_wav(src_path, data, sample_rate) + # 2.1. Convert the original wav to amb with torchaudio + sox_io_backend.save(amb_path, load_wav(src_path, normalize=False)[0], sample_rate) + # 2.2. Convert the amb to wav with Sox + sox_utils.convert_audio_file(amb_path, wav_path) + # 2.3. Load + found = load_wav(wav_path)[0] + + # 3.1. Convert the original wav to amb with SoX + sox_utils.convert_audio_file(src_path, amb_path_sox) + # 3.2. Convert the amb to wav with Sox + sox_utils.convert_audio_file(amb_path_sox, wav_path_sox) + # 3.3. Load + expected = load_wav(wav_path_sox)[0] + + self.assertEqual(found, expected) + + def assert_amr_nb(self, duration): + """`sox_io_backend.save` can save amr_nb format. + + This test takes the same strategy as mp3 to compare the result + """ + sample_rate = 8000 + num_channels = 1 + src_path = self.get_temp_path('1.reference.wav') + amr_path = self.get_temp_path('2.1.torchaudio.amr-nb') + wav_path = self.get_temp_path('2.2.torchaudio.wav') + amr_path_sox = self.get_temp_path('3.1.sox.amr-nb') + wav_path_sox = self.get_temp_path('3.2.sox.wav') + + # 1. Generate original wav + data = get_wav_data('int16', num_channels, normalize=False, num_frames=duration * sample_rate) + save_wav(src_path, data, sample_rate) + # 2.1. Convert the original wav to amr_nb with torchaudio + sox_io_backend.save(amr_path, load_wav(src_path, normalize=False)[0], sample_rate) + # 2.2. Convert the amr_nb to wav with Sox + sox_utils.convert_audio_file(amr_path, wav_path) + # 2.3. Load + found = load_wav(wav_path)[0] + + # 3.1. Convert the original wav to amr_nb with SoX + sox_utils.convert_audio_file(src_path, amr_path_sox) + # 3.2. Convert the amr_nb to wav with Sox + sox_utils.convert_audio_file(amr_path_sox, wav_path_sox) + # 3.3. Load + expected = load_wav(wav_path_sox)[0] + + self.assertEqual(found, expected) + @skipIfNoExec('sox') @skipIfNoExtension @@ -302,6 +364,19 @@ def test_sphere(self, sample_rate, num_channels): """`sox_io_backend.save` can save sph format.""" self.assert_sphere(sample_rate, num_channels, duration=1) + @parameterized.expand(list(itertools.product( + ['float32', 'int32', 'int16', 'uint8'], + [8000, 16000], + [1, 2], + )), name_func=name_func) + def test_amb(self, dtype, sample_rate, num_channels): + """`sox_io_backend.save` can save amb format.""" + self.assert_amb(dtype, sample_rate, num_channels, duration=1) + + def test_amr_nb(self): + """`sox_io_backend.save` can save amr-nb format.""" + self.assert_amr_nb(duration=1) + @skipIfNoExec('sox') @skipIfNoExtension diff --git a/third_party/CMakeLists.txt b/third_party/CMakeLists.txt index c4be4cb7b0..ad0eac582b 100644 --- a/third_party/CMakeLists.txt +++ b/third_party/CMakeLists.txt @@ -16,6 +16,14 @@ ExternalProject_Add(libmad CONFIGURE_COMMAND ${CMAKE_CURRENT_SOURCE_DIR}/src/libmad/configure ${COMMON_ARGS} ) +ExternalProject_Add(amr + PREFIX ${CMAKE_CURRENT_SOURCE_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 + CONFIGURE_COMMAND ${CMAKE_CURRENT_SOURCE_DIR}/src/amr/configure ${COMMON_ARGS} +) + ExternalProject_Add(libmp3lame PREFIX ${CMAKE_CURRENT_SOURCE_DIR} DOWNLOAD_DIR ${ARCHIVE_DIR} @@ -72,9 +80,11 @@ ExternalProject_Add(opusfile ExternalProject_Add(libsox PREFIX ${CMAKE_CURRENT_SOURCE_DIR} - DEPENDS libogg libflac libvorbis opusfile libmp3lame libmad + DEPENDS libogg libflac libvorbis opusfile libmp3lame libmad amr 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 - CONFIGURE_COMMAND ${CMAKE_CURRENT_SOURCE_DIR}/build_codec_helper.sh ${CMAKE_CURRENT_SOURCE_DIR}/src/libsox/configure ${COMMON_ARGS} --with-lame --with-flac --with-mad --with-oggvorbis --without-alsa --without-coreaudio --without-png --without-oss --without-sndfile --with-opus + # 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 + CONFIGURE_COMMAND ${CMAKE_CURRENT_SOURCE_DIR}/build_codec_helper.sh ${CMAKE_CURRENT_SOURCE_DIR}/src/libsox/configure ${COMMON_ARGS} --with-lame --with-flac --with-mad --with-oggvorbis --without-alsa --without-coreaudio --without-png --without-oss --without-sndfile --with-opus --with-amrwb --with-amrnb --disable-openmp ) diff --git a/torchaudio/backend/sox_io_backend.py b/torchaudio/backend/sox_io_backend.py index 1e57e92834..5293223977 100644 --- a/torchaudio/backend/sox_io_backend.py +++ b/torchaudio/backend/sox_io_backend.py @@ -40,18 +40,19 @@ def load( This function can handle all the codecs that underlying libsox can handle, however it is tested on the following formats; - * WAV + * WAV, AMB * 32-bit floating-point * 32-bit signed integer * 16-bit signed integer - * 8-bit unsigned integer + * 8-bit unsigned integer (WAV only) * MP3 * FLAC * OGG/VORBIS * OPUS * SPHERE + * AMR-NB To load ``MP3``, ``FLAC``, ``OGG/VORBIS``, ``OPUS`` and other codecs ``libsox`` does not handle natively, your installation of ``torchaudio`` has to be linked to ``libsox`` @@ -119,7 +120,7 @@ def save( Note: Supported formats are; - * WAV + * WAV, AMB * 32-bit floating-point * 32-bit signed integer @@ -130,6 +131,7 @@ def save( * FLAC * OGG/VORBIS * SPHERE + * AMR-NB To save ``MP3``, ``FLAC``, ``OGG/VORBIS``, and other codecs ``libsox`` does not handle natively, your installation of ``torchaudio`` has to be linked to ``libsox`` @@ -160,7 +162,7 @@ def save( filepath = str(filepath) if compression is None: ext = str(filepath).split('.')[-1].lower() - if ext in ['wav', 'sph']: + if ext in ['wav', 'sph', 'amb', 'amr-nb']: compression = 0. elif ext == 'mp3': compression = -4.5 diff --git a/torchaudio/csrc/sox_effects.cpp b/torchaudio/csrc/sox_effects.cpp index 8a7cc7c494..7bd24b6bc2 100644 --- a/torchaudio/csrc/sox_effects.cpp +++ b/torchaudio/csrc/sox_effects.cpp @@ -91,8 +91,8 @@ c10::intrusive_ptr apply_effects_tensor( c10::intrusive_ptr apply_effects_file( const std::string path, std::vector> effects, - const bool normalize, - const bool channels_first) { + c10::optional& normalize, + c10::optional& channels_first) { // Open input file SoxFormat sf(sox_open_read( path.c_str(), @@ -121,16 +121,17 @@ c10::intrusive_ptr apply_effects_file( chain.run(); // Create tensor from buffer + bool channels_first_ = channels_first.value_or(true); auto tensor = convert_to_tensor( /*buffer=*/out_buffer.data(), /*num_samples=*/out_buffer.size(), /*num_channels=*/chain.getOutputNumChannels(), dtype, - normalize, - channels_first); + normalize.value_or(true), + channels_first_); return c10::make_intrusive( - tensor, chain.getOutputSampleRate(), channels_first); + tensor, chain.getOutputSampleRate(), channels_first_); } } // namespace sox_effects diff --git a/torchaudio/csrc/sox_effects.h b/torchaudio/csrc/sox_effects.h index 7883a7beac..669c86ac39 100644 --- a/torchaudio/csrc/sox_effects.h +++ b/torchaudio/csrc/sox_effects.h @@ -18,8 +18,8 @@ c10::intrusive_ptr apply_effects_tensor( c10::intrusive_ptr apply_effects_file( const std::string path, std::vector> effects, - const bool normalize = true, - const bool channels_first = true); + c10::optional& normalize, + c10::optional& channels_first); } // namespace sox_effects } // namespace torchaudio diff --git a/torchaudio/csrc/sox_io.cpp b/torchaudio/csrc/sox_io.cpp index 4092d215d0..9acab1c030 100644 --- a/torchaudio/csrc/sox_io.cpp +++ b/torchaudio/csrc/sox_io.cpp @@ -49,30 +49,32 @@ c10::intrusive_ptr get_info(const std::string& path) { c10::intrusive_ptr load_audio_file( const std::string& path, - const int64_t frame_offset, - const int64_t num_frames, - const bool normalize, - const bool channels_first) { - if (frame_offset < 0) { + c10::optional& frame_offset, + c10::optional& num_frames, + c10::optional& normalize, + c10::optional& channels_first) { + const auto offset = frame_offset.value_or(0); + if (offset < 0) { throw std::runtime_error( "Invalid argument: frame_offset must be non-negative."); } - if (num_frames == 0 || num_frames < -1) { + const auto frames = num_frames.value_or(-1); + if (frames == 0 || frames < -1) { throw std::runtime_error( "Invalid argument: num_frames must be -1 or greater than 0."); } std::vector> effects; - if (num_frames != -1) { - std::ostringstream offset, frames; - offset << frame_offset << "s"; - frames << "+" << num_frames << "s"; + if (frames != -1) { + std::ostringstream os_offset, os_frames; + os_offset << offset << "s"; + os_frames << "+" << frames << "s"; effects.emplace_back( - std::vector{"trim", offset.str(), frames.str()}); - } else if (frame_offset != 0) { - std::ostringstream offset; - offset << frame_offset << "s"; - effects.emplace_back(std::vector{"trim", offset.str()}); + std::vector{"trim", os_offset.str(), os_frames.str()}); + } else if (offset != 0) { + std::ostringstream os_offset; + os_offset << offset << "s"; + effects.emplace_back(std::vector{"trim", os_offset.str()}); } return torchaudio::sox_effects::apply_effects_file( @@ -83,11 +85,17 @@ void save_audio_file( const std::string& file_name, const c10::intrusive_ptr& signal, const double compression) { - const auto tensor = signal->getTensor(); + auto tensor = signal->tensor; validate_input_tensor(tensor); const auto filetype = get_filetype(file_name); + if (filetype == "amr-nb") { + const auto num_channels = tensor.size(signal->channels_first ? 0 : 1); + TORCH_CHECK( + num_channels == 1, "amr-nb format only supports single channel audio."); + tensor = (unnormalize_wav(tensor) / 65536).to(torch::kInt16); + } const auto signal_info = get_signalinfo(signal.get(), filetype); const auto encoding_info = get_encodinginfo(filetype, tensor.dtype(), compression); diff --git a/torchaudio/csrc/sox_io.h b/torchaudio/csrc/sox_io.h index 5288e911e8..d62997243e 100644 --- a/torchaudio/csrc/sox_io.h +++ b/torchaudio/csrc/sox_io.h @@ -25,10 +25,10 @@ c10::intrusive_ptr get_info(const std::string& path); c10::intrusive_ptr load_audio_file( const std::string& path, - const int64_t frame_offset = 0, - const int64_t num_frames = -1, - const bool normalize = true, - const bool channels_first = true); + c10::optional& frame_offset, + c10::optional& num_frames, + c10::optional& normalize, + c10::optional& channels_first); void save_audio_file( const std::string& file_name, diff --git a/torchaudio/csrc/sox_utils.cpp b/torchaudio/csrc/sox_utils.cpp index 25fe376c8b..656cc63348 100644 --- a/torchaudio/csrc/sox_utils.cpp +++ b/torchaudio/csrc/sox_utils.cpp @@ -223,7 +223,7 @@ sox_encoding_t get_encoding( return SOX_ENCODING_FLAC; if (filetype == "ogg" || filetype == "vorbis") return SOX_ENCODING_VORBIS; - if (filetype == "wav") { + if (filetype == "wav" || filetype == "amb") { if (dtype == torch::kUInt8) return SOX_ENCODING_UNSIGNED; if (dtype == torch::kInt16) @@ -236,7 +236,9 @@ sox_encoding_t get_encoding( } if (filetype == "sph") return SOX_ENCODING_SIGN2; - throw std::runtime_error("Unsupported file type."); + if (filetype == "amr-nb") + return SOX_ENCODING_AMR_NB; + throw std::runtime_error("Unsupported file type: " + filetype); } unsigned get_precision( @@ -248,7 +250,7 @@ unsigned get_precision( return 24; if (filetype == "ogg" || filetype == "vorbis") return SOX_UNSPEC; - if (filetype == "wav") { + if (filetype == "wav" || filetype == "amb") { if (dtype == torch::kUInt8) return 8; if (dtype == torch::kInt16) @@ -261,7 +263,13 @@ unsigned get_precision( } if (filetype == "sph") return 32; - throw std::runtime_error("Unsupported file type."); + if (filetype == "amr-nb") { + TORCH_INTERNAL_ASSERT( + dtype == torch::kInt16, + "When saving to AMR-NB format, the input tensor must be int16 type."); + return 16; + } + throw std::runtime_error("Unsupported file type: " + filetype); } sox_signalinfo_t get_signalinfo( @@ -287,11 +295,13 @@ sox_encodinginfo_t get_encodinginfo( return compression; if (filetype == "ogg" || filetype == "vorbis") return compression; - if (filetype == "wav") + if (filetype == "wav" || filetype == "amb") return 0.; if (filetype == "sph") return 0.; - throw std::runtime_error("Unsupported file type."); + if (filetype == "amr-nb") + return 0.; + throw std::runtime_error("Unsupported file type: " + filetype); }(); return sox_encodinginfo_t{/*encoding=*/get_encoding(filetype, dtype), diff --git a/torchaudio/datasets/commonvoice.py b/torchaudio/datasets/commonvoice.py index 963777cf38..1a1f4273a4 100644 --- a/torchaudio/datasets/commonvoice.py +++ b/torchaudio/datasets/commonvoice.py @@ -1,9 +1,10 @@ import os +import warnings from pathlib import Path -from typing import List, Dict, Tuple, Union +from typing import List, Dict, Tuple, Optional, Union import torchaudio -from torchaudio.datasets.utils import download_url, extract_archive, unicode_csv_reader +from torchaudio.datasets.utils import extract_archive, unicode_csv_reader, validate_file from torch import Tensor from torch.utils.data import Dataset @@ -16,68 +17,39 @@ # validated.tsv FOLDER_IN_ARCHIVE = "CommonVoice" -URL = "english" -VERSION = "cv-corpus-4-2019-12-10" +LANGUAGE = "english" +VERSION = "cv-corpus-5.1-2020-06-22" TSV = "train.tsv" _CHECKSUMS = { - "https://voice-prod-bundler-ee1969a6ce8178826482b88e843c335139bd3fb4.s3.amazonaws.com/cv-corpus-3/tt.tar.gz": - None, - "https://voice-prod-bundler-ee1969a6ce8178826482b88e843c335139bd3fb4.s3.amazonaws.com/cv-corpus-3/en.tar.gz": - None, - "https://voice-prod-bundler-ee1969a6ce8178826482b88e843c335139bd3fb4.s3.amazonaws.com/cv-corpus-3/de.tar.gz": - None, - "https://voice-prod-bundler-ee1969a6ce8178826482b88e843c335139bd3fb4.s3.amazonaws.com/cv-corpus-3/fr.tar.gz": - None, - "https://voice-prod-bundler-ee1969a6ce8178826482b88e843c335139bd3fb4.s3.amazonaws.com/cv-corpus-3/cy.tar.gz": - None, - "https://voice-prod-bundler-ee1969a6ce8178826482b88e843c335139bd3fb4.s3.amazonaws.com/cv-corpus-3/br.tar.gz": - None, - "https://voice-prod-bundler-ee1969a6ce8178826482b88e843c335139bd3fb4.s3.amazonaws.com/cv-corpus-3/cv.tar.gz": - None, - "https://voice-prod-bundler-ee1969a6ce8178826482b88e843c335139bd3fb4.s3.amazonaws.com/cv-corpus-3/tr.tar.gz": - None, - "https://voice-prod-bundler-ee1969a6ce8178826482b88e843c335139bd3fb4.s3.amazonaws.com/cv-corpus-3/ky.tar.gz": - None, - "https://voice-prod-bundler-ee1969a6ce8178826482b88e843c335139bd3fb4.s3.amazonaws.com/cv-corpus-3/ga-IE.tar.gz": - None, - "https://voice-prod-bundler-ee1969a6ce8178826482b88e843c335139bd3fb4.s3.amazonaws.com/cv-corpus-3/kab.tar.gz": - None, - "https://voice-prod-bundler-ee1969a6ce8178826482b88e843c335139bd3fb4.s3.amazonaws.com/cv-corpus-3/ca.tar.gz": - None, - "https://voice-prod-bundler-ee1969a6ce8178826482b88e843c335139bd3fb4.s3.amazonaws.com/cv-corpus-3/zh-TW.tar.gz": - None, - "https://voice-prod-bundler-ee1969a6ce8178826482b88e843c335139bd3fb4.s3.amazonaws.com/cv-corpus-3/sl.tar.gz": - None, - "https://voice-prod-bundler-ee1969a6ce8178826482b88e843c335139bd3fb4.s3.amazonaws.com/cv-corpus-3/it.tar.gz": - None, - "https://voice-prod-bundler-ee1969a6ce8178826482b88e843c335139bd3fb4.s3.amazonaws.com/cv-corpus-3/nl.tar.gz": - None, - "https://voice-prod-bundler-ee1969a6ce8178826482b88e843c335139bd3fb4.s3.amazonaws.com/cv-corpus-3/cnh.tar.gz": - None, - "https://voice-prod-bundler-ee1969a6ce8178826482b88e843c335139bd3fb4.s3.amazonaws.com/cv-corpus-3/eo.tar.gz": - None, - "https://voice-prod-bundler-ee1969a6ce8178826482b88e843c335139bd3fb4.s3.amazonaws.com/cv-corpus-3/et.tar.gz": - None, - "https://voice-prod-bundler-ee1969a6ce8178826482b88e843c335139bd3fb4.s3.amazonaws.com/cv-corpus-3/fa.tar.gz": - None, - "https://voice-prod-bundler-ee1969a6ce8178826482b88e843c335139bd3fb4.s3.amazonaws.com/cv-corpus-3/eu.tar.gz": - None, - "https://voice-prod-bundler-ee1969a6ce8178826482b88e843c335139bd3fb4.s3.amazonaws.com/cv-corpus-3/es.tar.gz": - None, - "https://voice-prod-bundler-ee1969a6ce8178826482b88e843c335139bd3fb4.s3.amazonaws.com/cv-corpus-3/zh-CN.tar.gz": - None, - "https://voice-prod-bundler-ee1969a6ce8178826482b88e843c335139bd3fb4.s3.amazonaws.com/cv-corpus-3/mn.tar.gz": - None, - "https://voice-prod-bundler-ee1969a6ce8178826482b88e843c335139bd3fb4.s3.amazonaws.com/cv-corpus-3/sah.tar.gz": - None, - "https://voice-prod-bundler-ee1969a6ce8178826482b88e843c335139bd3fb4.s3.amazonaws.com/cv-corpus-3/dv.tar.gz": - None, - "https://voice-prod-bundler-ee1969a6ce8178826482b88e843c335139bd3fb4.s3.amazonaws.com/cv-corpus-3/rw.tar.gz": - None, - "https://voice-prod-bundler-ee1969a6ce8178826482b88e843c335139bd3fb4.s3.amazonaws.com/cv-corpus-3/sv-SE.tar.gz": - None, - "https://voice-prod-bundler-ee1969a6ce8178826482b88e843c335139bd3fb4.s3.amazonaws.com/cv-corpus-3/ru.tar.gz": - None + "cv-corpus-5.1-2020-06-22/tt.tar.gz": None, + "cv-corpus-5.1-2020-06-22/en.tar.gz": None, + "cv-corpus-5.1-2020-06-22/de.tar.gz": None, + "cv-corpus-5.1-2020-06-22/fr.tar.gz": None, + "cv-corpus-5.1-2020-06-22/cy.tar.gz": None, + "cv-corpus-5.1-2020-06-22/br.tar.gz": None, + "cv-corpus-5.1-2020-06-22/cv.tar.gz": None, + "cv-corpus-5.1-2020-06-22/tr.tar.gz": None, + "cv-corpus-5.1-2020-06-22/ky.tar.gz": None, + "cv-corpus-5.1-2020-06-22/ga-IE.tar.gz": None, + "cv-corpus-5.1-2020-06-22/kab.tar.gz": None, + "cv-corpus-5.1-2020-06-22/ca.tar.gz": None, + "cv-corpus-5.1-2020-06-22/zh-TW.tar.gz": None, + "cv-corpus-5.1-2020-06-22/sl.tar.gz": None, + "cv-corpus-5.1-2020-06-22/it.tar.gz": None, + "cv-corpus-5.1-2020-06-22/nl.tar.gz": None, + "cv-corpus-5.1-2020-06-22/cnh.tar.gz": None, + "cv-corpus-5.1-2020-06-22/eo.tar.gz": None, + "cv-corpus-5.1-2020-06-22/et.tar.gz": None, + "cv-corpus-5.1-2020-06-22/fa.tar.gz": None, + "cv-corpus-5.1-2020-06-22/eu.tar.gz": None, + "cv-corpus-5.1-2020-06-22/es.tar.gz": None, + "cv-corpus-5.1-2020-06-22/zh-CN.tar.gz": None, + "cv-corpus-5.1-2020-06-22/mn.tar.gz": None, + "cv-corpus-5.1-2020-06-22/sah.tar.gz": None, + "cv-corpus-5.1-2020-06-22/dv.tar.gz": None, + "cv-corpus-5.1-2020-06-22/rw.tar.gz": None, + "cv-corpus-5.1-2020-06-22/sv-SE.tar.gz": None, + "cv-corpus-5.1-2020-06-22/ru.tar.gz": None, } @@ -101,15 +73,18 @@ def load_commonvoice_item(line: List[str], class COMMONVOICE(Dataset): - """Create a Dataset for CommonVoice. + """Create a Dataset for `CommonVoice `_. Args: root (str or Path): Path to the directory where the dataset is found or downloaded. tsv (str, optional): The name of the tsv file used to construct the metadata. (default: ``"train.tsv"``) - url (str, optional): The URL to download the dataset from, or the language of - the dataset to download. (default: ``"english"``). - Allowed language values are ``"tatar"``, ``"english"``, ``"german"``, + url (str, optional): Deprecated. + folder_in_archive (str, optional): The top-level directory of the dataset. + version (str): Version string. (default: ``"cv-corpus-5.1-2020-06-22"``) + language (str, optional): Language of the dataset. (default: None) + The following values are mapped to their corresponding shortened version: + ``"tatar"``, ``"english"``, ``"german"``, ``"french"``, ``"welsh"``, ``"breton"``, ``"chuvash"``, ``"turkish"``, ``"kyrgyz"``, ``"irish"``, ``"kabyle"``, ``"catalan"``, ``"taiwanese"``, ``"slovenian"``, ``"italian"``, ``"dutch"``, ``"hakha chin"``, ``"esperanto"``, ``"estonian"``, @@ -118,11 +93,8 @@ class COMMONVOICE(Dataset): ``"russian"``, ``"indonesian"``, ``"arabic"``, ``"tamil"``, ``"interlingua"``, ``"latvian"``, ``"japanese"``, ``"votic"``, ``"abkhaz"``, ``"cantonese"`` and ``"romansh sursilvan"``. - folder_in_archive (str, optional): The top-level directory of the dataset. - version (str): Version string. (default: ``"cv-corpus-4-2019-12-10"``) For the other allowed values, Please checkout https://commonvoice.mozilla.org/en/datasets. - download (bool, optional): - Whether to download the dataset if it is not found at root path. (default: ``False``). + download (bool, optional): Deprecated. """ _ext_txt = ".txt" @@ -132,10 +104,30 @@ class COMMONVOICE(Dataset): def __init__(self, root: Union[str, Path], tsv: str = TSV, - url: str = URL, + url: Optional[str] = None, folder_in_archive: str = FOLDER_IN_ARCHIVE, version: str = VERSION, - download: bool = False) -> None: + language: str = LANGUAGE, + download: Optional[bool] = False) -> None: + + if download is True: + raise RuntimeError( + "The dataset is no longer publicly accessible. You need to " + "download the archives externally and place them in the root " + "directory." + ) + elif download is False: + warnings.warn( + "The use of the download flag is deprecated, since the dataset " + "is no longer directly accessible.", RuntimeWarning + ) + + if url is not None: + warnings.warn( + "The use of the url flag is deprecated, since the dataset " + "is no longer publicly accessible. To specify the language of the dataset, " + "please use the language parameter instead.", RuntimeWarning + ) languages = { "tatar": "tt", @@ -180,12 +172,22 @@ def __init__(self, "romansh sursilvan": "rm-sursilv" } - if url in languages: + if language in languages: ext_archive = ".tar.gz" - language = languages[url] - - base_url = "https://voice-prod-bundler-ee1969a6ce8178826482b88e843c335139bd3fb4.s3.amazonaws.com" - url = os.path.join(base_url, version, language + ext_archive) + language = languages[language] + url = os.path.join(version, language + ext_archive) + else: + raise ValueError( + 'Allowed language values are "tatar", "english", "german",' + '"french", "welsh", "breton", "chuvash", "turkish", "kyrgyz",' + '"irish", "kabyle", "catalan", "taiwanese", "slovenian",' + '"italian", "dutch", "hakha chin", "esperanto", "estonian",' + '"persian", "portuguese", "basque", "spanish", "chinese",' + '"mongolian", "sakha", "dhivehi", "kinyarwanda", "swedish",' + '"russian", "indonesian", "arabic", "tamil", "interlingua",' + '"latvian", "japanese", "votic", "abkhaz", "cantonese" and' + '"romansh sursilvan".' + ) # Get string representation of 'root' in case Path object is passed root = os.fspath(root) @@ -198,12 +200,23 @@ def __init__(self, self._path = os.path.join(root, folder_in_archive) - if download: - if not os.path.isdir(self._path): - if not os.path.isfile(archive): - checksum = _CHECKSUMS.get(url, None) - download_url(url, root, hash_value=checksum) + if not os.path.isdir(self._path): + if os.path.isfile(archive): + checksum = _CHECKSUMS.get(url, None) + if checksum: + filepath = os.path.basename(url) + with open(filepath, "rb") as file_obj: + if not validate_file(file_obj, checksum, "sha256"): + raise RuntimeError( + f"The hash of {filepath} does not match. Delete the file manually and retry." + ) extract_archive(archive) + else: + raise RuntimeError( + "The dataset is no longer publicly accessible. You need to " + "download the archives externally and place them in the root " + "directory." + ) self._tsv = os.path.join(root, folder_in_archive, tsv) diff --git a/torchaudio/datasets/librispeech.py b/torchaudio/datasets/librispeech.py index 24da90aa66..c13fb312b8 100644 --- a/torchaudio/datasets/librispeech.py +++ b/torchaudio/datasets/librispeech.py @@ -1,5 +1,6 @@ import os -from typing import Tuple +from typing import Tuple, Union +from pathlib import Path import torchaudio from torch import Tensor @@ -70,7 +71,7 @@ class LIBRISPEECH(Dataset): """Create a Dataset for LibriSpeech. Args: - root (str): Path to the directory where the dataset is found or downloaded. + root (str or Path): Path to the directory where the dataset is found or downloaded. url (str, optional): The URL to download the dataset from, or the type of the dataset to dowload. Allowed type values are ``"dev-clean"``, ``"dev-other"``, ``"test-clean"``, @@ -86,7 +87,7 @@ class LIBRISPEECH(Dataset): _ext_audio = ".flac" def __init__(self, - root: str, + root: Union[str, Path], url: str = URL, folder_in_archive: str = FOLDER_IN_ARCHIVE, download: bool = False) -> None: @@ -106,6 +107,9 @@ def __init__(self, url = os.path.join(base_url, url + ext_archive) + # Get string representation of 'root' in case Path object is passed + root = os.fspath(root) + basename = os.path.basename(url) archive = os.path.join(root, basename) diff --git a/torchaudio/datasets/libritts.py b/torchaudio/datasets/libritts.py index 5d4e94cca5..8ed57d9b52 100644 --- a/torchaudio/datasets/libritts.py +++ b/torchaudio/datasets/libritts.py @@ -1,5 +1,6 @@ import os -from typing import Tuple +from typing import Tuple, Union +from pathlib import Path import torchaudio from torch import Tensor @@ -68,7 +69,7 @@ class LIBRITTS(Dataset): """Create a Dataset for LibriTTS. Args: - root (str): Path to the directory where the dataset is found or downloaded. + root (str or Path): Path to the directory where the dataset is found or downloaded. url (str, optional): The URL to download the dataset from, or the type of the dataset to dowload. Allowed type values are ``"dev-clean"``, ``"dev-other"``, ``"test-clean"``, @@ -86,7 +87,7 @@ class LIBRITTS(Dataset): def __init__( self, - root: str, + root: Union[str, Path], url: str = URL, folder_in_archive: str = FOLDER_IN_ARCHIVE, download: bool = False, @@ -107,6 +108,9 @@ def __init__( url = os.path.join(base_url, url + ext_archive) + # Get string representation of 'root' in case Path object is passed + root = os.fspath(root) + basename = os.path.basename(url) archive = os.path.join(root, basename) diff --git a/torchaudio/datasets/speechcommands.py b/torchaudio/datasets/speechcommands.py index 2bcd2d199f..7d774da943 100644 --- a/torchaudio/datasets/speechcommands.py +++ b/torchaudio/datasets/speechcommands.py @@ -1,5 +1,6 @@ import os -from typing import Tuple, Optional +from typing import Tuple, Optional, Union +from pathlib import Path import torchaudio from torch.utils.data import Dataset @@ -48,7 +49,7 @@ class SPEECHCOMMANDS(Dataset): """Create a Dataset for Speech Commands. Args: - root (str): Path to the directory where the dataset is found or downloaded. + root (str or Path): Path to the directory where the dataset is found or downloaded. url (str, optional): The URL to download the dataset from, or the type of the dataset to dowload. Allowed type values are ``"speech_commands_v0.01"`` and ``"speech_commands_v0.02"`` @@ -64,7 +65,7 @@ class SPEECHCOMMANDS(Dataset): """ def __init__(self, - root: str, + root: Union[str, Path], url: str = URL, folder_in_archive: str = FOLDER_IN_ARCHIVE, download: bool = False, @@ -85,6 +86,9 @@ def __init__(self, url = os.path.join(base_url, url + ext_archive) + # Get string representation of 'root' in case Path object is passed + root = os.fspath(root) + basename = os.path.basename(url) archive = os.path.join(root, basename) diff --git a/torchaudio/datasets/tedlium.py b/torchaudio/datasets/tedlium.py index 7ac347cd3c..e8d1d1cefc 100644 --- a/torchaudio/datasets/tedlium.py +++ b/torchaudio/datasets/tedlium.py @@ -1,5 +1,6 @@ import os -from typing import Tuple +from typing import Tuple, Union +from pathlib import Path import torchaudio from torch import Tensor @@ -46,7 +47,7 @@ class TEDLIUM(Dataset): Create a Dataset for Tedlium. It supports releases 1,2 and 3. Args: - root (str): Path to the directory where the dataset is found or downloaded. + root (str or Path): Path to the directory where the dataset is found or downloaded. release (str, optional): Release version. Allowed values are ``"release1"``, ``"release2"`` or ``"release3"``. (default: ``"release1"``). @@ -56,7 +57,12 @@ class TEDLIUM(Dataset): Whether to download the dataset if it is not found at root path. (default: ``False``). """ def __init__( - self, root: str, release: str = "release1", subset: str = None, download: bool = False, audio_ext=".sph" + self, + root: Union[str, Path], + release: str = "release1", + subset: str = None, + download: bool = False, + audio_ext=".sph" ) -> None: self._ext_audio = audio_ext if release in _RELEASE_CONFIGS.keys(): @@ -78,6 +84,9 @@ def __init__( ) ) + # Get string representation of 'root' in case Path object is passed + root = os.fspath(root) + basename = os.path.basename(url) archive = os.path.join(root, basename) diff --git a/torchaudio/functional/filtering.py b/torchaudio/functional/filtering.py index aa9f95f2e0..55cf05a51f 100644 --- a/torchaudio/functional/filtering.py +++ b/torchaudio/functional/filtering.py @@ -1006,7 +1006,8 @@ def phaser( References: http://sox.sourceforge.net/sox.html - Scott Lehman, Effects Explained, http://harmony-central.com/Effects/effects-explained.html + Scott Lehman, Effects Explained, + https://web.archive.org/web/20051125072557/http://www.harmony-central.com/Effects/effects-explained.html """ actual_shape = waveform.shape device, dtype = waveform.device, waveform.dtype diff --git a/torchaudio/functional/functional.py b/torchaudio/functional/functional.py index b967904f2a..20b71e4e33 100644 --- a/torchaudio/functional/functional.py +++ b/torchaudio/functional/functional.py @@ -102,16 +102,14 @@ def griffinlim( r"""Compute waveform from a linear scale magnitude spectrogram using the Griffin-Lim transformation. Implementation ported from `librosa`. - .. [1] McFee, Brian, Colin Raffel, Dawen Liang, Daniel PW Ellis, Matt McVicar, Eric Battenberg, and Oriol Nieto. + * [1] McFee, Brian, Colin Raffel, Dawen Liang, Daniel PW Ellis, Matt McVicar, Eric Battenberg, and Oriol Nieto. "librosa: Audio and music signal analysis in python." In Proceedings of the 14th python in science conference, pp. 18-25. 2015. - - .. [2] Perraudin, N., Balazs, P., & Sรธndergaard, P. L. + * [2] Perraudin, N., Balazs, P., & Sรธndergaard, P. L. "A fast Griffin-Lim algorithm," IEEE Workshop on Applications of Signal Processing to Audio and Acoustics (pp. 1-4), Oct. 2013. - - .. [3] D. W. Griffin and J. S. Lim, + * [3] D. W. Griffin and J. S. Lim, "Signal estimation from modified short-time Fourier transform," IEEE Trans. ASSP, vol.32, no.2, pp.236โ€“243, Apr. 1984. @@ -139,6 +137,12 @@ def griffinlim( assert momentum < 1, 'momentum={} > 1 can be unstable'.format(momentum) assert momentum >= 0, 'momentum={} < 0'.format(momentum) + if normalized: + warnings.warn( + "The argument normalized is not used in Griffin-Lim, " + "and will be removed in v0.9.0 release. To suppress this warning, " + "please use `normalized=False`.") + # pack batch shape = specgram.size() specgram = specgram.reshape([-1] + list(shape[-2:])) @@ -205,7 +209,7 @@ def amplitude_to_DB( This output depends on the maximum value in the input tensor, and so may return different values for an audio clip split into snippets vs. a - a full clip. + full clip. Args: x (Tensor): Input tensor before being converted to decibel scale diff --git a/torchaudio/sox_effects/sox_effects.py b/torchaudio/sox_effects/sox_effects.py index 8b50d19aa7..857df5d899 100644 --- a/torchaudio/sox_effects/sox_effects.py +++ b/torchaudio/sox_effects/sox_effects.py @@ -169,7 +169,8 @@ def apply_effects_file( rate and leave samples untouched. Args: - path (str): Path to the audio file. + path (str or pathlib.Path): Path to the audio file. This function also handles ``pathlib.Path`` objects, but is + annotated as ``str`` for TorchScript compiler compatibility. effects (List[List[str]]): List of effects. normalize (bool): When ``True``, this function always return ``float32``, and sample values are @@ -223,10 +224,9 @@ def apply_effects_file( ... super().__init__() ... self.flist = flist ... self.sample_rate = sample_rate - ... self.rng = None ... ... def __getitem__(self, index): - ... speed = self.rng.uniform(0.5, 2.0) + ... speed = 0.5 + 1.5 * torch.rand() ... effects = [ ... ['gain', '-n', '-10'], # apply 10 db attenuation ... ['remix', '-'], # merge all the channels @@ -247,5 +247,7 @@ def apply_effects_file( >>> for batch in loader: >>> pass """ + # Get string representation of 'path' in case Path object is passed + path = str(path) signal = torch.ops.torchaudio.sox_effects_apply_effects_file(path, effects, normalize, channels_first) return signal.get_tensor(), signal.get_sample_rate() diff --git a/torchaudio/utils/sox_utils.py b/torchaudio/utils/sox_utils.py index 59090e4b88..3f9ad0b5ec 100644 --- a/torchaudio/utils/sox_utils.py +++ b/torchaudio/utils/sox_utils.py @@ -26,10 +26,11 @@ def set_verbosity(verbosity: int): Args: verbosity (int): Set verbosity level of libsox. - 1: failure messages - 2: warnings - 3: details of processing - 4-6: increasing levels of debug messages + + * ``1`` failure messages + * ``2`` warnings + * ``3`` details of processing + * ``4``-``6`` increasing levels of debug messages See Also: http://sox.sourceforge.net/sox.html From 5f7a11cc588e5bd8196683df826dab5e29261572 Mon Sep 17 00:00:00 2001 From: Moto Hira Date: Tue, 22 Dec 2020 09:19:16 -0800 Subject: [PATCH 24/73] Import torchaudio #1105 37692d8 Summary: Import torchaudio up to #1105 37692d8 Reviewed By: datumbox Differential Revision: D25671497 fbshipit-source-id: 5af11c801321f2bb964245ac6ed74979310f4b5f --- .circleci/build_docs/commit_docs.sh | 10 +- .circleci/config.yml | 15 +- .circleci/config.yml.in | 15 +- test/torchaudio_unittest/README.md | 18 +- .../batch_consistency_test.py | 25 +- .../common_utils/sox_utils.py | 4 +- .../datasets/commonvoice_test.py | 21 +- .../datasets/utils_test.py | 6 +- .../soundfile_backend/load_test.py | 38 ++- .../sox_io_backend/load_test.py | 28 ++- third_party/CMakeLists.txt | 1 + third_party/patch/libsox.patch | 24 ++ torchaudio/datasets/cmuarctic.py | 4 +- torchaudio/datasets/commonvoice.py | 220 ++++-------------- torchaudio/datasets/librispeech.py | 6 +- torchaudio/datasets/libritts.py | 6 +- torchaudio/datasets/ljspeech.py | 4 +- torchaudio/datasets/speechcommands.py | 5 +- torchaudio/datasets/utils.py | 46 +--- torchaudio/datasets/vctk.py | 5 +- torchaudio/datasets/yesno.py | 6 +- torchaudio/functional/functional.py | 32 ++- torchaudio/sox_effects/sox_effects.py | 2 +- 23 files changed, 220 insertions(+), 321 deletions(-) create mode 100644 third_party/patch/libsox.patch diff --git a/.circleci/build_docs/commit_docs.sh b/.circleci/build_docs/commit_docs.sh index 9e9548936a..7d18214eef 100755 --- a/.circleci/build_docs/commit_docs.sh +++ b/.circleci/build_docs/commit_docs.sh @@ -5,7 +5,7 @@ set -ex if [ "$2" == "" ]; then echo call as "$0" "" "" - echo where src is the built documentation and + echo where src is the root of the built documentation git checkout and echo branch should be "master" or "1.7" or so exit 1 fi @@ -15,14 +15,15 @@ target=$2 echo "committing docs from ${src} to ${target}" +pushd "${src}" git checkout gh-pages mkdir -p ./"${target}" rm -rf ./"${target}"/* -cp -r "${src}/build/html/"* ./"$target" +cp -r "${src}/docs/build/html/"* ./"$target" if [ "${target}" == "master" ]; then mkdir -p ./_static rm -rf ./_static/* - cp -r "${src}/build/html/_static/"* ./_static + cp -r "${src}/docs/build/html/_static/"* ./_static git add --all ./_static || true fi git add --all ./"${target}" || true @@ -30,4 +31,5 @@ git config user.email "soumith+bot@pytorch.org" git config user.name "pytorchbot" # If there aren't changes, don't make a commit; push is no-op git commit -m "auto-generating sphinx docs" || true -git push -u origin gh-pages +git remote add https https://github.com/pytorch/audio.git +git push -u https gh-pages diff --git a/.circleci/config.yml b/.circleci/config.yml index f0ee6764b1..ee442189e4 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -283,7 +283,7 @@ jobs: command: | set -x source /usr/local/etc/profile.d/conda.sh && conda activate python${PYTHON_VERSION} - conda install -v -y -c pytorch-${UPLOAD_CHANNEL} pytorch + conda install -v -y -c pytorch-${UPLOAD_CHANNEL} pytorch cpuonly conda install -v -y -c file://$HOME/workspace/conda-bld torchaudio - run: name: smoke test @@ -325,7 +325,7 @@ jobs: conda env remove -n python${PYTHON_VERSION} || true conda create -yn python${PYTHON_VERSION} python=${PYTHON_VERSION} conda activate python${PYTHON_VERSION} - conda install -v -y -c pytorch-${UPLOAD_CHANNEL} pytorch + conda install -v -y -c pytorch-${UPLOAD_CHANNEL} pytorch cpuonly conda install -v -y $(ls ~/workspace/torchaudio*.tar.bz2) - run: name: smoke test @@ -662,7 +662,6 @@ jobs: steps: - attach_workspace: at: ~/workspace - - designate_upload_channel - checkout - run: name: Install pytorch-audio @@ -671,7 +670,7 @@ jobs: name: Build docs command: .circleci/build_docs/build_docs.sh - persist_to_workspace: - root: docs + root: ./ paths: - "*" @@ -683,7 +682,6 @@ jobs: steps: - attach_workspace: at: ~/workspace - - designate_upload_channel - run: name: Generate netrc command: | @@ -694,16 +692,15 @@ jobs: login pytorchbot password ${GITHUB_PYTORCHBOT_TOKEN} DONE - - checkout - run: name: Upload docs command: | + # Don't use "checkout" step since it uses ssh, which cannot git push + # https://circleci.com/docs/2.0/configuration-reference/#checkout set -ex - echo $PWD - ls ~/workspace tag=${CIRCLE_TAG:1:5} target=${tag:-master} - .circleci/build_docs/commit_docs.sh ~/workspace $target + ~/workspace/.circleci/build_docs/commit_docs.sh ~/workspace $target workflows: build: diff --git a/.circleci/config.yml.in b/.circleci/config.yml.in index bdbc3c774d..5c9c4d7693 100644 --- a/.circleci/config.yml.in +++ b/.circleci/config.yml.in @@ -283,7 +283,7 @@ jobs: command: | set -x source /usr/local/etc/profile.d/conda.sh && conda activate python${PYTHON_VERSION} - conda install -v -y -c pytorch-${UPLOAD_CHANNEL} pytorch + conda install -v -y -c pytorch-${UPLOAD_CHANNEL} pytorch cpuonly conda install -v -y -c file://$HOME/workspace/conda-bld torchaudio - run: name: smoke test @@ -325,7 +325,7 @@ jobs: conda env remove -n python${PYTHON_VERSION} || true conda create -yn python${PYTHON_VERSION} python=${PYTHON_VERSION} conda activate python${PYTHON_VERSION} - conda install -v -y -c pytorch-${UPLOAD_CHANNEL} pytorch + conda install -v -y -c pytorch-${UPLOAD_CHANNEL} pytorch cpuonly conda install -v -y $(ls ~/workspace/torchaudio*.tar.bz2) - run: name: smoke test @@ -662,7 +662,6 @@ jobs: steps: - attach_workspace: at: ~/workspace - - designate_upload_channel - checkout - run: name: Install pytorch-audio @@ -671,7 +670,7 @@ jobs: name: Build docs command: .circleci/build_docs/build_docs.sh - persist_to_workspace: - root: docs + root: ./ paths: - "*" @@ -683,7 +682,6 @@ jobs: steps: - attach_workspace: at: ~/workspace - - designate_upload_channel - run: name: Generate netrc command: | @@ -694,16 +692,15 @@ jobs: login pytorchbot password ${GITHUB_PYTORCHBOT_TOKEN} DONE - - checkout - run: name: Upload docs command: | + # Don't use "checkout" step since it uses ssh, which cannot git push + # https://circleci.com/docs/2.0/configuration-reference/#checkout set -ex - echo $PWD - ls ~/workspace tag=${CIRCLE_TAG:1:5} target=${tag:-master} - .circleci/build_docs/commit_docs.sh ~/workspace $target + ~/workspace/.circleci/build_docs/commit_docs.sh ~/workspace $target workflows: build: diff --git a/test/torchaudio_unittest/README.md b/test/torchaudio_unittest/README.md index 306ca23098..119c644687 100644 --- a/test/torchaudio_unittest/README.md +++ b/test/torchaudio_unittest/README.md @@ -10,9 +10,9 @@ pytest test --collect-only # Run all the test suites pytest test # Run tests on sox_effects module -pytest test/sox_effect +pytest test/torchaudio_unittest/sox_effect # use -k to apply filter -pytest test/sox_io_backend -k load # only runs tests where their names contain load +pytest test/torchaudio_unittest/sox_io_backend -k load # only runs tests where their names contain load # Some other useful options; # Stop on the first failure -x # Run failure fast --ff @@ -51,7 +51,7 @@ The following test modules are defined for corresponding `torchaudio` module/fun - [`torchaudio.transforms`](./transforms_test.py) - [`torchaudio.compliance.kaldi`](./compliance_kaldi_test.py) - [`torchaudio.kaldi_io`](./kaldi_io_test.py) -- [`torchaudio.sox_effects`](test/sox_effects) +- [`torchaudio.sox_effects`](./sox_effect) - [`torchaudio.save`, `torchaudio.load`, `torchaudio.info`](./io_test.py) ### Test modules that do not fall into the above categories @@ -82,12 +82,12 @@ Code: ```python waveform = common_utils.get_sinusoid( - frequency=300, - sample_rate=16000, - duration=1, # seconds - n_channels=1, - dtype="float32", - device="cpu", + frequency=300, + sample_rate=16000, + duration=1, # seconds + n_channels=1, + dtype="float32", + device="cpu", ) ``` diff --git a/test/torchaudio_unittest/batch_consistency_test.py b/test/torchaudio_unittest/batch_consistency_test.py index 696b714df1..d4edf65e98 100644 --- a/test/torchaudio_unittest/batch_consistency_test.py +++ b/test/torchaudio_unittest/batch_consistency_test.py @@ -227,19 +227,22 @@ def test_batch_TimeStretch(self): test_filepath = common_utils.get_asset_path('steam-train-whistle-daniel_simon.wav') waveform, _ = torchaudio.load(test_filepath) # (2, 278756), 44100 - kwargs = { - 'n_fft': 2048, - 'hop_length': 512, - 'win_length': 2048, - 'window': torch.hann_window(2048), - 'center': True, - 'pad_mode': 'reflect', - 'normalized': True, - 'onesided': True, - } rate = 2 - complex_specgrams = torch.stft(waveform, **kwargs) + complex_specgrams = torch.view_as_real( + torch.stft( + input=waveform, + n_fft=2048, + hop_length=512, + win_length=2048, + window=torch.hann_window(2048), + center=True, + pad_mode='reflect', + normalized=True, + onesided=True, + return_complex=True, + ) + ) # Single then transform then batch expected = torchaudio.transforms.TimeStretch( diff --git a/test/torchaudio_unittest/common_utils/sox_utils.py b/test/torchaudio_unittest/common_utils/sox_utils.py index db131cdec5..0267017393 100644 --- a/test/torchaudio_unittest/common_utils/sox_utils.py +++ b/test/torchaudio_unittest/common_utils/sox_utils.py @@ -1,4 +1,5 @@ import subprocess +import warnings def get_encoding(dtype): @@ -27,8 +28,7 @@ def gen_audio_file( ): """Generate synthetic audio file with `sox` command.""" if path.endswith('.wav'): - raise RuntimeError( - 'Use get_wav_data and save_wav to generate wav file for accurate result.') + warnings.warn('Use get_wav_data and save_wav to generate wav file for accurate result.') command = [ 'sox', '-V3', # verbose diff --git a/test/torchaudio_unittest/datasets/commonvoice_test.py b/test/torchaudio_unittest/datasets/commonvoice_test.py index 731c4e07cc..22c811a67b 100644 --- a/test/torchaudio_unittest/datasets/commonvoice_test.py +++ b/test/torchaudio_unittest/datasets/commonvoice_test.py @@ -1,9 +1,8 @@ import os import csv -import random from pathlib import Path -from torchaudio.datasets import commonvoice +from torchaudio.datasets import COMMONVOICE from torchaudio_unittest.common_utils import ( TempDirMixin, TorchaudioTestCase, @@ -31,29 +30,23 @@ class TestCommonVoice(TempDirMixin, TorchaudioTestCase): "common_voice_en_18607573.wav", "Caddy, show Miss Clare and Miss Summerson their rooms.", "2", "0", "twenties", "male", "canada"], ] - _folder_audio = "clips" sample_rate = 48000 @classmethod def setUpClass(cls): cls.root_dir = cls.get_base_temp_dir() - # The path convention commonvoice uses - base_dir = os.path.join(cls.root_dir, commonvoice.FOLDER_IN_ARCHIVE, commonvoice.VERSION, "en") - os.makedirs(base_dir, exist_ok=True) - # Tsv file name difference does not mean different subset, testing as a whole dataset here - tsv_filename = os.path.join(base_dir, commonvoice.TSV) + tsv_filename = os.path.join(cls.root_dir, "train.tsv") + audio_base_path = os.path.join(cls.root_dir, "clips") + os.makedirs(audio_base_path, exist_ok=True) with open(tsv_filename, "w", newline='') as tsv: writer = csv.writer(tsv, delimiter='\t') writer.writerow(cls._headers) for i, content in enumerate(cls._train_csv_contents): - audio_filename = audio_filename = content[1] writer.writerow(content) # Generate and store audio - audio_base_path = os.path.join(base_dir, cls._folder_audio) - os.makedirs(audio_base_path, exist_ok=True) - audio_path = os.path.join(audio_base_path, audio_filename) + audio_path = os.path.join(audio_base_path, content[1]) data = get_whitenoise(sample_rate=cls.sample_rate, duration=1, n_channels=1, seed=i, dtype='float32') save_wav(audio_path, data, cls.sample_rate) @@ -72,9 +65,9 @@ def _test_commonvoice(self, dataset): assert n_ite == len(self.data) def test_commonvoice_str(self): - dataset = commonvoice.COMMONVOICE(self.root_dir) + dataset = COMMONVOICE(self.root_dir) self._test_commonvoice(dataset) def test_commonvoice_path(self): - dataset = commonvoice.COMMONVOICE(Path(self.root_dir)) + dataset = COMMONVOICE(Path(self.root_dir)) self._test_commonvoice(dataset) diff --git a/test/torchaudio_unittest/datasets/utils_test.py b/test/torchaudio_unittest/datasets/utils_test.py index a9e13a1e38..5263319e51 100644 --- a/test/torchaudio_unittest/datasets/utils_test.py +++ b/test/torchaudio_unittest/datasets/utils_test.py @@ -51,10 +51,10 @@ def test_walk_files(self): class TestIterator(TorchaudioTestCase): backend = 'default' - path = get_asset_path() + path = get_asset_path('CommonVoice', 'cv-corpus-4-2019-12-10', 'tt') def test_disckcache_iterator(self): - data = COMMONVOICE(self.path, version="cv-corpus-4-2019-12-10", language="tatar") + data = COMMONVOICE(self.path, url="tatar") data = dataset_utils.diskcache_iterator(data) # Save data[0] @@ -62,7 +62,7 @@ def test_disckcache_iterator(self): data[0] def test_bg_iterator(self): - data = COMMONVOICE(self.path, version="cv-corpus-4-2019-12-10", language="tatar") + data = COMMONVOICE(self.path, url="tatar") data = dataset_utils.bg_iterator(data, 5) for _ in data: pass diff --git a/test/torchaudio_unittest/soundfile_backend/load_test.py b/test/torchaudio_unittest/soundfile_backend/load_test.py index 8860263eed..4277ac03e9 100644 --- a/test/torchaudio_unittest/soundfile_backend/load_test.py +++ b/test/torchaudio_unittest/soundfile_backend/load_test.py @@ -1,4 +1,4 @@ -import itertools +import os from unittest.mock import patch import torch @@ -263,3 +263,39 @@ def test_sphere(self, dtype, sample_rate, num_channels, channels_first): def test_flac(self, dtype, sample_rate, num_channels, channels_first): """`soundfile_backend.load` can load flac format correctly.""" self.assert_flac(dtype, sample_rate, num_channels, channels_first) + + +@skipIfNoModule("soundfile") +class TestLoadFormat(TempDirMixin, PytorchTestCase): + """Given `format` parameter, `so.load` can load files without extension""" + original = None + path = None + + def _make_file(self, format_): + sample_rate = 8000 + path_with_ext = self.get_temp_path(f'test.{format_}') + data = get_wav_data('float32', num_channels=2).numpy().T + soundfile.write(path_with_ext, data, sample_rate) + expected = soundfile.read(path_with_ext, dtype='float32')[0].T + path = os.path.splitext(path_with_ext)[0] + os.rename(path_with_ext, path) + return path, expected + + def _test_format(self, format_): + """Providing format allows to read file without extension""" + path, expected = self._make_file(format_) + found, _ = soundfile_backend.load(path) + self.assertEqual(found, expected) + + @parameterized.expand([ + ('WAV', ), ('wav', ), + ]) + def test_wav(self, format_): + self._test_format(format_) + + @parameterized.expand([ + ('FLAC', ), ('flac',), + ]) + @skipIfFormatNotSupported("FLAC") + def test_flac(self, format_): + self._test_format(format_) diff --git a/test/torchaudio_unittest/sox_io_backend/load_test.py b/test/torchaudio_unittest/sox_io_backend/load_test.py index 156ad9ad3e..2b4e916861 100644 --- a/test/torchaudio_unittest/sox_io_backend/load_test.py +++ b/test/torchaudio_unittest/sox_io_backend/load_test.py @@ -1,3 +1,4 @@ +import os import itertools from torchaudio.backend import sox_io_backend @@ -333,7 +334,7 @@ def setUp(self): super().setUp() sample_rate = 8000 self.original = get_wav_data('float32', num_channels=2) - self.path = self.get_temp_path('test.wave') + self.path = self.get_temp_path('test.wav') save_wav(self.path, self.original, sample_rate) @parameterized.expand(list(itertools.product( @@ -352,3 +353,28 @@ def test_channels_first(self, channels_first): found, _ = sox_io_backend.load(self.path, channels_first=channels_first) expected = self.original if channels_first else self.original.transpose(1, 0) self.assertEqual(found, expected) + + +@skipIfNoExec('sox') +@skipIfNoExtension +class TestLoadExtensionLess(TempDirMixin, PytorchTestCase): + """Given `format` parameter, `sox_io_backend.load` can load files without extension""" + original = None + path = None + + def _make_file(self, format_): + sample_rate = 8000 + path = self.get_temp_path(f'test.{format_}') + sox_utils.gen_audio_file(f'{path}', sample_rate, num_channels=2) + self.original = sox_io_backend.load(path)[0] + self.path = os.path.splitext(path)[0] + os.rename(path, self.path) + + @parameterized.expand([ + ('WAV', ), ('wav', ), ('MP3', ), ('mp3', ), ('FLAC', ), ('flac',), + ], name_func=name_func) + def test_format(self, format_): + """Providing format allows to read file without extension""" + self._make_file(format_) + found, _ = sox_io_backend.load(self.path) + self.assertEqual(found, self.original) diff --git a/third_party/CMakeLists.txt b/third_party/CMakeLists.txt index ad0eac582b..50c7696eb5 100644 --- a/third_party/CMakeLists.txt +++ b/third_party/CMakeLists.txt @@ -84,6 +84,7 @@ ExternalProject_Add(libsox 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 patch -p0 < ${CMAKE_CURRENT_SOURCE_DIR}/patch/libsox.patch # 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 CONFIGURE_COMMAND ${CMAKE_CURRENT_SOURCE_DIR}/build_codec_helper.sh ${CMAKE_CURRENT_SOURCE_DIR}/src/libsox/configure ${COMMON_ARGS} --with-lame --with-flac --with-mad --with-oggvorbis --without-alsa --without-coreaudio --without-png --without-oss --without-sndfile --with-opus --with-amrwb --with-amrnb --disable-openmp diff --git a/third_party/patch/libsox.patch b/third_party/patch/libsox.patch new file mode 100644 index 0000000000..996bafdd57 --- /dev/null +++ b/third_party/patch/libsox.patch @@ -0,0 +1,24 @@ +--- src/formats.c 2014-10-27 02:55:50.000000000 +0000 ++++ src/formats_new.c 2020-11-18 19:14:17.398689371 +0000 +@@ -91,6 +91,21 @@ + + if (ext && !strcasecmp(ext, "snd")) + CHECK(sndr , 7, 1, "" , 0, 2, "\0") ++ ++#if defined HAVE_MP3 && (defined STATIC_MP3 || !defined HAVE_LIBLTDL) ++ // http://www.mp3-tech.org/programmer/frame_header.html ++ // Check the first two bytes are ++ // expected 1111_1111 111X_X01X ++ // mask \xEEE6 (1111_1111 1110_0110) ++ // masked value \xEEE2 (1111_1111 1110_0010) ++ if (len >= 2 && !memcmp(data, "\xFF", 1)) { ++ unsigned char second_byte = data[1]; ++ unsigned char mask = 0xE6; ++ unsigned char expected = 0xE2; ++ if ((second_byte & mask) == expected) ++ return "mp3"; ++ } ++#endif + #undef CHECK + + #if HAVE_MAGIC diff --git a/torchaudio/datasets/cmuarctic.py b/torchaudio/datasets/cmuarctic.py index f8674127fd..9bc5577616 100644 --- a/torchaudio/datasets/cmuarctic.py +++ b/torchaudio/datasets/cmuarctic.py @@ -1,4 +1,5 @@ import os +import csv from pathlib import Path from typing import Tuple, Union @@ -8,7 +9,6 @@ from torchaudio.datasets.utils import ( download_url, extract_archive, - unicode_csv_reader, ) URL = "aew" @@ -154,7 +154,7 @@ def __init__(self, self._text = os.path.join(self._path, self._folder_text, self._file_text) with open(self._text, "r") as text: - walker = unicode_csv_reader(text, delimiter="\n") + walker = csv.reader(text, delimiter="\n") self._walker = list(walker) def __getitem__(self, n: int) -> Tuple[Tensor, int, str, str]: diff --git a/torchaudio/datasets/commonvoice.py b/torchaudio/datasets/commonvoice.py index 1a1f4273a4..d387a8ca2a 100644 --- a/torchaudio/datasets/commonvoice.py +++ b/torchaudio/datasets/commonvoice.py @@ -1,57 +1,13 @@ import os +import csv import warnings from pathlib import Path -from typing import List, Dict, Tuple, Optional, Union +from typing import List, Dict, Tuple, Union, Optional import torchaudio -from torchaudio.datasets.utils import extract_archive, unicode_csv_reader, validate_file from torch import Tensor from torch.utils.data import Dataset -# Default TSV should be one of -# dev.tsv -# invalidated.tsv -# other.tsv -# test.tsv -# train.tsv -# validated.tsv - -FOLDER_IN_ARCHIVE = "CommonVoice" -LANGUAGE = "english" -VERSION = "cv-corpus-5.1-2020-06-22" -TSV = "train.tsv" -_CHECKSUMS = { - "cv-corpus-5.1-2020-06-22/tt.tar.gz": None, - "cv-corpus-5.1-2020-06-22/en.tar.gz": None, - "cv-corpus-5.1-2020-06-22/de.tar.gz": None, - "cv-corpus-5.1-2020-06-22/fr.tar.gz": None, - "cv-corpus-5.1-2020-06-22/cy.tar.gz": None, - "cv-corpus-5.1-2020-06-22/br.tar.gz": None, - "cv-corpus-5.1-2020-06-22/cv.tar.gz": None, - "cv-corpus-5.1-2020-06-22/tr.tar.gz": None, - "cv-corpus-5.1-2020-06-22/ky.tar.gz": None, - "cv-corpus-5.1-2020-06-22/ga-IE.tar.gz": None, - "cv-corpus-5.1-2020-06-22/kab.tar.gz": None, - "cv-corpus-5.1-2020-06-22/ca.tar.gz": None, - "cv-corpus-5.1-2020-06-22/zh-TW.tar.gz": None, - "cv-corpus-5.1-2020-06-22/sl.tar.gz": None, - "cv-corpus-5.1-2020-06-22/it.tar.gz": None, - "cv-corpus-5.1-2020-06-22/nl.tar.gz": None, - "cv-corpus-5.1-2020-06-22/cnh.tar.gz": None, - "cv-corpus-5.1-2020-06-22/eo.tar.gz": None, - "cv-corpus-5.1-2020-06-22/et.tar.gz": None, - "cv-corpus-5.1-2020-06-22/fa.tar.gz": None, - "cv-corpus-5.1-2020-06-22/eu.tar.gz": None, - "cv-corpus-5.1-2020-06-22/es.tar.gz": None, - "cv-corpus-5.1-2020-06-22/zh-CN.tar.gz": None, - "cv-corpus-5.1-2020-06-22/mn.tar.gz": None, - "cv-corpus-5.1-2020-06-22/sah.tar.gz": None, - "cv-corpus-5.1-2020-06-22/dv.tar.gz": None, - "cv-corpus-5.1-2020-06-22/rw.tar.gz": None, - "cv-corpus-5.1-2020-06-22/sv-SE.tar.gz": None, - "cv-corpus-5.1-2020-06-22/ru.tar.gz": None, -} - def load_commonvoice_item(line: List[str], header: List[str], @@ -73,28 +29,19 @@ def load_commonvoice_item(line: List[str], class COMMONVOICE(Dataset): - """Create a Dataset for `CommonVoice `_. + """Create a Dataset for CommonVoice. Args: - root (str or Path): Path to the directory where the dataset is found or downloaded. - tsv (str, optional): The name of the tsv file used to construct the metadata. - (default: ``"train.tsv"``) - url (str, optional): Deprecated. - folder_in_archive (str, optional): The top-level directory of the dataset. - version (str): Version string. (default: ``"cv-corpus-5.1-2020-06-22"``) - language (str, optional): Language of the dataset. (default: None) - The following values are mapped to their corresponding shortened version: - ``"tatar"``, ``"english"``, ``"german"``, - ``"french"``, ``"welsh"``, ``"breton"``, ``"chuvash"``, ``"turkish"``, ``"kyrgyz"``, - ``"irish"``, ``"kabyle"``, ``"catalan"``, ``"taiwanese"``, ``"slovenian"``, - ``"italian"``, ``"dutch"``, ``"hakha chin"``, ``"esperanto"``, ``"estonian"``, - ``"persian"``, ``"portuguese"``, ``"basque"``, ``"spanish"``, ``"chinese"``, - ``"mongolian"``, ``"sakha"``, ``"dhivehi"``, ``"kinyarwanda"``, ``"swedish"``, - ``"russian"``, ``"indonesian"``, ``"arabic"``, ``"tamil"``, ``"interlingua"``, - ``"latvian"``, ``"japanese"``, ``"votic"``, ``"abkhaz"``, ``"cantonese"`` and - ``"romansh sursilvan"``. - For the other allowed values, Please checkout https://commonvoice.mozilla.org/en/datasets. - download (bool, optional): Deprecated. + root (str or Path): Path to the directory where the dataset is located. + (Where the ``tsv`` file is present.) + tsv (str, optional): + The name of the tsv file used to construct the metadata, such as + ``"train.tsv"``, ``"test.tsv"``, ``"dev.tsv"``, ``"invalidated.tsv"``, + ``"validated.tsv"`` and ``"other.tsv"``. (default: ``"train.tsv"``) + url (str, optional): Deprecated, not used. + folder_in_archive (str, optional): Deprecated, not used. + version (str): Deprecated, not used. + download (bool, optional): Deprecated, not used. """ _ext_txt = ".txt" @@ -103,125 +50,36 @@ class COMMONVOICE(Dataset): def __init__(self, root: Union[str, Path], - tsv: str = TSV, + tsv: str = "train.tsv", url: Optional[str] = None, - folder_in_archive: str = FOLDER_IN_ARCHIVE, - version: str = VERSION, - language: str = LANGUAGE, - download: Optional[bool] = False) -> None: - - if download is True: + folder_in_archive: Optional[str] = None, + version: Optional[str] = None, + download: Optional[bool] = None) -> None: + if download: raise RuntimeError( - "The dataset is no longer publicly accessible. You need to " - "download the archives externally and place them in the root " - "directory." - ) - elif download is False: - warnings.warn( - "The use of the download flag is deprecated, since the dataset " - "is no longer directly accessible.", RuntimeWarning - ) - - if url is not None: - warnings.warn( - "The use of the url flag is deprecated, since the dataset " - "is no longer publicly accessible. To specify the language of the dataset, " - "please use the language parameter instead.", RuntimeWarning - ) - - languages = { - "tatar": "tt", - "english": "en", - "german": "de", - "french": "fr", - "welsh": "cy", - "breton": "br", - "chuvash": "cv", - "turkish": "tr", - "kyrgyz": "ky", - "irish": "ga-IE", - "kabyle": "kab", - "catalan": "ca", - "taiwanese": "zh-TW", - "slovenian": "sl", - "italian": "it", - "dutch": "nl", - "hakha chin": "cnh", - "esperanto": "eo", - "estonian": "et", - "persian": "fa", - "portuguese": "pt", - "basque": "eu", - "spanish": "es", - "chinese": "zh-CN", - "mongolian": "mn", - "sakha": "sah", - "dhivehi": "dv", - "kinyarwanda": "rw", - "swedish": "sv-SE", - "russian": "ru", - "indonesian": "id", - "arabic": "ar", - "tamil": "ta", - "interlingua": "ia", - "latvian": "lv", - "japanese": "ja", - "votic": "vot", - "abkhaz": "ab", - "cantonese": "zh-HK", - "romansh sursilvan": "rm-sursilv" - } - - if language in languages: - ext_archive = ".tar.gz" - language = languages[language] - url = os.path.join(version, language + ext_archive) - else: - raise ValueError( - 'Allowed language values are "tatar", "english", "german",' - '"french", "welsh", "breton", "chuvash", "turkish", "kyrgyz",' - '"irish", "kabyle", "catalan", "taiwanese", "slovenian",' - '"italian", "dutch", "hakha chin", "esperanto", "estonian",' - '"persian", "portuguese", "basque", "spanish", "chinese",' - '"mongolian", "sakha", "dhivehi", "kinyarwanda", "swedish",' - '"russian", "indonesian", "arabic", "tamil", "interlingua",' - '"latvian", "japanese", "votic", "abkhaz", "cantonese" and' - '"romansh sursilvan".' - ) + "Common Voice dataset requires user agreement on the usage term, " + "and torchaudio no longer provides the download feature. " + "Please download the dataset and extract it manually.") + + deprecated = [ + ('url', url), + ('folder_in_archive', folder_in_archive), + ('version', version), + ('download', download) + ] + for name, val in deprecated: + if val is not None: + warnings.warn( + f"`{name}` argument is no longer used and deprecated. " + "It will be removed in 0.9.0 releaase. " + "Please remove it from the function call") # Get string representation of 'root' in case Path object is passed - root = os.fspath(root) - - basename = os.path.basename(url) - archive = os.path.join(root, basename) - - basename = basename.rsplit(".", 2)[0] - folder_in_archive = os.path.join(folder_in_archive, version, basename) - - self._path = os.path.join(root, folder_in_archive) - - if not os.path.isdir(self._path): - if os.path.isfile(archive): - checksum = _CHECKSUMS.get(url, None) - if checksum: - filepath = os.path.basename(url) - with open(filepath, "rb") as file_obj: - if not validate_file(file_obj, checksum, "sha256"): - raise RuntimeError( - f"The hash of {filepath} does not match. Delete the file manually and retry." - ) - extract_archive(archive) - else: - raise RuntimeError( - "The dataset is no longer publicly accessible. You need to " - "download the archives externally and place them in the root " - "directory." - ) - - self._tsv = os.path.join(root, folder_in_archive, tsv) - - with open(self._tsv, "r") as tsv: - walker = unicode_csv_reader(tsv, delimiter="\t") + self._path = os.fspath(root) + self._tsv = os.path.join(self._path, tsv) + + with open(self._tsv, "r") as tsv_: + walker = csv.reader(tsv_, delimiter="\t") self._header = next(walker) self._walker = list(walker) diff --git a/torchaudio/datasets/librispeech.py b/torchaudio/datasets/librispeech.py index c13fb312b8..8447c4c8a2 100644 --- a/torchaudio/datasets/librispeech.py +++ b/torchaudio/datasets/librispeech.py @@ -8,7 +8,6 @@ from torchaudio.datasets.utils import ( download_url, extract_archive, - walk_files, ) URL = "train-clean-100" @@ -125,10 +124,7 @@ def __init__(self, download_url(url, root, hash_value=checksum) extract_archive(archive) - walker = walk_files( - self._path, suffix=self._ext_audio, prefix=False, remove_suffix=True - ) - self._walker = list(walker) + self._walker = sorted(str(p.stem) for p in Path(self._path).glob('*/*/*' + self._ext_audio)) def __getitem__(self, n: int) -> Tuple[Tensor, int, str, int, int, int]: """Load the n-th sample from the dataset. diff --git a/torchaudio/datasets/libritts.py b/torchaudio/datasets/libritts.py index 8ed57d9b52..9f0c38a751 100644 --- a/torchaudio/datasets/libritts.py +++ b/torchaudio/datasets/libritts.py @@ -8,7 +8,6 @@ from torchaudio.datasets.utils import ( download_url, extract_archive, - walk_files, ) URL = "train-clean-100" @@ -126,10 +125,7 @@ def __init__( download_url(url, root, hash_value=checksum) extract_archive(archive) - walker = walk_files( - self._path, suffix=self._ext_audio, prefix=False, remove_suffix=True - ) - self._walker = list(walker) + self._walker = sorted(str(p.stem) for p in Path(self._path).glob('*/*/*' + self._ext_audio)) def __getitem__(self, n: int) -> Tuple[Tensor, int, str, str, int, int, str]: """Load the n-th sample from the dataset. diff --git a/torchaudio/datasets/ljspeech.py b/torchaudio/datasets/ljspeech.py index 2d653fbf46..01d3fe7d95 100644 --- a/torchaudio/datasets/ljspeech.py +++ b/torchaudio/datasets/ljspeech.py @@ -4,7 +4,7 @@ from pathlib import Path import torchaudio -from torchaudio.datasets.utils import download_url, extract_archive, unicode_csv_reader +from torchaudio.datasets.utils import download_url, extract_archive from torch import Tensor from torch.utils.data import Dataset @@ -75,7 +75,7 @@ def __init__(self, extract_archive(archive) with open(self._metadata_path, "r", newline='') as metadata: - walker = unicode_csv_reader(metadata, delimiter="|", quoting=csv.QUOTE_NONE) + walker = csv.reader(metadata, delimiter="|", quoting=csv.QUOTE_NONE) self._walker = list(walker) def __getitem__(self, n: int) -> Tuple[Tensor, int, str, str]: diff --git a/torchaudio/datasets/speechcommands.py b/torchaudio/datasets/speechcommands.py index 7d774da943..5264ea24de 100644 --- a/torchaudio/datasets/speechcommands.py +++ b/torchaudio/datasets/speechcommands.py @@ -8,7 +8,6 @@ from torchaudio.datasets.utils import ( download_url, extract_archive, - walk_files ) FOLDER_IN_ARCHIVE = "SpeechCommands" @@ -110,7 +109,7 @@ def __init__(self, self._walker = _load_list(self._path, "testing_list.txt") elif subset == "training": excludes = set(_load_list(self._path, "validation_list.txt", "testing_list.txt")) - walker = walk_files(self._path, suffix=".wav", prefix=True) + walker = sorted(str(p) for p in Path(self._path).glob('*/*.wav')) self._walker = [ w for w in walker if HASH_DIVIDER in w @@ -118,7 +117,7 @@ def __init__(self, and os.path.normpath(w) not in excludes ] else: - walker = walk_files(self._path, suffix=".wav", prefix=True) + walker = sorted(str(p) for p in Path(self._path).glob('*/*.wav')) self._walker = [w for w in walker if HASH_DIVIDER in w and EXCEPT_FOLDER not in w] def __getitem__(self, n: int) -> Tuple[Tensor, int, str, str, int]: diff --git a/torchaudio/datasets/utils.py b/torchaudio/datasets/utils.py index d00ffc143b..c187d0d814 100644 --- a/torchaudio/datasets/utils.py +++ b/torchaudio/datasets/utils.py @@ -1,4 +1,3 @@ -import csv import errno import hashlib import logging @@ -18,49 +17,6 @@ from torch.utils.model_zoo import tqdm -def unicode_csv_reader(unicode_csv_data: TextIOWrapper, **kwargs: Any) -> Any: - r"""Since the standard csv library does not handle unicode in Python 2, we need a wrapper. - Borrowed and slightly modified from the Python docs: - https://docs.python.org/2/library/csv.html#csv-examples - Args: - unicode_csv_data (TextIOWrapper): unicode csv data (see example below) - - Examples: - >>> from torchaudio.datasets.utils import unicode_csv_reader - >>> import io - >>> with io.open(data_path, encoding="utf8") as f: - >>> reader = unicode_csv_reader(f) - """ - - # Fix field larger than field limit error - maxInt = sys.maxsize - while True: - # decrease the maxInt value by factor 10 - # as long as the OverflowError occurs. - try: - csv.field_size_limit(maxInt) - break - except OverflowError: - maxInt = int(maxInt / 10) - csv.field_size_limit(maxInt) - - for line in csv.reader(unicode_csv_data, **kwargs): - yield line - - -def makedir_exist_ok(dirpath: str) -> None: - """ - Python2 support for os.makedirs(.., exist_ok=True) - """ - try: - os.makedirs(dirpath) - except OSError as e: - if e.errno == errno.EEXIST: - pass - else: - raise - - def stream_url(url: str, start_byte: Optional[int] = None, block_size: int = 32 * 1024, @@ -305,7 +261,7 @@ def __getitem__(self, n: int) -> Any: item = self.dataset[n] self._cache[n] = f - makedir_exist_ok(self.location) + os.makedirs(self.location, exist_ok=True) torch.save(item, f) return item diff --git a/torchaudio/datasets/vctk.py b/torchaudio/datasets/vctk.py index 9bf843f685..c71962bad8 100644 --- a/torchaudio/datasets/vctk.py +++ b/torchaudio/datasets/vctk.py @@ -9,7 +9,6 @@ from torchaudio.datasets.utils import ( download_url, extract_archive, - walk_files ) URL = "https://datashare.is.ed.ac.uk/bitstream/handle/10283/3443/VCTK-Corpus-0.92.zip" @@ -123,9 +122,7 @@ def __init__(self, "with `download=True` to donwload the latest version." ) - walker = walk_files( - self._path, suffix=self._ext_audio, prefix=False, remove_suffix=True - ) + walker = sorted(str(p.stem) for p in Path(self._path).glob('**/*' + self._ext_audio)) walker = filter(lambda w: self._except_folder not in w, walker) self._walker = list(walker) diff --git a/torchaudio/datasets/yesno.py b/torchaudio/datasets/yesno.py index 182d224ba4..21d67f8ecc 100644 --- a/torchaudio/datasets/yesno.py +++ b/torchaudio/datasets/yesno.py @@ -9,7 +9,6 @@ from torchaudio.datasets.utils import ( download_url, extract_archive, - walk_files ) URL = "http://www.openslr.org/resources/1/waves_yesno.tar.gz" @@ -85,10 +84,7 @@ def __init__(self, "Dataset not found. Please use `download=True` to download it." ) - walker = walk_files( - self._path, suffix=self._ext_audio, prefix=False, remove_suffix=True - ) - self._walker = list(walker) + self._walker = sorted(str(p.stem) for p in Path(self._path).glob('*' + self._ext_audio)) def __getitem__(self, n: int) -> Tuple[Tensor, int, List[int]]: """Load the n-th sample from the dataset. diff --git a/torchaudio/functional/functional.py b/torchaudio/functional/functional.py index 20b71e4e33..3fedf93d09 100644 --- a/torchaudio/functional/functional.py +++ b/torchaudio/functional/functional.py @@ -24,7 +24,6 @@ "angle", "magphase", "phase_vocoder", - "detect_pitch_frequency", 'mask_along_axis', 'mask_along_axis_iid', 'sliding_window_cmn', @@ -71,8 +70,19 @@ def spectrogram( waveform = waveform.reshape(-1, shape[-1]) # default values are consistent with librosa.core.spectrum._spectrogram - spec_f = torch.stft( - waveform, n_fft, hop_length, win_length, window, True, "reflect", False, True + spec_f = torch.view_as_real( + torch.stft( + input=waveform, + n_fft=n_fft, + hop_length=hop_length, + win_length=win_length, + window=window, + center=True, + pad_mode="reflect", + normalized=False, + onesided=True, + return_complex=True, + ) ) # unpack batch @@ -175,8 +185,20 @@ def griffinlim( length=length).float() # Rebuild the spectrogram - rebuilt = torch.stft(inverse, n_fft, hop_length, win_length, window, - True, 'reflect', False, True) + rebuilt = torch.view_as_real( + torch.stft( + input=inverse, + n_fft=n_fft, + hop_length=hop_length, + win_length=win_length, + window=window, + center=True, + pad_mode='reflect', + normalized=False, + onesided=True, + return_complex=True, + ) + ) # Update our phase estimates angles = rebuilt diff --git a/torchaudio/sox_effects/sox_effects.py b/torchaudio/sox_effects/sox_effects.py index 857df5d899..82ee613ba0 100644 --- a/torchaudio/sox_effects/sox_effects.py +++ b/torchaudio/sox_effects/sox_effects.py @@ -226,7 +226,7 @@ def apply_effects_file( ... self.sample_rate = sample_rate ... ... def __getitem__(self, index): - ... speed = 0.5 + 1.5 * torch.rand() + ... speed = 0.5 + 1.5 * random.randn() ... effects = [ ... ['gain', '-n', '-10'], # apply 10 db attenuation ... ['remix', '-'], # merge all the channels From 17c0f55ea4459a8a3181b140b526771ebb2404b2 Mon Sep 17 00:00:00 2001 From: Moto Hira Date: Mon, 11 Jan 2021 13:01:15 -0800 Subject: [PATCH 25/73] Import torchaudio #1161 7a36c55 Summary: Import torchaudio #1161 7a36c55 Reviewed By: cpuhrsch Differential Revision: D25827050 fbshipit-source-id: 31e07ace85f7e1417884cd721bc80c5c6c33960f --- .circleci/config.yml | 14 +- .circleci/config.yml.in | 14 +- .circleci/torchscript_bc_test/common.sh | 3 +- .circleci/unittest/linux/scripts/install.sh | 6 +- .circleci/unittest/linux/scripts/run_test.sh | 2 +- .circleci/unittest/linux/scripts/setup_env.sh | 1 + .gitignore | 4 +- .gitmodules | 4 + build_tools/setup_helpers/extension.py | 48 ++- packaging/build_wheel.sh | 2 +- packaging/pkg_helpers.bash | 1 + packaging/torchaudio/build.sh | 2 +- setup.py | 4 +- test/torchaudio_unittest/README.md | 2 +- .../tt/clips/common_voice_tt_00000000.wav | Bin 80700 -> 0 bytes .../cv-corpus-4-2019-12-10/tt/train.tsv | 3 - .../assets/mp3_without_ext | Bin 0 -> 15453 bytes .../common_utils/__init__.py | 1 + .../common_utils/case_utils.py | 28 ++ .../datasets/cmuarctic_test.py | 75 ++--- .../datasets/commonvoice_test.py | 145 ++++++--- .../datasets/gtzan_test.py | 55 ++-- .../datasets/librispeech_test.py | 119 ++++---- .../datasets/libritts_test.py | 76 ++--- .../datasets/ljspeech_test.py | 92 +++--- .../datasets/speechcommands_test.py | 102 ++++--- .../datasets/tedlium_test.py | 124 ++++---- .../datasets/utils_test.py | 63 +--- .../torchaudio_unittest/datasets/vctk_test.py | 92 +++--- .../datasets/yesno_test.py | 26 +- .../functional/functional_cpu_test.py | 107 ++++--- .../functional/functional_cuda_test.py | 14 +- .../functional/functional_impl.py | 23 ++ .../kaldi_compatibility_impl.py | 2 +- .../librosa_compatibility_test.py | 79 ++--- .../soundfile_backend/load_test.py | 56 ++++ .../sox_effect/sox_effect_test.py | 19 ++ .../sox_io_backend/info_test.py | 17 ++ .../sox_io_backend/load_test.py | 193 ++++++++++-- test/torchaudio_unittest/transducer_test.py | 276 ++++++++++++++++++ third_party/CMakeLists.txt | 95 +----- third_party/build_codec_helper.sh | 13 - third_party/patch/libsox.patch | 24 -- third_party/sox/CMakeLists.txt | 95 ++++++ third_party/{ => sox}/patch/libmad.patch | 0 third_party/transducer/CMakeLists.txt | 27 ++ torchaudio/backend/_soundfile_backend.py | 19 +- torchaudio/backend/sox_io_backend.py | 45 ++- torchaudio/csrc/{sox.cpp => pybind.cpp} | 185 +----------- .../csrc/{sox_effects.cpp => sox/effects.cpp} | 94 +++++- .../csrc/{sox_effects.h => sox/effects.h} | 20 +- .../effects_chain.cpp} | 141 ++++++++- .../effects_chain.h} | 17 +- torchaudio/csrc/{sox_io.cpp => sox/io.cpp} | 53 +++- torchaudio/csrc/{sox_io.h => sox/io.h} | 25 +- torchaudio/csrc/sox/legacy.cpp | 174 +++++++++++ torchaudio/csrc/{sox.h => sox/legacy.h} | 11 +- torchaudio/csrc/{ => sox}/register.cpp | 21 +- .../csrc/{sox_utils.cpp => sox/utils.cpp} | 8 +- torchaudio/csrc/{sox_utils.h => sox/utils.h} | 2 +- torchaudio/csrc/transducer.cpp | 93 ++++++ torchaudio/datasets/commonvoice.py | 14 +- torchaudio/datasets/utils.py | 55 +--- torchaudio/datasets/vctk.py | 39 +-- torchaudio/datasets/yesno.py | 28 +- torchaudio/functional/functional.py | 33 +-- torchaudio/prototype/__init__.py | 0 torchaudio/prototype/transducer.py | 159 ++++++++++ torchaudio/sox_effects/sox_effects.py | 10 +- 69 files changed, 2327 insertions(+), 1067 deletions(-) create mode 100644 .gitmodules delete mode 100644 test/torchaudio_unittest/assets/CommonVoice/cv-corpus-4-2019-12-10/tt/clips/common_voice_tt_00000000.wav delete mode 100644 test/torchaudio_unittest/assets/CommonVoice/cv-corpus-4-2019-12-10/tt/train.tsv create mode 100644 test/torchaudio_unittest/assets/mp3_without_ext create mode 100644 test/torchaudio_unittest/transducer_test.py delete mode 100755 third_party/build_codec_helper.sh delete mode 100644 third_party/patch/libsox.patch create mode 100644 third_party/sox/CMakeLists.txt rename third_party/{ => sox}/patch/libmad.patch (100%) create mode 100755 third_party/transducer/CMakeLists.txt rename torchaudio/csrc/{sox.cpp => pybind.cpp} (52%) rename torchaudio/csrc/{sox_effects.cpp => sox/effects.cpp} (51%) rename torchaudio/csrc/{sox_effects.h => sox/effects.h} (54%) rename torchaudio/csrc/{sox_effects_chain.cpp => sox/effects_chain.cpp} (64%) rename torchaudio/csrc/{sox_effects_chain.h => sox/effects_chain.h} (78%) rename torchaudio/csrc/{sox_io.cpp => sox/io.cpp} (72%) rename torchaudio/csrc/{sox_io.h => sox/io.h} (56%) create mode 100644 torchaudio/csrc/sox/legacy.cpp rename torchaudio/csrc/{sox.h => sox/legacy.h} (91%) rename torchaudio/csrc/{ => sox}/register.cpp (85%) rename torchaudio/csrc/{sox_utils.cpp => sox/utils.cpp} (97%) rename torchaudio/csrc/{sox_utils.h => sox/utils.h} (98%) create mode 100644 torchaudio/csrc/transducer.cpp create mode 100644 torchaudio/prototype/__init__.py create mode 100644 torchaudio/prototype/transducer.py diff --git a/.circleci/config.yml b/.circleci/config.yml index ee442189e4..d51bb3ca96 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -101,14 +101,14 @@ jobs: - run: command: | - mkdir -p third_party/archives/ - wget --no-clobber --directory-prefix=third_party/archives/ $(awk '/URL /{print $2}' third_party/CMakeLists.txt) + mkdir -p third_party/sox/archives/ + wget --no-clobber --directory-prefix=third_party/sox/archives/ $(awk '/URL /{print $2}' third_party/sox/CMakeLists.txt) - save_cache: key: tp-nix-v2-{{ checksum ".cachekey" }} paths: - - third_party/archives + - third_party/sox/archives - persist_to_workspace: root: third_party paths: @@ -411,9 +411,7 @@ jobs: paths: - conda - env - - third_party/build - third_party/install - - third_party/src - run: name: Install torchaudio command: .circleci/unittest/linux/scripts/install.sh @@ -458,9 +456,7 @@ jobs: paths: - conda - env - - third_party/build - third_party/install - - third_party/src - run: name: Install torchaudio command: docker run -t --gpus all -e UPLOAD_CHANNEL -v $PWD:$PWD -w $PWD "${image_name}" .circleci/unittest/linux/scripts/install.sh @@ -573,9 +569,7 @@ jobs: paths: - conda - env - - third_party/build - third_party/install - - third_party/src - run: name: Install torchaudio command: .circleci/unittest/linux/scripts/install.sh @@ -612,9 +606,7 @@ jobs: paths: - conda - env - - third_party/build - third_party/install - - third_party/src - run: name: Run style check command: .circleci/unittest/linux/scripts/run_style_checks.sh diff --git a/.circleci/config.yml.in b/.circleci/config.yml.in index 5c9c4d7693..9f6f41a379 100644 --- a/.circleci/config.yml.in +++ b/.circleci/config.yml.in @@ -101,14 +101,14 @@ jobs: {% endraw %} - run: command: | - mkdir -p third_party/archives/ - wget --no-clobber --directory-prefix=third_party/archives/ $(awk '/URL /{print $2}' third_party/CMakeLists.txt) + mkdir -p third_party/sox/archives/ + wget --no-clobber --directory-prefix=third_party/sox/archives/ $(awk '/URL /{print $2}' third_party/sox/CMakeLists.txt) - save_cache: {% raw %} key: tp-nix-v2-{{ checksum ".cachekey" }} {% endraw %} paths: - - third_party/archives + - third_party/sox/archives - persist_to_workspace: root: third_party paths: @@ -411,9 +411,7 @@ jobs: paths: - conda - env - - third_party/build - third_party/install - - third_party/src - run: name: Install torchaudio command: .circleci/unittest/linux/scripts/install.sh @@ -458,9 +456,7 @@ jobs: paths: - conda - env - - third_party/build - third_party/install - - third_party/src - run: name: Install torchaudio command: docker run -t --gpus all -e UPLOAD_CHANNEL -v $PWD:$PWD -w $PWD "${image_name}" .circleci/unittest/linux/scripts/install.sh @@ -573,9 +569,7 @@ jobs: paths: - conda - env - - third_party/build - third_party/install - - third_party/src - run: name: Install torchaudio command: .circleci/unittest/linux/scripts/install.sh @@ -612,9 +606,7 @@ jobs: paths: - conda - env - - third_party/build - third_party/install - - third_party/src - run: name: Run style check command: .circleci/unittest/linux/scripts/run_style_checks.sh diff --git a/.circleci/torchscript_bc_test/common.sh b/.circleci/torchscript_bc_test/common.sh index 24ad5e45fb..6f64e7204c 100644 --- a/.circleci/torchscript_bc_test/common.sh +++ b/.circleci/torchscript_bc_test/common.sh @@ -66,5 +66,6 @@ build_master() { conda install -y -q pytorch "cpuonly" -c pytorch-nightly printf "* Installing torchaudio\n" cd "${_root_dir}" || exit 1 - BUILD_SOX=1 python setup.py clean install + git submodule update --init --recursive + BUILD_TRANSDUCER=1 BUILD_SOX=1 python setup.py clean install } diff --git a/.circleci/unittest/linux/scripts/install.sh b/.circleci/unittest/linux/scripts/install.sh index 27dec79251..72b7c9c88f 100755 --- a/.circleci/unittest/linux/scripts/install.sh +++ b/.circleci/unittest/linux/scripts/install.sh @@ -38,7 +38,7 @@ conda install -y -c "pytorch-${UPLOAD_CHANNEL}" pytorch ${cudatoolkit} # 2. Install torchaudio printf "* Installing torchaudio\n" -BUILD_SOX=1 python setup.py install +BUILD_TRANSDUCER=1 BUILD_SOX=1 python setup.py install # 3. Install Test tools printf "* Installing test tools\n" @@ -46,9 +46,9 @@ if [ "${os}" == Linux ] ; then # TODO: move this to docker apt install -y -q libsndfile1 conda install -y -c conda-forge codecov pytest pytest-cov - pip install kaldi-io 'librosa>=0.8.0' parameterized SoundFile scipy + pip install kaldi-io 'librosa>=0.8.0' parameterized SoundFile scipy 'requests>=2.20' else # Note: installing librosa via pip fail because it will try to compile numba. conda install -y -c conda-forge codecov pytest pytest-cov 'librosa>=0.8.0' parameterized scipy - pip install kaldi-io SoundFile + pip install kaldi-io SoundFile 'requests>=2.20' fi diff --git a/.circleci/unittest/linux/scripts/run_test.sh b/.circleci/unittest/linux/scripts/run_test.sh index e9016d266c..2f9c10476d 100755 --- a/.circleci/unittest/linux/scripts/run_test.sh +++ b/.circleci/unittest/linux/scripts/run_test.sh @@ -17,4 +17,4 @@ declare -a args=( ) cd test -pytest "${args[@]}" torchaudio_unittest +pytest "${args[@]}" torchaudio_unittest -k "not fileobj" diff --git a/.circleci/unittest/linux/scripts/setup_env.sh b/.circleci/unittest/linux/scripts/setup_env.sh index 26292a00d5..f56b211ac9 100755 --- a/.circleci/unittest/linux/scripts/setup_env.sh +++ b/.circleci/unittest/linux/scripts/setup_env.sh @@ -43,6 +43,7 @@ conda activate "${env_dir}" pip --quiet install cmake ninja # 4. Buld codecs +git submodule update --init --recursive mkdir -p third_party/build ( cd third_party/build diff --git a/.gitignore b/.gitignore index e8a9d4c409..ae628691f5 100644 --- a/.gitignore +++ b/.gitignore @@ -123,7 +123,5 @@ examples/interactive_asr/data/*.model examples/interactive_asr/data/*.pt # third parties -third_party/archives/ third_party/install/ -third_party/src/ -third_party/tmp/ +third_party/sox/archives/ diff --git a/.gitmodules b/.gitmodules new file mode 100644 index 0000000000..c01f8c91ad --- /dev/null +++ b/.gitmodules @@ -0,0 +1,4 @@ +[submodule "third_party/warp_transducer/submodule"] + path = third_party/transducer/submodule + url = https://github.com/HawkAaron/warp-transducer + ignore = dirty diff --git a/build_tools/setup_helpers/extension.py b/build_tools/setup_helpers/extension.py index 8e6cd337cb..0dc306f07e 100644 --- a/build_tools/setup_helpers/extension.py +++ b/build_tools/setup_helpers/extension.py @@ -20,20 +20,21 @@ _TP_INSTALL_DIR = _TP_BASE_DIR / 'install' -def _get_build_sox(): - val = os.environ.get('BUILD_SOX', '0') +def _get_build(var): + val = os.environ.get(var, '0') trues = ['1', 'true', 'TRUE', 'on', 'ON', 'yes', 'YES'] falses = ['0', 'false', 'FALSE', 'off', 'OFF', 'no', 'NO'] if val in trues: return True if val not in falses: print( - f'WARNING: Unexpected environment variable value `BUILD_SOX={val}`. ' + f'WARNING: Unexpected environment variable value `{var}={val}`. ' f'Expected one of {trues + falses}') return False -_BUILD_SOX = _get_build_sox() +_BUILD_SOX = _get_build("BUILD_SOX") +_BUILD_TRANSDUCER = _get_build("BUILD_TRANSDUCER") def _get_eca(debug): @@ -42,6 +43,8 @@ def _get_eca(debug): eca += ["-O0", "-g"] else: eca += ["-O3"] + if _BUILD_TRANSDUCER: + eca += ['-DBUILD_TRANSDUCER'] return eca @@ -58,27 +61,31 @@ def _get_ela(debug): def _get_srcs(): - return [str(p) for p in _CSRC_DIR.glob('**/*.cpp')] + srcs = [_CSRC_DIR / 'pybind.cpp'] + srcs += list(_CSRC_DIR.glob('sox/**/*.cpp')) + if _BUILD_TRANSDUCER: + srcs += [_CSRC_DIR / 'transducer.cpp'] + return [str(path) for path in srcs] def _get_include_dirs(): dirs = [ str(_ROOT_DIR), ] - if _BUILD_SOX: + if _BUILD_SOX or _BUILD_TRANSDUCER: dirs.append(str(_TP_INSTALL_DIR / 'include')) return dirs def _get_extra_objects(): - objs = [] + libs = [] if _BUILD_SOX: # NOTE: The order of the library listed bellow matters. # # (the most important thing is that dependencies come after a library # e.g., sox comes first, flac/vorbis comes before ogg, and # vorbisenc/vorbisfile comes before vorbis - libs = [ + libs += [ 'libsox.a', 'libmad.a', 'libFLAC.a', @@ -92,25 +99,34 @@ def _get_extra_objects(): 'libopencore-amrnb.a', 'libopencore-amrwb.a', ] - for lib in libs: - objs.append(str(_TP_INSTALL_DIR / 'lib' / lib)) - return objs + if _BUILD_TRANSDUCER: + libs += ['libwarprnnt.a'] + + return [str(_TP_INSTALL_DIR / 'lib' / lib) for lib in libs] def _get_libraries(): return [] if _BUILD_SOX else ['sox'] -def _build_third_party(): - build_dir = str(_TP_BASE_DIR / 'build') +def _build_third_party(base_build_dir): + build_dir = os.path.join(base_build_dir, 'third_party') os.makedirs(build_dir, exist_ok=True) subprocess.run( - args=['cmake', '..'], + args=[ + 'cmake', + f'-DCMAKE_INSTALL_PREFIX={_TP_INSTALL_DIR}', + f'-DBUILD_SOX={"ON" if _BUILD_SOX else "OFF"}', + f'-DBUILD_TRANSDUCER={"ON" if _BUILD_TRANSDUCER else "OFF"}', + f'{_TP_BASE_DIR}'], cwd=build_dir, check=True, ) + command = ['cmake', '--build', '.'] + if _BUILD_TRANSDUCER: + command += ['--target', 'install'] subprocess.run( - args=['cmake', '--build', '.'], + args=command, cwd=build_dir, check=True, ) @@ -138,5 +154,5 @@ def get_ext_modules(debug=False): class BuildExtension(TorchBuildExtension): def build_extension(self, ext): if ext.name == _EXT_NAME and _BUILD_SOX: - _build_third_party() + _build_third_party(self.build_temp) super().build_extension(ext) diff --git a/packaging/build_wheel.sh b/packaging/build_wheel.sh index ad45a08d59..957b41e048 100755 --- a/packaging/build_wheel.sh +++ b/packaging/build_wheel.sh @@ -15,5 +15,5 @@ if [[ "$OSTYPE" == "msys" ]]; then python_tag="$(echo "cp$PYTHON_VERSION" | tr -d '.')" python setup.py bdist_wheel --plat-name win_amd64 --python-tag $python_tag else - BUILD_SOX=1 python setup.py bdist_wheel + BUILD_TRANSDUCER=1 BUILD_SOX=1 python setup.py bdist_wheel fi diff --git a/packaging/pkg_helpers.bash b/packaging/pkg_helpers.bash index 3316f789e2..635bfa3a14 100644 --- a/packaging/pkg_helpers.bash +++ b/packaging/pkg_helpers.bash @@ -103,6 +103,7 @@ setup_macos() { # # Usage: setup_env 0.2.0 setup_env() { + git submodule update --init --recursive setup_cuda setup_build_version "$1" setup_macos diff --git a/packaging/torchaudio/build.sh b/packaging/torchaudio/build.sh index 99c17b6913..88bbfce375 100644 --- a/packaging/torchaudio/build.sh +++ b/packaging/torchaudio/build.sh @@ -1,4 +1,4 @@ #!/usr/bin/env bash set -ex -BUILD_SOX=1 python setup.py install --single-version-externally-managed --record=record.txt +BUILD_TRANSDUCER=1 BUILD_SOX=1 python setup.py install --single-version-externally-managed --record=record.txt diff --git a/setup.py b/setup.py index 4ced5fc8fd..8168472ecf 100644 --- a/setup.py +++ b/setup.py @@ -50,7 +50,6 @@ def run(self): # Remove build directory build_dirs = [ ROOT_DIR / 'build', - ROOT_DIR / 'third_party' / 'build', ] for path in build_dirs: if path.exists(): @@ -83,7 +82,8 @@ def run(self): packages=find_packages(exclude=["build*", "test*", "torchaudio.csrc*", "third_party*", "build_tools*"]), ext_modules=setup_helpers.get_ext_modules(), cmdclass={ - 'build_ext': setup_helpers.BuildExtension.with_options(no_python_abi_suffix=True) + 'build_ext': setup_helpers.BuildExtension.with_options(no_python_abi_suffix=True), + 'clean': clean, }, install_requires=[pytorch_package_dep], zip_safe=False, diff --git a/test/torchaudio_unittest/README.md b/test/torchaudio_unittest/README.md index 119c644687..50d17d9948 100644 --- a/test/torchaudio_unittest/README.md +++ b/test/torchaudio_unittest/README.md @@ -2,7 +2,7 @@ ## How to run test -You can use `pytest` to run `torchaudio`'s test suites. See https://docs.pytest.org/ for the detail of how to use `pytest` command. +You can use `pytest` to run `torchaudio`'s test suites. See https://docs.pytest.org/ for the detail of how to use `pytest` command. The `parametrized` package is also needed; it can be installed via `pip` or with ` conda install -c conda-forge parameterized`. ``` # List up all the tests diff --git a/test/torchaudio_unittest/assets/CommonVoice/cv-corpus-4-2019-12-10/tt/clips/common_voice_tt_00000000.wav b/test/torchaudio_unittest/assets/CommonVoice/cv-corpus-4-2019-12-10/tt/clips/common_voice_tt_00000000.wav deleted file mode 100644 index 8f9d80d7e152b418703d0421f8ea5e0b710d6a89..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 80700 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 diff --git a/test/torchaudio_unittest/assets/CommonVoice/cv-corpus-4-2019-12-10/tt/train.tsv b/test/torchaudio_unittest/assets/CommonVoice/cv-corpus-4-2019-12-10/tt/train.tsv deleted file mode 100644 index a5244b01f2..0000000000 --- a/test/torchaudio_unittest/assets/CommonVoice/cv-corpus-4-2019-12-10/tt/train.tsv +++ /dev/null @@ -1,3 +0,0 @@ -client_id path sentence up_votes down_votes age gender accent -00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 common_voice_tt_00000000.wav test. 1 0 thirties female -00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001 common_voice_tt_00000000.wav test. 1 0 thirties female diff --git a/test/torchaudio_unittest/assets/mp3_without_ext b/test/torchaudio_unittest/assets/mp3_without_ext new file mode 100644 index 0000000000000000000000000000000000000000..e4d4e6973e1cd0d8262ad3c88edbcc0464bf4663 GIT binary patch literal 15453 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 DHUU%3 literal 0 HcmV?d00001 diff --git a/test/torchaudio_unittest/common_utils/__init__.py b/test/torchaudio_unittest/common_utils/__init__.py index 105a054864..cf3e717116 100644 --- a/test/torchaudio_unittest/common_utils/__init__.py +++ b/test/torchaudio_unittest/common_utils/__init__.py @@ -8,6 +8,7 @@ ) from .case_utils import ( TempDirMixin, + HttpServerMixin, TestBaseMixin, PytorchTestCase, TorchaudioTestCase, diff --git a/test/torchaudio_unittest/common_utils/case_utils.py b/test/torchaudio_unittest/common_utils/case_utils.py index 2e0a17b5da..9a9d491541 100644 --- a/test/torchaudio_unittest/common_utils/case_utils.py +++ b/test/torchaudio_unittest/common_utils/case_utils.py @@ -1,6 +1,8 @@ import shutil import os.path +import subprocess import tempfile +import time import unittest import torch @@ -40,6 +42,32 @@ def get_temp_path(self, *paths): return path +class HttpServerMixin(TempDirMixin): + """Mixin that serves temporary directory as web server + + This class creates temporary directory and serve the directory as HTTP service. + The server is up through the execution of all the test suite defined under the subclass. + """ + _proc = None + _port = 8000 + + @classmethod + def setUpClass(cls): + super().setUpClass() + cls._proc = subprocess.Popen( + ['python', '-m', 'http.server', f'{cls._port}'], + cwd=cls.get_base_temp_dir()) + time.sleep(1.0) + + @classmethod + def tearDownClass(cls): + super().tearDownClass() + cls._proc.kill() + + def get_url(self, *route): + return f'http://localhost:{self._port}/{self.id()}/{"/".join(route)}' + + class TestBaseMixin: """Mixin to provide consistent way to define device/dtype/backend aware TestCase""" dtype = None diff --git a/test/torchaudio_unittest/datasets/cmuarctic_test.py b/test/torchaudio_unittest/datasets/cmuarctic_test.py index f8f7969c25..dd91edafca 100644 --- a/test/torchaudio_unittest/datasets/cmuarctic_test.py +++ b/test/torchaudio_unittest/datasets/cmuarctic_test.py @@ -12,6 +12,47 @@ ) +def get_mock_dataset(root_dir): + """ + root_dir: directory to the mocked dataset + """ + mocked_data = [] + sample_rate = 16000 + utterance = "This is a test utterance." + + base_dir = os.path.join(root_dir, "ARCTIC", "cmu_us_aew_arctic") + txt_dir = os.path.join(base_dir, "etc") + os.makedirs(txt_dir, exist_ok=True) + txt_file = os.path.join(txt_dir, "txt.done.data") + audio_dir = os.path.join(base_dir, "wav") + os.makedirs(audio_dir, exist_ok=True) + + seed = 42 + with open(txt_file, "w") as txt: + for c in ["a", "b"]: + for i in range(5): + utterance_id = f"arctic_{c}{i:04d}" + path = os.path.join(audio_dir, f"{utterance_id}.wav") + data = get_whitenoise( + sample_rate=sample_rate, + duration=3, + n_channels=1, + dtype="int16", + seed=seed, + ) + save_wav(path, data, sample_rate) + sample = ( + normalize_wav(data), + sample_rate, + utterance, + utterance_id.split("_")[1], + ) + mocked_data.append(sample) + txt.write(f'( {utterance_id} "{utterance}" )\n') + seed += 1 + return mocked_data + + class TestCMUARCTIC(TempDirMixin, TorchaudioTestCase): backend = "default" @@ -21,39 +62,7 @@ class TestCMUARCTIC(TempDirMixin, TorchaudioTestCase): @classmethod def setUpClass(cls): cls.root_dir = cls.get_base_temp_dir() - sample_rate = 16000 - utterance = "This is a test utterance." - - base_dir = os.path.join(cls.root_dir, "ARCTIC", "cmu_us_aew_arctic") - txt_dir = os.path.join(base_dir, "etc") - os.makedirs(txt_dir, exist_ok=True) - txt_file = os.path.join(txt_dir, "txt.done.data") - audio_dir = os.path.join(base_dir, "wav") - os.makedirs(audio_dir, exist_ok=True) - - seed = 42 - with open(txt_file, "w") as txt: - for c in ["a", "b"]: - for i in range(5): - utterance_id = f"arctic_{c}{i:04d}" - path = os.path.join(audio_dir, f"{utterance_id}.wav") - data = get_whitenoise( - sample_rate=sample_rate, - duration=3, - n_channels=1, - dtype="int16", - seed=seed, - ) - save_wav(path, data, sample_rate) - sample = ( - normalize_wav(data), - sample_rate, - utterance, - utterance_id.split("_")[1], - ) - cls.samples.append(sample) - txt.write(f'( {utterance_id} "{utterance}" )\n') - seed += 1 + cls.samples = get_mock_dataset(cls.root_dir) def _test_cmuarctic(self, dataset): n_ite = 0 diff --git a/test/torchaudio_unittest/datasets/commonvoice_test.py b/test/torchaudio_unittest/datasets/commonvoice_test.py index 22c811a67b..4d7c269f2a 100644 --- a/test/torchaudio_unittest/datasets/commonvoice_test.py +++ b/test/torchaudio_unittest/datasets/commonvoice_test.py @@ -1,8 +1,9 @@ -import os import csv +import os from pathlib import Path +from typing import Tuple, Dict -from torchaudio.datasets import COMMONVOICE +from torch import Tensor from torchaudio_unittest.common_utils import ( TempDirMixin, TorchaudioTestCase, @@ -11,47 +12,97 @@ normalize_wav, ) +from torchaudio.datasets import COMMONVOICE -class TestCommonVoice(TempDirMixin, TorchaudioTestCase): - backend = 'default' +_ORIGINAL_EXT_AUDIO = COMMONVOICE._ext_audio +_SAMPLE_RATE = 48000 +_HEADERS = [u"client_ids", u"path", u"sentence", u"up_votes", u"down_votes", u"age", u"gender", u"accent"] +_EN_TRAIN_CSV_CONTENTS = [ + ["9d16c5d980247861130e0480e2719f448be73d86a496c36d01a477cbdecd8cfd1399403d7a77bf458d211a70711b2da0845c", + "common_voice_en_18885784.wav", + "He was accorded a State funeral, and was buried in Drayton and Toowoomba Cemetery.", "2", "0", "", "", + ""], + ["c82eb9291328620f06025a1f8112b909099e447e485e99236cb87df008650250e79fea5ca772061fb6a370830847b9c44d20", + "common_voice_en_556542.wav", "Once more into the breach", "2", "0", "thirties", "male", "us"], + ["f74d880c5ad4c5917f314a604d3fc4805159d255796fb9f8defca35333ecc002bdf53dc463503c12674ea840b21b4a507b7c", + "common_voice_en_18607573.wav", + "Caddy, show Miss Clare and Miss Summerson their rooms.", "2", "0", "twenties", "male", "canada"], +] - root_dir = None - data = [] - _headers = [u"client_ids", u"path", u"sentence", u"up_votes", u"down_votes", u"age", u"gender", u"accent"] +_FR_TRAIN_CSV_CONTENTS = [ + [ + "a2e8e1e1cc74d08c92a53d7b9ff84e077eb90410edd85b8882f16fd037cecfcb6a19413c6c63ce6458cfea9579878fa91cef" + "18343441c601cae0597a4b0d3144", + "89e67e7682b36786a0b4b4022c4d42090c86edd96c78c12d30088e62522b8fe466ea4912e6a1055dfb91b296a0743e0a2bbe" + "16cebac98ee5349e3e8262cb9329", + "Or sur ce point nous nโ€™avons aucune rรฉponse de votre part.", "2", "0", "twenties", "male", "france"], + [ + "a2e8e1e1cc74d08c92a53d7b9ff84e077eb90410edd85b8882f16fd037cecfcb6a19413c6c63ce6458cfea9579878fa91cef18" + "343441c601cae0597a4b0d3144", + "87d71819a26179e93acfee149d0b21b7bf5e926e367d80b2b3792d45f46e04853a514945783ff764c1fc237b4eb0ee2b0a7a7" + "cbd395acbdfcfa9d76a6e199bbd", + "Monsieur de La Verpilliรจre, laissez parler le ministre", "2", "0", "twenties", "male", "france"], + +] + + +def get_mock_dataset(root_dir, train_csv_contents, ext_audio) -> Tuple[Tensor, int, Dict[str, str]]: + """ + prepares mocked dataset + """ + mocked_data = [] # Note: extension is changed to wav for the sake of test # Note: the first content is missing values for `age`, `gender` and `accent` as in the original data. - _train_csv_contents = [ - ["9d16c5d980247861130e0480e2719f448be73d86a496c36d01a477cbdecd8cfd1399403d7a77bf458d211a70711b2da0845c", - "common_voice_en_18885784.wav", - "He was accorded a State funeral, and was buried in Drayton and Toowoomba Cemetery.", "2", "0", "", "", ""], - ["c82eb9291328620f06025a1f8112b909099e447e485e99236cb87df008650250e79fea5ca772061fb6a370830847b9c44d20", - "common_voice_en_556542.wav", "Once more into the breach", "2", "0", "thirties", "male", "us"], - ["f74d880c5ad4c5917f314a604d3fc4805159d255796fb9f8defca35333ecc002bdf53dc463503c12674ea840b21b4a507b7c", - "common_voice_en_18607573.wav", - "Caddy, show Miss Clare and Miss Summerson their rooms.", "2", "0", "twenties", "male", "canada"], - ] - sample_rate = 48000 + # Tsv file name difference does not mean different subset, testing as a whole dataset here + tsv_filename = os.path.join(root_dir, "train.tsv") + audio_base_path = os.path.join(root_dir, "clips") + os.makedirs(audio_base_path, exist_ok=True) + with open(tsv_filename, "w", newline='') as tsv: + writer = csv.writer(tsv, delimiter='\t') + writer.writerow(_HEADERS) + for i, content in enumerate(train_csv_contents): + content[2] = str(content[2].encode("utf-8")) + writer.writerow(content) + if not content[1].endswith(ext_audio): + audio_path = os.path.join(audio_base_path, content[1] + ext_audio) + else: + audio_path = os.path.join(audio_base_path, content[1]) + + data = get_whitenoise(sample_rate=_SAMPLE_RATE, duration=1, n_channels=1, seed=i, dtype='float32') + save_wav(audio_path, data, _SAMPLE_RATE) + # Append data entry + mocked_data.append((normalize_wav(data), _SAMPLE_RATE, dict(zip(_HEADERS, content)))) + return mocked_data + + +def get_mock_dataset_en(root_dir, ext_audio) -> Tuple[Tensor, int, Dict[str, str]]: + """ + prepares english mocked dataset + """ + return get_mock_dataset(root_dir, _EN_TRAIN_CSV_CONTENTS, ext_audio) + + +def get_mock_dataset_fr(root_dir, ext_audio) -> Tuple[Tensor, int, Dict[str, str]]: + """ + prepares french mocked dataset + """ + return get_mock_dataset(root_dir, _FR_TRAIN_CSV_CONTENTS, ext_audio) + + +class BaseTestCommonVoice(TempDirMixin): + root_dir = None + data = None @classmethod def setUpClass(cls): + super().setUpClass() cls.root_dir = cls.get_base_temp_dir() - # Tsv file name difference does not mean different subset, testing as a whole dataset here - tsv_filename = os.path.join(cls.root_dir, "train.tsv") - audio_base_path = os.path.join(cls.root_dir, "clips") - os.makedirs(audio_base_path, exist_ok=True) - with open(tsv_filename, "w", newline='') as tsv: - writer = csv.writer(tsv, delimiter='\t') - writer.writerow(cls._headers) - for i, content in enumerate(cls._train_csv_contents): - writer.writerow(content) - - # Generate and store audio - audio_path = os.path.join(audio_base_path, content[1]) - data = get_whitenoise(sample_rate=cls.sample_rate, duration=1, n_channels=1, seed=i, dtype='float32') - save_wav(audio_path, data, cls.sample_rate) + COMMONVOICE._ext_audio = ".wav" - # Append data entry - cls.data.append((normalize_wav(data), cls.sample_rate, dict(zip(cls._headers, content)))) + @classmethod + def tearDownClass(cls): + super().tearDownClass() + COMMONVOICE._ext_audio = _ORIGINAL_EXT_AUDIO def _test_commonvoice(self, dataset): n_ite = 0 @@ -59,11 +110,21 @@ def _test_commonvoice(self, dataset): expected_dictionary = self.data[i][2] expected_data = self.data[i][0] self.assertEqual(expected_data, waveform, atol=5e-5, rtol=1e-8) - assert sample_rate == TestCommonVoice.sample_rate + assert sample_rate == _SAMPLE_RATE assert dictionary == expected_dictionary n_ite += 1 assert n_ite == len(self.data) + +class TestCommonVoiceEN(BaseTestCommonVoice, TorchaudioTestCase): + backend = 'default' + root_dir = None + + @classmethod + def setUpClass(cls): + super().setUpClass() + cls.data = get_mock_dataset_en(cls.root_dir, COMMONVOICE._ext_audio) + def test_commonvoice_str(self): dataset = COMMONVOICE(self.root_dir) self._test_commonvoice(dataset) @@ -71,3 +132,17 @@ def test_commonvoice_str(self): def test_commonvoice_path(self): dataset = COMMONVOICE(Path(self.root_dir)) self._test_commonvoice(dataset) + + +class TestCommonVoiceFR(BaseTestCommonVoice, TorchaudioTestCase): + backend = 'default' + root_dir = None + + @classmethod + def setUpClass(cls): + super().setUpClass() + cls.data = get_mock_dataset_fr(cls.root_dir, COMMONVOICE._ext_audio) + + def test_commonvoice_str(self): + dataset = COMMONVOICE(self.root_dir) + self._test_commonvoice(dataset) diff --git a/test/torchaudio_unittest/datasets/gtzan_test.py b/test/torchaudio_unittest/datasets/gtzan_test.py index 763e0a866f..838292f55d 100644 --- a/test/torchaudio_unittest/datasets/gtzan_test.py +++ b/test/torchaudio_unittest/datasets/gtzan_test.py @@ -12,6 +12,37 @@ ) +def get_mock_dataset(root_dir): + """ + root_dir: directory to the mocked dataset + """ + mocked_samples = [] + mocked_training = [] + mocked_validation = [] + mocked_testing = [] + sample_rate = 22050 + + seed = 0 + for genre in gtzan.gtzan_genres: + base_dir = os.path.join(root_dir, 'genres', genre) + os.makedirs(base_dir, exist_ok=True) + for i in range(100): + filename = f'{genre}.{i:05d}' + path = os.path.join(base_dir, f'{filename}.wav') + data = get_whitenoise(sample_rate=sample_rate, duration=0.01, n_channels=1, dtype='int16', seed=seed) + save_wav(path, data, sample_rate) + sample = (normalize_wav(data), sample_rate, genre) + mocked_samples.append(sample) + if filename in gtzan.filtered_test: + mocked_testing.append(sample) + if filename in gtzan.filtered_train: + mocked_training.append(sample) + if filename in gtzan.filtered_valid: + mocked_validation.append(sample) + seed += 1 + return (mocked_samples, mocked_training, mocked_validation, mocked_testing) + + class TestGTZAN(TempDirMixin, TorchaudioTestCase): backend = 'default' @@ -24,25 +55,11 @@ class TestGTZAN(TempDirMixin, TorchaudioTestCase): @classmethod def setUpClass(cls): cls.root_dir = cls.get_base_temp_dir() - sample_rate = 22050 - seed = 0 - for genre in gtzan.gtzan_genres: - base_dir = os.path.join(cls.root_dir, 'genres', genre) - os.makedirs(base_dir, exist_ok=True) - for i in range(100): - filename = f'{genre}.{i:05d}' - path = os.path.join(base_dir, f'{filename}.wav') - data = get_whitenoise(sample_rate=sample_rate, duration=0.01, n_channels=1, dtype='int16', seed=seed) - save_wav(path, data, sample_rate) - sample = (normalize_wav(data), sample_rate, genre) - cls.samples.append(sample) - if filename in gtzan.filtered_test: - cls.testing.append(sample) - if filename in gtzan.filtered_train: - cls.training.append(sample) - if filename in gtzan.filtered_valid: - cls.validation.append(sample) - seed += 1 + mocked_data = get_mock_dataset(cls.root_dir) + cls.samples = mocked_data[0] + cls.training = mocked_data[1] + cls.validation = mocked_data[2] + cls.testing = mocked_data[3] def test_no_subset(self): dataset = gtzan.GTZAN(self.root_dir) diff --git a/test/torchaudio_unittest/datasets/librispeech_test.py b/test/torchaudio_unittest/datasets/librispeech_test.py index b0eabb767c..0fab5356f6 100644 --- a/test/torchaudio_unittest/datasets/librispeech_test.py +++ b/test/torchaudio_unittest/datasets/librispeech_test.py @@ -1,8 +1,6 @@ import os from pathlib import Path -from torchaudio.datasets import librispeech - from torchaudio_unittest.common_utils import ( TempDirMixin, TorchaudioTestCase, @@ -11,8 +9,10 @@ normalize_wav, ) +from torchaudio.datasets import librispeech + # Used to generate a unique utterance for each dummy audio file -NUMBERS = [ +_NUMBERS = [ 'ZERO', 'ONE', 'TWO', @@ -26,6 +26,65 @@ ] +def get_mock_dataset(root_dir): + """ + root_dir: directory to the mocked dataset + """ + mocked_data = [] + dataset_dir = os.path.join( + root_dir, librispeech.FOLDER_IN_ARCHIVE, librispeech.URL + ) + os.makedirs(dataset_dir, exist_ok=True) + sample_rate = 16000 # 16kHz + seed = 0 + + for speaker_id in range(5): + speaker_path = os.path.join(dataset_dir, str(speaker_id)) + os.makedirs(speaker_path, exist_ok=True) + + for chapter_id in range(3): + chapter_path = os.path.join(speaker_path, str(chapter_id)) + os.makedirs(chapter_path, exist_ok=True) + trans_content = [] + + for utterance_id in range(10): + filename = f'{speaker_id}-{chapter_id}-{utterance_id:04d}.wav' + path = os.path.join(chapter_path, filename) + + utterance = ' '.join( + [_NUMBERS[x] for x in [speaker_id, chapter_id, utterance_id]] + ) + trans_content.append( + f'{speaker_id}-{chapter_id}-{utterance_id:04d} {utterance}' + ) + + data = get_whitenoise( + sample_rate=sample_rate, + duration=0.01, + n_channels=1, + dtype='float32', + seed=seed + ) + save_wav(path, data, sample_rate) + sample = ( + normalize_wav(data), + sample_rate, + utterance, + speaker_id, + chapter_id, + utterance_id + ) + mocked_data.append(sample) + + seed += 1 + + trans_filename = f'{speaker_id}-{chapter_id}.trans.txt' + trans_path = os.path.join(chapter_path, trans_filename) + with open(trans_path, 'w') as f: + f.write('\n'.join(trans_content)) + return mocked_data + + class TestLibriSpeech(TempDirMixin, TorchaudioTestCase): backend = 'default' @@ -35,57 +94,7 @@ class TestLibriSpeech(TempDirMixin, TorchaudioTestCase): @classmethod def setUpClass(cls): cls.root_dir = cls.get_base_temp_dir() - dataset_dir = os.path.join( - cls.root_dir, librispeech.FOLDER_IN_ARCHIVE, librispeech.URL - ) - os.makedirs(dataset_dir, exist_ok=True) - sample_rate = 16000 # 16kHz - seed = 0 - - for speaker_id in range(5): - speaker_path = os.path.join(dataset_dir, str(speaker_id)) - os.makedirs(speaker_path, exist_ok=True) - - for chapter_id in range(3): - chapter_path = os.path.join(speaker_path, str(chapter_id)) - os.makedirs(chapter_path, exist_ok=True) - trans_content = [] - - for utterance_id in range(10): - filename = f'{speaker_id}-{chapter_id}-{utterance_id:04d}.wav' - path = os.path.join(chapter_path, filename) - - utterance = ' '.join( - [NUMBERS[x] for x in [speaker_id, chapter_id, utterance_id]] - ) - trans_content.append( - f'{speaker_id}-{chapter_id}-{utterance_id:04d} {utterance}' - ) - - data = get_whitenoise( - sample_rate=sample_rate, - duration=0.01, - n_channels=1, - dtype='float32', - seed=seed - ) - save_wav(path, data, sample_rate) - sample = ( - normalize_wav(data), - sample_rate, - utterance, - speaker_id, - chapter_id, - utterance_id - ) - cls.samples.append(sample) - - seed += 1 - - trans_filename = f'{speaker_id}-{chapter_id}.trans.txt' - trans_path = os.path.join(chapter_path, trans_filename) - with open(trans_path, 'w') as f: - f.write('\n'.join(trans_content)) + cls.samples = get_mock_dataset(cls.root_dir) @classmethod def tearDownClass(cls): @@ -95,7 +104,7 @@ def tearDownClass(cls): def _test_librispeech(self, dataset): num_samples = 0 for i, ( - data, sample_rate, utterance, speaker_id, chapter_id, utterance_id + data, sample_rate, utterance, speaker_id, chapter_id, utterance_id ) in enumerate(dataset): self.assertEqual(data, self.samples[i][0], atol=5e-5, rtol=1e-8) assert sample_rate == self.samples[i][1] diff --git a/test/torchaudio_unittest/datasets/libritts_test.py b/test/torchaudio_unittest/datasets/libritts_test.py index 04d47e95f4..32e6dbcf73 100644 --- a/test/torchaudio_unittest/datasets/libritts_test.py +++ b/test/torchaudio_unittest/datasets/libritts_test.py @@ -1,8 +1,6 @@ import os from pathlib import Path -from torchaudio.datasets.libritts import LIBRITTS - from torchaudio_unittest.common_utils import ( TempDirMixin, TorchaudioTestCase, @@ -11,42 +9,55 @@ normalize_wav, ) +from torchaudio.datasets.libritts import LIBRITTS + +_UTTERANCE_IDS = [ + [19, 198, '000000', '000000'], + [26, 495, '000004', '000000'], +] +_ORIGINAL_TEXT = 'this is the original text.' +_NORMALIZED_TEXT = 'this is the normalized text.' + + +def get_mock_dataset(root_dir): + """ + root_dir: directory to the mocked dataset + """ + mocked_data = [] + base_dir = os.path.join(root_dir, 'LibriTTS', 'train-clean-100') + for i, utterance_id in enumerate(_UTTERANCE_IDS): + filename = f'{"_".join(str(u) for u in utterance_id)}.wav' + file_dir = os.path.join(base_dir, str(utterance_id[0]), str(utterance_id[1])) + os.makedirs(file_dir, exist_ok=True) + path = os.path.join(file_dir, filename) + + data = get_whitenoise(sample_rate=24000, duration=2, n_channels=1, dtype='int16', seed=i) + save_wav(path, data, 24000) + mocked_data.append(normalize_wav(data)) + + original_text_filename = f'{"_".join(str(u) for u in utterance_id)}.original.txt' + path_original = os.path.join(file_dir, original_text_filename) + with open(path_original, 'w') as file_: + file_.write(_ORIGINAL_TEXT) + + normalized_text_filename = f'{"_".join(str(u) for u in utterance_id)}.normalized.txt' + path_normalized = os.path.join(file_dir, normalized_text_filename) + with open(path_normalized, 'w') as file_: + file_.write(_NORMALIZED_TEXT) + return mocked_data, _UTTERANCE_IDS, _ORIGINAL_TEXT, _NORMALIZED_TEXT + class TestLibriTTS(TempDirMixin, TorchaudioTestCase): backend = 'default' root_dir = None data = [] - utterance_ids = [ - [19, 198, '000000', '000000'], - [26, 495, '000004', '000000'], - ] - original_text = 'this is the original text.' - normalized_text = 'this is the normalized text.' + _utterance_ids, _original_text, _normalized_text = [], [], [] @classmethod def setUpClass(cls): cls.root_dir = cls.get_base_temp_dir() - base_dir = os.path.join(cls.root_dir, 'LibriTTS', 'train-clean-100') - for i, utterance_id in enumerate(cls.utterance_ids): - filename = f'{"_".join(str(u) for u in utterance_id)}.wav' - file_dir = os.path.join(base_dir, str(utterance_id[0]), str(utterance_id[1])) - os.makedirs(file_dir, exist_ok=True) - path = os.path.join(file_dir, filename) - - data = get_whitenoise(sample_rate=24000, duration=2, n_channels=1, dtype='int16', seed=i) - save_wav(path, data, 24000) - cls.data.append(normalize_wav(data)) - - original_text_filename = f'{"_".join(str(u) for u in utterance_id)}.original.txt' - path_original = os.path.join(file_dir, original_text_filename) - with open(path_original, 'w') as file_: - file_.write(cls.original_text) - - normalized_text_filename = f'{"_".join(str(u) for u in utterance_id)}.normalized.txt' - path_normalized = os.path.join(file_dir, normalized_text_filename) - with open(path_normalized, 'w') as file_: - file_.write(cls.normalized_text) + cls.data, cls._utterance_ids, cls._original_text, cls._normalized_text = get_mock_dataset(cls.root_dir) def _test_libritts(self, dataset): n_ites = 0 @@ -57,18 +68,17 @@ def _test_libritts(self, dataset): speaker_id, chapter_id, utterance_id) in enumerate(dataset): - - expected_ids = self.utterance_ids[i] + expected_ids = self._utterance_ids[i] expected_data = self.data[i] self.assertEqual(expected_data, waveform, atol=5e-5, rtol=1e-8) assert sample_rate == 24000 assert speaker_id == expected_ids[0] assert chapter_id == expected_ids[1] - assert original_text == self.original_text - assert normalized_text == self.normalized_text + assert original_text == self._original_text + assert normalized_text == self._normalized_text assert utterance_id == f'{"_".join(str(u) for u in expected_ids[-4:])}' n_ites += 1 - assert n_ites == len(self.utterance_ids) + assert n_ites == len(self._utterance_ids) def test_libritts_str(self): dataset = LIBRITTS(self.root_dir) diff --git a/test/torchaudio_unittest/datasets/ljspeech_test.py b/test/torchaudio_unittest/datasets/ljspeech_test.py index 33458fd6e1..4cf834b226 100644 --- a/test/torchaudio_unittest/datasets/ljspeech_test.py +++ b/test/torchaudio_unittest/datasets/ljspeech_test.py @@ -2,8 +2,6 @@ import os from pathlib import Path -from torchaudio.datasets import ljspeech - from torchaudio_unittest.common_utils import ( TempDirMixin, TorchaudioTestCase, @@ -12,59 +10,71 @@ save_wav, ) +from torchaudio.datasets import ljspeech + +_TRANSCRIPTS = [ + "Test transcript 1", + "Test transcript 2", + "Test transcript 3", + "In 1465 Sweynheim and Pannartz began printing in the monastery of Subiaco near Rome," +] + +_NORMALIZED_TRANSCRIPT = [ + "Test transcript one", + "Test transcript two", + "Test transcript three", + "In fourteen sixty-five Sweynheim and Pannartz began printing in the monastery of Subiaco near Rome," +] + + +def get_mock_dataset(root_dir): + """ + root_dir: path to the mocked dataset + """ + mocked_data = [] + base_dir = os.path.join(root_dir, "LJSpeech-1.1") + archive_dir = os.path.join(base_dir, "wavs") + os.makedirs(archive_dir, exist_ok=True) + metadata_path = os.path.join(base_dir, "metadata.csv") + sample_rate = 22050 + + with open(metadata_path, mode="w", newline='') as metadata_file: + metadata_writer = csv.writer( + metadata_file, delimiter="|", quoting=csv.QUOTE_NONE + ) + for i, (transcript, normalized_transcript) in enumerate( + zip(_TRANSCRIPTS, _NORMALIZED_TRANSCRIPT) + ): + fileid = f'LJ001-{i:04d}' + metadata_writer.writerow([fileid, transcript, normalized_transcript]) + filename = fileid + ".wav" + path = os.path.join(archive_dir, filename) + data = get_whitenoise( + sample_rate=sample_rate, duration=1, n_channels=1, dtype="int16", seed=i + ) + save_wav(path, data, sample_rate) + mocked_data.append(normalize_wav(data)) + return mocked_data, _TRANSCRIPTS, _NORMALIZED_TRANSCRIPT + class TestLJSpeech(TempDirMixin, TorchaudioTestCase): backend = "default" root_dir = None - data = [] - transcripts = [ - "Test transcript 1", - "Test transcript 2", - "Test transcript 3", - "In 1465 Sweynheim and Pannartz began printing in the monastery of Subiaco near Rome," - ] - - normalized_transcripts = [ - "Test transcript one", - "Test transcript two", - "Test transcript three", - "In fourteen sixty-five Sweynheim and Pannartz began printing in the monastery of Subiaco near Rome," - ] + data, _transcripts, _normalized_transcript = [], [], [] @classmethod def setUpClass(cls): cls.root_dir = cls.get_base_temp_dir() - base_dir = os.path.join(cls.root_dir, "LJSpeech-1.1") - archive_dir = os.path.join(base_dir, "wavs") - os.makedirs(archive_dir, exist_ok=True) - metadata_path = os.path.join(base_dir, "metadata.csv") - sample_rate = 22050 - - with open(metadata_path, mode="w", newline='') as metadata_file: - metadata_writer = csv.writer( - metadata_file, delimiter="|", quoting=csv.QUOTE_NONE - ) - for i, (transcript, normalized_transcript) in enumerate( - zip(cls.transcripts, cls.normalized_transcripts) - ): - fileid = f'LJ001-{i:04d}' - metadata_writer.writerow([fileid, transcript, normalized_transcript]) - filename = fileid + ".wav" - path = os.path.join(archive_dir, filename) - data = get_whitenoise( - sample_rate=sample_rate, duration=1, n_channels=1, dtype="int16", seed=i - ) - save_wav(path, data, sample_rate) - cls.data.append(normalize_wav(data)) + cls.data, cls._transcripts, cls._normalized_transcript = get_mock_dataset(cls.root_dir) def _test_ljspeech(self, dataset): n_ite = 0 for i, (waveform, sample_rate, transcript, normalized_transcript) in enumerate( - dataset + dataset ): - expected_transcript = self.transcripts[i] - expected_normalized_transcript = self.normalized_transcripts[i] + expected_transcript = self._transcripts[i] + expected_normalized_transcript = self._normalized_transcript[i] expected_data = self.data[i] self.assertEqual(expected_data, waveform, atol=5e-5, rtol=1e-8) assert sample_rate == sample_rate diff --git a/test/torchaudio_unittest/datasets/speechcommands_test.py b/test/torchaudio_unittest/datasets/speechcommands_test.py index 6351d41b27..19a352ee16 100644 --- a/test/torchaudio_unittest/datasets/speechcommands_test.py +++ b/test/torchaudio_unittest/datasets/speechcommands_test.py @@ -1,8 +1,6 @@ import os from pathlib import Path -from torchaudio.datasets import speechcommands - from torchaudio_unittest.common_utils import ( TempDirMixin, TorchaudioTestCase, @@ -11,7 +9,9 @@ save_wav, ) -LABELS = [ +from torchaudio.datasets import speechcommands + +_LABELS = [ "bed", "bird", "cat", @@ -49,6 +49,58 @@ ] +def get_mock_dataset(dataset_dir): + """ + dataset_dir: directory to the mocked dataset + """ + mocked_samples = [] + mocked_train_samples = [] + mocked_valid_samples = [] + mocked_test_samples = [] + os.makedirs(dataset_dir, exist_ok=True) + sample_rate = 16000 # 16kHz sample rate + seed = 0 + valid_file = os.path.join(dataset_dir, "validation_list.txt") + test_file = os.path.join(dataset_dir, "testing_list.txt") + with open(valid_file, "w") as valid, open(test_file, "w") as test: + for label in _LABELS: + path = os.path.join(dataset_dir, label) + os.makedirs(path, exist_ok=True) + for j in range(6): + # generate hash ID for speaker + speaker = "{:08x}".format(j) + + for utterance in range(3): + filename = f"{speaker}{speechcommands.HASH_DIVIDER}{utterance}.wav" + file_path = os.path.join(path, filename) + seed += 1 + data = get_whitenoise( + sample_rate=sample_rate, + duration=0.01, + n_channels=1, + dtype="int16", + seed=seed, + ) + save_wav(file_path, data, sample_rate) + sample = ( + normalize_wav(data), + sample_rate, + label, + speaker, + utterance, + ) + mocked_samples.append(sample) + if j < 2: + mocked_train_samples.append(sample) + elif j < 4: + valid.write(f'{label}/{filename}\n') + mocked_valid_samples.append(sample) + elif j < 6: + test.write(f'{label}/{filename}\n') + mocked_test_samples.append(sample) + return mocked_samples, mocked_train_samples, mocked_valid_samples, mocked_test_samples + + class TestSpeechCommands(TempDirMixin, TorchaudioTestCase): backend = "default" @@ -64,52 +116,12 @@ def setUpClass(cls): dataset_dir = os.path.join( cls.root_dir, speechcommands.FOLDER_IN_ARCHIVE, speechcommands.URL ) - os.makedirs(dataset_dir, exist_ok=True) - sample_rate = 16000 # 16kHz sample rate - seed = 0 - valid_file = os.path.join(dataset_dir, "validation_list.txt") - test_file = os.path.join(dataset_dir, "testing_list.txt") - with open(valid_file, "w") as valid, open(test_file, "w") as test: - for label in LABELS: - path = os.path.join(dataset_dir, label) - os.makedirs(path, exist_ok=True) - for j in range(6): - # generate hash ID for speaker - speaker = "{:08x}".format(j) - - for utterance in range(3): - filename = f"{speaker}{speechcommands.HASH_DIVIDER}{utterance}.wav" - file_path = os.path.join(path, filename) - seed += 1 - data = get_whitenoise( - sample_rate=sample_rate, - duration=0.01, - n_channels=1, - dtype="int16", - seed=seed, - ) - save_wav(file_path, data, sample_rate) - sample = ( - normalize_wav(data), - sample_rate, - label, - speaker, - utterance, - ) - cls.samples.append(sample) - if j < 2: - cls.train_samples.append(sample) - elif j < 4: - valid.write(f'{label}/{filename}\n') - cls.valid_samples.append(sample) - elif j < 6: - test.write(f'{label}/{filename}\n') - cls.test_samples.append(sample) + cls.samples, cls.train_samples, cls.valid_samples, cls.test_samples = get_mock_dataset(dataset_dir) def _testSpeechCommands(self, dataset, data_samples): num_samples = 0 for i, (data, sample_rate, label, speaker_id, utterance_number) in enumerate( - dataset + dataset ): self.assertEqual(data, data_samples[i][0], atol=5e-5, rtol=1e-8) assert sample_rate == data_samples[i][1] diff --git a/test/torchaudio_unittest/datasets/tedlium_test.py b/test/torchaudio_unittest/datasets/tedlium_test.py index 3ea4d25eab..abb6ea5b5c 100644 --- a/test/torchaudio_unittest/datasets/tedlium_test.py +++ b/test/torchaudio_unittest/datasets/tedlium_test.py @@ -1,21 +1,18 @@ import os import platform -import unittest from pathlib import Path -from torchaudio.datasets import tedlium - from torchaudio_unittest.common_utils import ( - TestBaseMixin, TempDirMixin, TorchaudioTestCase, get_whitenoise, save_wav, - normalize_wav, ) +from torchaudio.datasets import tedlium + # Used to generate a unique utterance for each dummy audio file -UTTERANCES = [ +_UTTERANCES = [ "AaronHuey_2010X 1 AaronHuey_2010X 0.0 2.0 script1\n", "AaronHuey_2010X 1 AaronHuey_2010X 2.0 4.0 script2\n", "AaronHuey_2010X 1 AaronHuey_2010X 4.0 6.0 script3\n", @@ -23,7 +20,7 @@ "AaronHuey_2010X 1 AaronHuey_2010X 8.0 10.0 script5\n", ] -PHONEME = [ +_PHONEME = [ "a AH", "a(2) EY", "aachen AA K AH N", @@ -34,6 +31,65 @@ ] +def get_mock_dataset(dataset_dir): + """ + dataset_dir: directory of the mocked dataset + """ + mocked_samples = {} + os.makedirs(dataset_dir, exist_ok=True) + sample_rate = 16000 # 16kHz + seed = 0 + + for release in ["release1", "release2", "release3"]: + data = get_whitenoise(sample_rate=sample_rate, duration=10.00, n_channels=1, dtype="float32", seed=seed) + if release in ["release1", "release2"]: + release_dir = os.path.join( + dataset_dir, + tedlium._RELEASE_CONFIGS[release]["folder_in_archive"], + tedlium._RELEASE_CONFIGS[release]["subset"], + ) + else: + release_dir = os.path.join( + dataset_dir, + tedlium._RELEASE_CONFIGS[release]["folder_in_archive"], + tedlium._RELEASE_CONFIGS[release]["data_path"], + ) + os.makedirs(release_dir, exist_ok=True) + os.makedirs(os.path.join(release_dir, "stm"), exist_ok=True) # Subfolder for transcripts + os.makedirs(os.path.join(release_dir, "sph"), exist_ok=True) # Subfolder for audio files + filename = f"{release}.sph" + path = os.path.join(os.path.join(release_dir, "sph"), filename) + save_wav(path, data, sample_rate) + + trans_filename = f"{release}.stm" + trans_path = os.path.join(os.path.join(release_dir, "stm"), trans_filename) + with open(trans_path, "w") as f: + f.write("".join(_UTTERANCES)) + + dict_filename = f"{release}.dic" + dict_path = os.path.join(release_dir, dict_filename) + with open(dict_path, "w") as f: + f.write("\n".join(_PHONEME)) + + # Create a samples list to compare with + mocked_samples[release] = [] + for utterance in _UTTERANCES: + talk_id, _, speaker_id, start_time, end_time, identifier, transcript = utterance.split(" ", 6) + start_time = int(float(start_time)) * sample_rate + end_time = int(float(end_time)) * sample_rate + sample = ( + data[:, start_time:end_time], + sample_rate, + transcript, + talk_id, + speaker_id, + identifier, + ) + mocked_samples[release].append(sample) + seed += 1 + return mocked_samples + + class Tedlium(TempDirMixin): root_dir = None samples = {} @@ -42,57 +98,7 @@ class Tedlium(TempDirMixin): def setUpClass(cls): cls.root_dir = cls.get_base_temp_dir() cls.root_dir = dataset_dir = os.path.join(cls.root_dir, "tedlium") - os.makedirs(dataset_dir, exist_ok=True) - sample_rate = 16000 # 16kHz - seed = 0 - - for release in ["release1", "release2", "release3"]: - data = get_whitenoise(sample_rate=sample_rate, duration=10.00, n_channels=1, dtype="float32", seed=seed) - if release in ["release1", "release2"]: - release_dir = os.path.join( - dataset_dir, - tedlium._RELEASE_CONFIGS[release]["folder_in_archive"], - tedlium._RELEASE_CONFIGS[release]["subset"], - ) - else: - release_dir = os.path.join( - dataset_dir, - tedlium._RELEASE_CONFIGS[release]["folder_in_archive"], - tedlium._RELEASE_CONFIGS[release]["data_path"], - ) - os.makedirs(release_dir, exist_ok=True) - os.makedirs(os.path.join(release_dir, "stm"), exist_ok=True) # Subfolder for transcripts - os.makedirs(os.path.join(release_dir, "sph"), exist_ok=True) # Subfolder for audio files - filename = f"{release}.sph" - path = os.path.join(os.path.join(release_dir, "sph"), filename) - save_wav(path, data, sample_rate) - - trans_filename = f"{release}.stm" - trans_path = os.path.join(os.path.join(release_dir, "stm"), trans_filename) - with open(trans_path, "w") as f: - f.write("".join(UTTERANCES)) - - dict_filename = f"{release}.dic" - dict_path = os.path.join(release_dir, dict_filename) - with open(dict_path, "w") as f: - f.write("\n".join(PHONEME)) - - # Create a samples list to compare with - cls.samples[release] = [] - for utterance in UTTERANCES: - talk_id, _, speaker_id, start_time, end_time, identifier, transcript = utterance.split(" ", 6) - start_time = int(float(start_time)) * sample_rate - end_time = int(float(end_time)) * sample_rate - sample = ( - data[:, start_time:end_time], - sample_rate, - transcript, - talk_id, - speaker_id, - identifier, - ) - cls.samples[release].append(sample) - seed += 1 + cls.samples = get_mock_dataset(dataset_dir) def _test_tedlium(self, dataset, release): num_samples = 0 @@ -110,7 +116,7 @@ def _test_tedlium(self, dataset, release): dataset._dict_path = os.path.join(dataset._path, f"{release}.dic") phoneme_dict = dataset.phoneme_dict phoenemes = [f"{key} {' '.join(value)}" for key, value in phoneme_dict.items()] - assert phoenemes == PHONEME + assert phoenemes == _PHONEME def test_tedlium_release1_str(self): release = "release1" diff --git a/test/torchaudio_unittest/datasets/utils_test.py b/test/torchaudio_unittest/datasets/utils_test.py index 5263319e51..8906991434 100644 --- a/test/torchaudio_unittest/datasets/utils_test.py +++ b/test/torchaudio_unittest/datasets/utils_test.py @@ -1,68 +1,37 @@ -import os -from pathlib import Path - -from torchaudio.datasets import utils as dataset_utils -from torchaudio.datasets.commonvoice import COMMONVOICE - +import torch from torchaudio_unittest.common_utils import ( - TempDirMixin, TorchaudioTestCase, - get_asset_path, + TempDirMixin ) +from torchaudio.datasets import utils as dataset_utils -class TestWalkFiles(TempDirMixin, TorchaudioTestCase): - root = None - expected = None - - def _add_file(self, *parts): - path = self.get_temp_path(*parts) - self.expected.append(path) - Path(path).touch() - - def setUp(self): - self.root = self.get_temp_path() - self.expected = [] - - # level 1 - for filename in ['a.txt', 'b.txt', 'c.txt']: - self._add_file(filename) - # level 2 - for dir1 in ['d1', 'd2', 'd3']: - for filename in ['d.txt', 'e.txt', 'f.txt']: - self._add_file(dir1, filename) - # level 3 - for dir2 in ['d1', 'd2', 'd3']: - for filename in ['g.txt', 'h.txt', 'i.txt']: - self._add_file(dir1, dir2, filename) +class Dataset(torch.utils.data.Dataset): + def __getitem__(self, n): + sample_rate = 8000 + waveform = n * torch.ones(2, 256) + return waveform, sample_rate - print('\n'.join(self.expected)) + def __len__(self) -> int: + return 2 - def test_walk_files(self): - """walk_files should traverse files in alphabetical order""" - n_ites = 0 - for i, path in enumerate(dataset_utils.walk_files(self.root, '.txt', prefix=True)): - found = os.path.join(self.root, path) - assert found == self.expected[i] - n_ites += 1 - assert n_ites == len(self.expected) + def __iter__(self): + for i in range(len(self)): + yield self[i] -class TestIterator(TorchaudioTestCase): +class TestIterator(TorchaudioTestCase, TempDirMixin): backend = 'default' - path = get_asset_path('CommonVoice', 'cv-corpus-4-2019-12-10', 'tt') def test_disckcache_iterator(self): - data = COMMONVOICE(self.path, url="tatar") - data = dataset_utils.diskcache_iterator(data) + data = dataset_utils.diskcache_iterator(Dataset(), self.get_base_temp_dir()) # Save data[0] # Load data[0] def test_bg_iterator(self): - data = COMMONVOICE(self.path, url="tatar") - data = dataset_utils.bg_iterator(data, 5) + data = dataset_utils.bg_iterator(Dataset(), 5) for _ in data: pass diff --git a/test/torchaudio_unittest/datasets/vctk_test.py b/test/torchaudio_unittest/datasets/vctk_test.py index 76bbf29936..03a797daeb 100644 --- a/test/torchaudio_unittest/datasets/vctk_test.py +++ b/test/torchaudio_unittest/datasets/vctk_test.py @@ -12,7 +12,7 @@ ) # Used to generate a unique utterance for each dummy audio file -UTTERANCE = [ +_UTTERANCE = [ 'Please call Stella', 'Ask her to bring these things', 'with her from the store', @@ -27,6 +27,54 @@ ] +def get_mock_dataset(root_dir): + """ + root_dir: root directory of the mocked data + """ + mocked_samples = [] + dataset_dir = os.path.join(root_dir, 'VCTK-Corpus-0.92') + os.makedirs(dataset_dir, exist_ok=True) + sample_rate = 48000 + seed = 0 + + for speaker in range(225, 230): + speaker_id = 'p' + str(speaker) + audio_dir = os.path.join(dataset_dir, 'wav48_silence_trimmed', speaker_id) + os.makedirs(audio_dir, exist_ok=True) + + file_dir = os.path.join(dataset_dir, 'txt', speaker_id) + os.makedirs(file_dir, exist_ok=True) + + for utterance_id in range(1, 11): + filename = f'{speaker_id}_{utterance_id:03d}_mic2' + audio_file_path = os.path.join(audio_dir, filename + '.wav') + + data = get_whitenoise( + sample_rate=sample_rate, + duration=0.01, + n_channels=1, + dtype='float32', + seed=seed + ) + save_wav(audio_file_path, data, sample_rate) + + txt_file_path = os.path.join(file_dir, filename[:-5] + '.txt') + utterance = _UTTERANCE[utterance_id - 1] + with open(txt_file_path, 'w') as f: + f.write(utterance) + + sample = ( + normalize_wav(data), + sample_rate, + utterance, + speaker_id, + utterance_id + ) + mocked_samples.append(sample) + seed += 1 + return mocked_samples + + class TestVCTK(TempDirMixin, TorchaudioTestCase): backend = 'default' @@ -36,47 +84,7 @@ class TestVCTK(TempDirMixin, TorchaudioTestCase): @classmethod def setUpClass(cls): cls.root_dir = cls.get_base_temp_dir() - dataset_dir = os.path.join(cls.root_dir, 'VCTK-Corpus-0.92') - os.makedirs(dataset_dir, exist_ok=True) - sample_rate = 48000 - seed = 0 - - for speaker in range(225, 230): - speaker_id = 'p' + str(speaker) - audio_dir = os.path.join(dataset_dir, 'wav48_silence_trimmed', speaker_id) - os.makedirs(audio_dir, exist_ok=True) - - file_dir = os.path.join(dataset_dir, 'txt', speaker_id) - os.makedirs(file_dir, exist_ok=True) - - for utterance_id in range(1, 11): - filename = f'{speaker_id}_{utterance_id:03d}_mic2' - audio_file_path = os.path.join(audio_dir, filename + '.wav') - - data = get_whitenoise( - sample_rate=sample_rate, - duration=0.01, - n_channels=1, - dtype='float32', - seed=seed - ) - save_wav(audio_file_path, data, sample_rate) - - txt_file_path = os.path.join(file_dir, filename[:-5] + '.txt') - utterance = UTTERANCE[utterance_id - 1] - with open(txt_file_path, 'w') as f: - f.write(utterance) - - sample = ( - normalize_wav(data), - sample_rate, - utterance, - speaker_id, - utterance_id - ) - cls.samples.append(sample) - - seed += 1 + cls.samples = get_mock_dataset(cls.root_dir) def _test_vctk(self, dataset): num_samples = 0 diff --git a/test/torchaudio_unittest/datasets/yesno_test.py b/test/torchaudio_unittest/datasets/yesno_test.py index 6b094aaece..2f4144985d 100644 --- a/test/torchaudio_unittest/datasets/yesno_test.py +++ b/test/torchaudio_unittest/datasets/yesno_test.py @@ -12,6 +12,23 @@ ) +def get_mock_data(root_dir, labels): + """ + root_dir: path + labels: list of labels + """ + mocked_data = [] + base_dir = os.path.join(root_dir, 'waves_yesno') + os.makedirs(base_dir, exist_ok=True) + for i, label in enumerate(labels): + filename = f'{"_".join(str(l) for l in label)}.wav' + path = os.path.join(base_dir, filename) + data = get_whitenoise(sample_rate=8000, duration=6, n_channels=1, dtype='int16', seed=i) + save_wav(path, data, 8000) + mocked_data.append(normalize_wav(data)) + return mocked_data + + class TestYesNo(TempDirMixin, TorchaudioTestCase): backend = 'default' @@ -28,14 +45,7 @@ class TestYesNo(TempDirMixin, TorchaudioTestCase): @classmethod def setUpClass(cls): cls.root_dir = cls.get_base_temp_dir() - base_dir = os.path.join(cls.root_dir, 'waves_yesno') - os.makedirs(base_dir, exist_ok=True) - for i, label in enumerate(cls.labels): - filename = f'{"_".join(str(l) for l in label)}.wav' - path = os.path.join(base_dir, filename) - data = get_whitenoise(sample_rate=8000, duration=6, n_channels=1, dtype='int16', seed=i) - save_wav(path, data, 8000) - cls.data.append(normalize_wav(data)) + cls.data = get_mock_data(cls.root_dir, cls.labels) def _test_yesno(self, dataset): n_ite = 0 diff --git a/test/torchaudio_unittest/functional/functional_cpu_test.py b/test/torchaudio_unittest/functional/functional_cpu_test.py index 4fbe4d871e..4073654011 100644 --- a/test/torchaudio_unittest/functional/functional_cpu_test.py +++ b/test/torchaudio_unittest/functional/functional_cpu_test.py @@ -1,14 +1,14 @@ import math -import unittest import torch import torchaudio import torchaudio.functional as F from parameterized import parameterized import pytest +import itertools from torchaudio_unittest import common_utils -from .functional_impl import Lfilter +from .functional_impl import Lfilter, Spectrogram class TestLFilterFloat32(Lfilter, common_utils.PytorchTestCase): @@ -21,6 +21,16 @@ class TestLFilterFloat64(Lfilter, common_utils.PytorchTestCase): device = torch.device('cpu') +class TestSpectrogramFloat32(Spectrogram, common_utils.PytorchTestCase): + dtype = torch.float32 + device = torch.device('cpu') + + +class TestSpectrogramFloat64(Spectrogram, common_utils.PytorchTestCase): + dtype = torch.float64 + device = torch.device('cpu') + + class TestCreateFBMatrix(common_utils.TorchaudioTestCase): def test_no_warning_high_n_freq(self): with pytest.warns(None) as w: @@ -44,7 +54,7 @@ def test_one_channel(self): specgram = torch.tensor([[[1.0, 2.0, 3.0, 4.0]]]) expected = torch.tensor([[[0.5, 1.0, 1.0, 0.5]]]) computed = F.compute_deltas(specgram, win_length=3) - torch.testing.assert_allclose(computed, expected) + self.assertEqual(computed, expected) def test_two_channels(self): specgram = torch.tensor([[[1.0, 2.0, 3.0, 4.0], @@ -52,7 +62,7 @@ def test_two_channels(self): expected = torch.tensor([[[0.5, 1.0, 1.0, 0.5], [0.5, 1.0, 1.0, 0.5]]]) computed = F.compute_deltas(specgram, win_length=3) - torch.testing.assert_allclose(computed, expected) + self.assertEqual(computed, expected) class TestDetectPitchFrequency(common_utils.TorchaudioTestCase): @@ -88,13 +98,13 @@ def test_DB_to_amplitude(self): db = F.amplitude_to_DB(torch.abs(x), multiplier, amin, db_multiplier, top_db=None) x2 = F.DB_to_amplitude(db, ref, power) - torch.testing.assert_allclose(x2, torch.abs(x), atol=5e-5, rtol=1e-5) + self.assertEqual(x2, torch.abs(x), atol=5e-5, rtol=1e-5) # Spectrogram amplitude -> DB -> amplitude db = F.amplitude_to_DB(spec, multiplier, amin, db_multiplier, top_db=None) x2 = F.DB_to_amplitude(db, ref, power) - torch.testing.assert_allclose(x2, spec, atol=5e-5, rtol=1e-5) + self.assertEqual(x2, spec, atol=5e-5, rtol=1e-5) # Waveform power -> DB -> power multiplier = 10. @@ -103,61 +113,66 @@ def test_DB_to_amplitude(self): db = F.amplitude_to_DB(x, multiplier, amin, db_multiplier, top_db=None) x2 = F.DB_to_amplitude(db, ref, power) - torch.testing.assert_allclose(x2, torch.abs(x), atol=5e-5, rtol=1e-5) + self.assertEqual(x2, torch.abs(x), atol=5e-5, rtol=1e-5) # Spectrogram power -> DB -> power db = F.amplitude_to_DB(spec, multiplier, amin, db_multiplier, top_db=None) x2 = F.DB_to_amplitude(db, ref, power) - torch.testing.assert_allclose(x2, spec, atol=5e-5, rtol=1e-5) - - -@pytest.mark.parametrize('complex_tensor', [ - torch.randn(1, 2, 1025, 400, 2), - torch.randn(1025, 400, 2) -]) -@pytest.mark.parametrize('power', [1, 2, 0.7]) -def test_complex_norm(complex_tensor, power): - expected_norm_tensor = complex_tensor.pow(2).sum(-1).pow(power / 2) - norm_tensor = F.complex_norm(complex_tensor, power) + self.assertEqual(x2, spec, atol=5e-5, rtol=1e-5) - torch.testing.assert_allclose(norm_tensor, expected_norm_tensor, atol=1e-5, rtol=1e-5) +class TestComplexNorm(common_utils.TorchaudioTestCase): + @parameterized.expand(list(itertools.product( + [(1, 2, 1025, 400, 2), (1025, 400, 2)], + [1, 2, 0.7] + ))) + def test_complex_norm(self, shape, power): + torch.random.manual_seed(42) + complex_tensor = torch.randn(*shape) + expected_norm_tensor = complex_tensor.pow(2).sum(-1).pow(power / 2) + norm_tensor = F.complex_norm(complex_tensor, power) + self.assertEqual(norm_tensor, expected_norm_tensor, atol=1e-5, rtol=1e-5) -@pytest.mark.parametrize('specgram', [ - torch.randn(2, 1025, 400), - torch.randn(1, 201, 100) -]) -@pytest.mark.parametrize('mask_param', [100]) -@pytest.mark.parametrize('mask_value', [0., 30.]) -@pytest.mark.parametrize('axis', [1, 2]) -def test_mask_along_axis(specgram, mask_param, mask_value, axis): - mask_specgram = F.mask_along_axis(specgram, mask_param, mask_value, axis) +class TestMaskAlongAxis(common_utils.TorchaudioTestCase): + @parameterized.expand(list(itertools.product( + [(2, 1025, 400), (1, 201, 100)], + [100], + [0., 30.], + [1, 2] + ))) + def test_mask_along_axis(self, shape, mask_param, mask_value, axis): + torch.random.manual_seed(42) + specgram = torch.randn(*shape) + mask_specgram = F.mask_along_axis(specgram, mask_param, mask_value, axis) - other_axis = 1 if axis == 2 else 2 + other_axis = 1 if axis == 2 else 2 - masked_columns = (mask_specgram == mask_value).sum(other_axis) - num_masked_columns = (masked_columns == mask_specgram.size(other_axis)).sum() - num_masked_columns //= mask_specgram.size(0) + masked_columns = (mask_specgram == mask_value).sum(other_axis) + num_masked_columns = (masked_columns == mask_specgram.size(other_axis)).sum() + num_masked_columns //= mask_specgram.size(0) - assert mask_specgram.size() == specgram.size() - assert num_masked_columns < mask_param + assert mask_specgram.size() == specgram.size() + assert num_masked_columns < mask_param -@pytest.mark.parametrize('mask_param', [100]) -@pytest.mark.parametrize('mask_value', [0., 30.]) -@pytest.mark.parametrize('axis', [2, 3]) -def test_mask_along_axis_iid(mask_param, mask_value, axis): - torch.random.manual_seed(42) - specgrams = torch.randn(4, 2, 1025, 400) +class TestMaskAlongAxisIID(common_utils.TorchaudioTestCase): + @parameterized.expand(list(itertools.product( + [100], + [0., 30.], + [2, 3] + ))) + def test_mask_along_axis_iid(self, mask_param, mask_value, axis): + torch.random.manual_seed(42) + specgrams = torch.randn(4, 2, 1025, 400) - mask_specgrams = F.mask_along_axis_iid(specgrams, mask_param, mask_value, axis) + mask_specgrams = F.mask_along_axis_iid(specgrams, mask_param, mask_value, axis) - other_axis = 2 if axis == 3 else 3 + other_axis = 2 if axis == 3 else 3 - masked_columns = (mask_specgrams == mask_value).sum(other_axis) - num_masked_columns = (masked_columns == mask_specgrams.size(other_axis)).sum(-1) + masked_columns = (mask_specgrams == mask_value).sum(other_axis) + num_masked_columns = (masked_columns == mask_specgrams.size(other_axis)).sum(-1) - assert mask_specgrams.size() == specgrams.size() - assert (num_masked_columns < mask_param).sum() == num_masked_columns.numel() + assert mask_specgrams.size() == specgrams.size() + assert (num_masked_columns < mask_param).sum() == num_masked_columns.numel() diff --git a/test/torchaudio_unittest/functional/functional_cuda_test.py b/test/torchaudio_unittest/functional/functional_cuda_test.py index 80ac5fa0c2..c89795be01 100644 --- a/test/torchaudio_unittest/functional/functional_cuda_test.py +++ b/test/torchaudio_unittest/functional/functional_cuda_test.py @@ -1,7 +1,7 @@ import torch from torchaudio_unittest import common_utils -from .functional_impl import Lfilter +from .functional_impl import Lfilter, Spectrogram @common_utils.skipIfNoCuda @@ -14,3 +14,15 @@ class TestLFilterFloat32(Lfilter, common_utils.PytorchTestCase): class TestLFilterFloat64(Lfilter, common_utils.PytorchTestCase): dtype = torch.float64 device = torch.device('cuda') + + +@common_utils.skipIfNoCuda +class TestSpectrogramFloat32(Spectrogram, common_utils.PytorchTestCase): + dtype = torch.float32 + device = torch.device('cuda') + + +@common_utils.skipIfNoCuda +class TestSpectrogramFloat64(Spectrogram, common_utils.PytorchTestCase): + dtype = torch.float64 + device = torch.device('cuda') diff --git a/test/torchaudio_unittest/functional/functional_impl.py b/test/torchaudio_unittest/functional/functional_impl.py index c63001a68e..1ba5e21fbb 100644 --- a/test/torchaudio_unittest/functional/functional_impl.py +++ b/test/torchaudio_unittest/functional/functional_impl.py @@ -1,6 +1,7 @@ """Test defintion common to CPU and CUDA""" import torch import torchaudio.functional as F +from parameterized import parameterized from torchaudio_unittest import common_utils @@ -29,3 +30,25 @@ def test_clamp(self): assert output_signal.max() <= 1 output_signal = F.lfilter(input_signal, a_coeffs, b_coeffs, clamp=False) assert output_signal.max() > 1 + + +class Spectrogram(common_utils.TestBaseMixin): + @parameterized.expand([(0., ), (1., ), (2., ), (3., )]) + def test_grad_at_zero(self, power): + """The gradient of power spectrogram should not be nan but zero near x=0 + + https://github.com/pytorch/audio/issues/993 + """ + x = torch.zeros(1, 22050, requires_grad=True) + spec = F.spectrogram( + x, + pad=0, + window=None, + n_fft=2048, + hop_length=None, + win_length=None, + power=power, + normalized=False, + ) + spec.sum().backward() + assert not x.grad.isnan().sum() diff --git a/test/torchaudio_unittest/kaldi_compatibility_impl.py b/test/torchaudio_unittest/kaldi_compatibility_impl.py index bae01203f1..983805fff5 100644 --- a/test/torchaudio_unittest/kaldi_compatibility_impl.py +++ b/test/torchaudio_unittest/kaldi_compatibility_impl.py @@ -28,7 +28,7 @@ def _convert_args(**kwargs): def _run_kaldi(command, input_type, input_value): """Run provided Kaldi command, pass a tensor and get the resulting tensor - Arguments: + Args: input_type: str 'ark' or 'scp' input_value: diff --git a/test/torchaudio_unittest/librosa_compatibility_test.py b/test/torchaudio_unittest/librosa_compatibility_test.py index f779f36dae..e1ef80fa79 100644 --- a/test/torchaudio_unittest/librosa_compatibility_test.py +++ b/test/torchaudio_unittest/librosa_compatibility_test.py @@ -7,6 +7,8 @@ import torchaudio import torchaudio.functional as F from torchaudio._internal.module_utils import is_module_available +from parameterized import parameterized +import itertools LIBROSA_AVAILABLE = is_module_available('librosa') @@ -111,42 +113,49 @@ def test_amplitude_to_DB(self): self.assertEqual(ta_out, lr_out, atol=5e-5, rtol=1e-5) -@pytest.mark.parametrize('complex_specgrams', [ - torch.randn(2, 1025, 400, 2) -]) -@pytest.mark.parametrize('rate', [0.5, 1.01, 1.3]) -@pytest.mark.parametrize('hop_length', [256]) @unittest.skipIf(not LIBROSA_AVAILABLE, "Librosa not available") -def test_phase_vocoder(complex_specgrams, rate, hop_length): - # Due to cummulative sum, numerical error in using torch.float32 will - # result in bottom right values of the stretched sectrogram to not - # match with librosa. - - complex_specgrams = complex_specgrams.type(torch.float64) - phase_advance = torch.linspace(0, np.pi * hop_length, complex_specgrams.shape[-3], dtype=torch.float64)[..., None] - - complex_specgrams_stretch = F.phase_vocoder(complex_specgrams, rate=rate, phase_advance=phase_advance) - - # == Test shape - expected_size = list(complex_specgrams.size()) - expected_size[-2] = int(np.ceil(expected_size[-2] / rate)) - - assert complex_specgrams.dim() == complex_specgrams_stretch.dim() - assert complex_specgrams_stretch.size() == torch.Size(expected_size) - - # == Test values - index = [0] * (complex_specgrams.dim() - 3) + [slice(None)] * 3 - mono_complex_specgram = complex_specgrams[index].numpy() - mono_complex_specgram = mono_complex_specgram[..., 0] + \ - mono_complex_specgram[..., 1] * 1j - expected_complex_stretch = librosa.phase_vocoder(mono_complex_specgram, - rate=rate, - hop_length=hop_length) - - complex_stretch = complex_specgrams_stretch[index].numpy() - complex_stretch = complex_stretch[..., 0] + 1j * complex_stretch[..., 1] - - assert np.allclose(complex_stretch, expected_complex_stretch, atol=1e-5) +class TestPhaseVocoder(common_utils.TorchaudioTestCase): + @parameterized.expand(list(itertools.product( + [(2, 1025, 400, 2)], + [0.5, 1.01, 1.3], + [256] + ))) + def test_phase_vocoder(self, shape, rate, hop_length): + # Due to cummulative sum, numerical error in using torch.float32 will + # result in bottom right values of the stretched sectrogram to not + # match with librosa. + torch.random.manual_seed(42) + complex_specgrams = torch.randn(*shape) + complex_specgrams = complex_specgrams.type(torch.float64) + phase_advance = torch.linspace( + 0, + np.pi * hop_length, + complex_specgrams.shape[-3], + dtype=torch.float64)[..., None] + + complex_specgrams_stretch = F.phase_vocoder(complex_specgrams, rate=rate, phase_advance=phase_advance) + + # == Test shape + expected_size = list(complex_specgrams.size()) + expected_size[-2] = int(np.ceil(expected_size[-2] / rate)) + + assert complex_specgrams.dim() == complex_specgrams_stretch.dim() + assert complex_specgrams_stretch.size() == torch.Size(expected_size) + + # == Test values + index = [0] * (complex_specgrams.dim() - 3) + [slice(None)] * 3 + mono_complex_specgram = complex_specgrams[index].numpy() + mono_complex_specgram = mono_complex_specgram[..., 0] + \ + mono_complex_specgram[..., 1] * 1j + expected_complex_stretch = librosa.phase_vocoder( + mono_complex_specgram, + rate=rate, + hop_length=hop_length) + + complex_stretch = complex_specgrams_stretch[index].numpy() + complex_stretch = complex_stretch[..., 0] + 1j * complex_stretch[..., 1] + + self.assertEqual(complex_stretch, torch.from_numpy(expected_complex_stretch), atol=1e-5, rtol=1e-5) def _load_audio_asset(*asset_paths, **kwargs): diff --git a/test/torchaudio_unittest/soundfile_backend/load_test.py b/test/torchaudio_unittest/soundfile_backend/load_test.py index 4277ac03e9..399266de8f 100644 --- a/test/torchaudio_unittest/soundfile_backend/load_test.py +++ b/test/torchaudio_unittest/soundfile_backend/load_test.py @@ -1,4 +1,5 @@ import os +import tarfile from unittest.mock import patch import torch @@ -299,3 +300,58 @@ def test_wav(self, format_): @skipIfFormatNotSupported("FLAC") def test_flac(self, format_): self._test_format(format_) + + +@skipIfNoModule("soundfile") +class TestFileObject(TempDirMixin, PytorchTestCase): + def _test_fileobj(self, ext): + """Loading audio via file-like object works""" + sample_rate = 16000 + path = self.get_temp_path(f'test.{ext}') + + data = get_wav_data('float32', num_channels=2).numpy().T + soundfile.write(path, data, sample_rate) + expected = soundfile.read(path, dtype='float32')[0].T + + with open(path, 'rb') as fileobj: + found, sr = soundfile_backend.load(fileobj) + assert sr == sample_rate + self.assertEqual(expected, found) + + def test_fileobj_wav(self): + """Loading audio via file-like object works""" + self._test_fileobj('wav') + + @skipIfFormatNotSupported("FLAC") + def test_fileobj_flac(self): + """Loading audio via file-like object works""" + self._test_fileobj('flac') + + def _test_tarfile(self, ext): + """Loading audio via file-like object works""" + sample_rate = 16000 + audio_file = f'test.{ext}' + audio_path = self.get_temp_path(audio_file) + archive_path = self.get_temp_path('archive.tar.gz') + + data = get_wav_data('float32', num_channels=2).numpy().T + soundfile.write(audio_path, data, sample_rate) + expected = soundfile.read(audio_path, dtype='float32')[0].T + + with tarfile.TarFile(archive_path, 'w') as tarobj: + tarobj.add(audio_path, arcname=audio_file) + with tarfile.TarFile(archive_path, 'r') as tarobj: + fileobj = tarobj.extractfile(audio_file) + found, sr = soundfile_backend.load(fileobj) + + assert sr == sample_rate + self.assertEqual(expected, found) + + def test_tarfile_wav(self): + """Loading audio via file-like object works""" + self._test_tarfile('wav') + + @skipIfFormatNotSupported("FLAC") + def test_tarfile_flac(self): + """Loading audio via file-like object works""" + self._test_tarfile('flac') diff --git a/test/torchaudio_unittest/sox_effect/sox_effect_test.py b/test/torchaudio_unittest/sox_effect/sox_effect_test.py index c5b57eaf5f..c25e376359 100644 --- a/test/torchaudio_unittest/sox_effect/sox_effect_test.py +++ b/test/torchaudio_unittest/sox_effect/sox_effect_test.py @@ -8,6 +8,7 @@ TempDirMixin, PytorchTestCase, skipIfNoExtension, + get_asset_path, get_sinusoid, get_wav_data, save_wav, @@ -243,3 +244,21 @@ def test_vorbis(self, sample_rate, num_channels): assert sr == expected_sr self.assertEqual(found, expected) + + +@skipIfNoExtension +class TestApplyEffectFileWithoutExtension(PytorchTestCase): + def test_mp3(self): + """Providing format allows to read mp3 without extension + + libsox does not check header for mp3 + + https://github.com/pytorch/audio/issues/1040 + + The file was generated with the following command + ffmpeg -f lavfi -i "sine=frequency=1000:duration=5" -ar 16000 -f mp3 test_noext + """ + effects = [['band', '300', '10']] + path = get_asset_path("mp3_without_ext") + _, sr = sox_effects.apply_effects_file(path, effects, format="mp3") + assert sr == 16000 diff --git a/test/torchaudio_unittest/sox_io_backend/info_test.py b/test/torchaudio_unittest/sox_io_backend/info_test.py index 9b928f3ae0..49fc797354 100644 --- a/test/torchaudio_unittest/sox_io_backend/info_test.py +++ b/test/torchaudio_unittest/sox_io_backend/info_test.py @@ -167,3 +167,20 @@ def test_opus(self, bitrate, num_channels, compression_level): assert info.sample_rate == 48000 assert info.num_frames == 32768 assert info.num_channels == num_channels + + +@skipIfNoExtension +class TestLoadWithoutExtension(PytorchTestCase): + def test_mp3(self): + """Providing `format` allows to read mp3 without extension + + libsox does not check header for mp3 + + https://github.com/pytorch/audio/issues/1040 + + The file was generated with the following command + ffmpeg -f lavfi -i "sine=frequency=1000:duration=5" -ar 16000 -f mp3 test_noext + """ + path = get_asset_path("mp3_without_ext") + sinfo = sox_io_backend.info(path, format="mp3") + assert sinfo.sample_rate == 16000 diff --git a/test/torchaudio_unittest/sox_io_backend/load_test.py b/test/torchaudio_unittest/sox_io_backend/load_test.py index 2b4e916861..3a4b0ba8fe 100644 --- a/test/torchaudio_unittest/sox_io_backend/load_test.py +++ b/test/torchaudio_unittest/sox_io_backend/load_test.py @@ -1,14 +1,18 @@ -import os +import io import itertools +import tarfile -from torchaudio.backend import sox_io_backend from parameterized import parameterized +from torchaudio.backend import sox_io_backend +from torchaudio._internal import module_utils as _mod_utils from torchaudio_unittest.common_utils import ( TempDirMixin, + HttpServerMixin, PytorchTestCase, skipIfNoExec, skipIfNoExtension, + skipIfNoModule, get_asset_path, get_wav_data, load_wav, @@ -20,6 +24,10 @@ ) +if _mod_utils.is_module_available("requests"): + import requests + + class LoadTestBase(TempDirMixin, PytorchTestCase): def assert_wav(self, dtype, sample_rate, num_channels, normalize, duration): """`sox_io_backend.load` can load wav format correctly. @@ -355,26 +363,171 @@ def test_channels_first(self, channels_first): self.assertEqual(found, expected) +@skipIfNoExtension +class TestLoadWithoutExtension(PytorchTestCase): + def test_mp3(self): + """Providing format allows to read mp3 without extension + + libsox does not check header for mp3 + + https://github.com/pytorch/audio/issues/1040 + + The file was generated with the following command + ffmpeg -f lavfi -i "sine=frequency=1000:duration=5" -ar 16000 -f mp3 test_noext + """ + path = get_asset_path("mp3_without_ext") + _, sr = sox_io_backend.load(path, format="mp3") + assert sr == 16000 + + +@skipIfNoExtension @skipIfNoExec('sox') +class TestFileObject(TempDirMixin, PytorchTestCase): + """ + In this test suite, the result of file-like object input is compared against file path input, + because `load` function is rigrously tested for file path inputs to match libsox's result, + """ + @parameterized.expand([ + ('wav', None), + ('mp3', 128), + ('mp3', 320), + ('flac', 0), + ('flac', 5), + ('flac', 8), + ('vorbis', -1), + ('vorbis', 10), + ('amb', None), + ]) + def test_fileobj(self, ext, compression): + """Loading audio via file object returns the same result as via file path.""" + sample_rate = 16000 + format_ = ext if ext in ['mp3'] else None + path = self.get_temp_path(f'test.{ext}') + + sox_utils.gen_audio_file( + path, sample_rate, num_channels=2, + compression=compression) + expected, _ = sox_io_backend.load(path) + + with open(path, 'rb') as fileobj: + found, sr = sox_io_backend.load(fileobj, format=format_) + + assert sr == sample_rate + self.assertEqual(expected, found) + + @parameterized.expand([ + ('wav', None), + ('mp3', 128), + ('mp3', 320), + ('flac', 0), + ('flac', 5), + ('flac', 8), + ('vorbis', -1), + ('vorbis', 10), + ('amb', None), + ]) + def test_bytesio(self, ext, compression): + """Loading audio via BytesIO object returns the same result as via file path.""" + sample_rate = 16000 + format_ = ext if ext in ['mp3'] else None + path = self.get_temp_path(f'test.{ext}') + + sox_utils.gen_audio_file( + path, sample_rate, num_channels=2, + compression=compression) + expected, _ = sox_io_backend.load(path) + + with open(path, 'rb') as file_: + fileobj = io.BytesIO(file_.read()) + found, sr = sox_io_backend.load(fileobj, format=format_) + + assert sr == sample_rate + self.assertEqual(expected, found) + + @parameterized.expand([ + ('wav', None), + ('mp3', 128), + ('mp3', 320), + ('flac', 0), + ('flac', 5), + ('flac', 8), + ('vorbis', -1), + ('vorbis', 10), + ('amb', None), + ]) + def test_tarfile(self, ext, compression): + """Loading compressed audio via file-like object returns the same result as via file path.""" + sample_rate = 16000 + format_ = ext if ext in ['mp3'] else None + audio_file = f'test.{ext}' + audio_path = self.get_temp_path(audio_file) + archive_path = self.get_temp_path('archive.tar.gz') + + sox_utils.gen_audio_file( + audio_path, sample_rate, num_channels=2, + compression=compression) + expected, _ = sox_io_backend.load(audio_path) + + with tarfile.TarFile(archive_path, 'w') as tarobj: + tarobj.add(audio_path, arcname=audio_file) + with tarfile.TarFile(archive_path, 'r') as tarobj: + fileobj = tarobj.extractfile(audio_file) + found, sr = sox_io_backend.load(fileobj, format=format_) + + assert sr == sample_rate + self.assertEqual(expected, found) + + @skipIfNoExtension -class TestLoadExtensionLess(TempDirMixin, PytorchTestCase): - """Given `format` parameter, `sox_io_backend.load` can load files without extension""" - original = None - path = None +@skipIfNoExec('sox') +@skipIfNoModule("requests") +class TestFileObjectHttp(HttpServerMixin, PytorchTestCase): + @parameterized.expand([ + ('wav', None), + ('mp3', 128), + ('mp3', 320), + ('flac', 0), + ('flac', 5), + ('flac', 8), + ('vorbis', -1), + ('vorbis', 10), + ('amb', None), + ]) + def test_requests(self, ext, compression): + sample_rate = 16000 + format_ = ext if ext in ['mp3'] else None + audio_file = f'test.{ext}' + audio_path = self.get_temp_path(audio_file) - def _make_file(self, format_): + sox_utils.gen_audio_file( + audio_path, sample_rate, num_channels=2, compression=compression) + expected, _ = sox_io_backend.load(audio_path) + + url = self.get_url(audio_file) + with requests.get(url, stream=True) as resp: + found, sr = sox_io_backend.load(resp.raw, format=format_) + + assert sr == sample_rate + self.assertEqual(expected, found) + + @parameterized.expand(list(itertools.product( + [0, 1, 10, 100, 1000], + [-1, 1, 10, 100, 1000], + )), name_func=name_func) + def test_frame(self, frame_offset, num_frames): + """num_frames and frame_offset correctly specify the region of data""" sample_rate = 8000 - path = self.get_temp_path(f'test.{format_}') - sox_utils.gen_audio_file(f'{path}', sample_rate, num_channels=2) - self.original = sox_io_backend.load(path)[0] - self.path = os.path.splitext(path)[0] - os.rename(path, self.path) + audio_file = 'test.wav' + audio_path = self.get_temp_path(audio_file) - @parameterized.expand([ - ('WAV', ), ('wav', ), ('MP3', ), ('mp3', ), ('FLAC', ), ('flac',), - ], name_func=name_func) - def test_format(self, format_): - """Providing format allows to read file without extension""" - self._make_file(format_) - found, _ = sox_io_backend.load(self.path) - self.assertEqual(found, self.original) + original = get_wav_data('float32', num_channels=2) + save_wav(audio_path, original, sample_rate) + frame_end = None if num_frames == -1 else frame_offset + num_frames + expected = original[:, frame_offset:frame_end] + + url = self.get_url(audio_file) + with requests.get(url, stream=True) as resp: + found, sr = sox_io_backend.load(resp.raw, frame_offset, num_frames) + + assert sr == sample_rate + self.assertEqual(expected, found) diff --git a/test/torchaudio_unittest/transducer_test.py b/test/torchaudio_unittest/transducer_test.py new file mode 100644 index 0000000000..3d8dc0683d --- /dev/null +++ b/test/torchaudio_unittest/transducer_test.py @@ -0,0 +1,276 @@ +import torch +from torchaudio.prototype.transducer import RNNTLoss + +from torchaudio_unittest import common_utils + + +def get_data_basic(device): + # Example provided + # in 6f73a2513dc784c59eec153a45f40bc528355b18 + # of https://github.com/HawkAaron/warp-transducer + + acts = torch.tensor( + [ + [ + [ + [0.1, 0.6, 0.1, 0.1, 0.1], + [0.1, 0.1, 0.6, 0.1, 0.1], + [0.1, 0.1, 0.2, 0.8, 0.1], + ], + [ + [0.1, 0.6, 0.1, 0.1, 0.1], + [0.1, 0.1, 0.2, 0.1, 0.1], + [0.7, 0.1, 0.2, 0.1, 0.1], + ], + ] + ], + dtype=torch.float, + ) + labels = torch.tensor([[1, 2]], dtype=torch.int) + act_length = torch.tensor([2], dtype=torch.int) + label_length = torch.tensor([2], dtype=torch.int) + + acts = acts.to(device) + labels = labels.to(device) + act_length = act_length.to(device) + label_length = label_length.to(device) + + acts.requires_grad_(True) + + return acts, labels, act_length, label_length + + +def get_data_B2_T4_U3_D3(dtype=torch.float32, device="cpu"): + # Test from D21322854 + + logits = torch.tensor( + [ + 0.065357, + 0.787530, + 0.081592, + 0.529716, + 0.750675, + 0.754135, + 0.609764, + 0.868140, + 0.622532, + 0.668522, + 0.858039, + 0.164539, + 0.989780, + 0.944298, + 0.603168, + 0.946783, + 0.666203, + 0.286882, + 0.094184, + 0.366674, + 0.736168, + 0.166680, + 0.714154, + 0.399400, + 0.535982, + 0.291821, + 0.612642, + 0.324241, + 0.800764, + 0.524106, + 0.779195, + 0.183314, + 0.113745, + 0.240222, + 0.339470, + 0.134160, + 0.505562, + 0.051597, + 0.640290, + 0.430733, + 0.829473, + 0.177467, + 0.320700, + 0.042883, + 0.302803, + 0.675178, + 0.569537, + 0.558474, + 0.083132, + 0.060165, + 0.107958, + 0.748615, + 0.943918, + 0.486356, + 0.418199, + 0.652408, + 0.024243, + 0.134582, + 0.366342, + 0.295830, + 0.923670, + 0.689929, + 0.741898, + 0.250005, + 0.603430, + 0.987289, + 0.592606, + 0.884672, + 0.543450, + 0.660770, + 0.377128, + 0.358021, + ], + dtype=dtype, + ).reshape(2, 4, 3, 3) + + targets = torch.tensor([[1, 2], [1, 1]], dtype=torch.int32) + src_lengths = torch.tensor([4, 4], dtype=torch.int32) + tgt_lengths = torch.tensor([2, 2], dtype=torch.int32) + + blank = 0 + + ref_costs = torch.tensor([4.2806528590890736, 3.9384369822503591], dtype=dtype) + + ref_gradients = torch.tensor( + [ + -0.186844, + -0.062555, + 0.249399, + -0.203377, + 0.202399, + 0.000977, + -0.141016, + 0.079123, + 0.061893, + -0.011552, + -0.081280, + 0.092832, + -0.154257, + 0.229433, + -0.075176, + -0.246593, + 0.146405, + 0.100188, + -0.012918, + -0.061593, + 0.074512, + -0.055986, + 0.219831, + -0.163845, + -0.497627, + 0.209240, + 0.288387, + 0.013605, + -0.030220, + 0.016615, + 0.113925, + 0.062781, + -0.176706, + -0.667078, + 0.367659, + 0.299419, + -0.356344, + -0.055347, + 0.411691, + -0.096922, + 0.029459, + 0.067463, + -0.063518, + 0.027654, + 0.035863, + -0.154499, + -0.073942, + 0.228441, + -0.166790, + -0.000088, + 0.166878, + -0.172370, + 0.105565, + 0.066804, + 0.023875, + -0.118256, + 0.094381, + -0.104707, + -0.108934, + 0.213642, + -0.369844, + 0.180118, + 0.189726, + 0.025714, + -0.079462, + 0.053748, + 0.122328, + -0.238789, + 0.116460, + -0.598687, + 0.302203, + 0.296484, + ], + dtype=dtype, + ).reshape(2, 4, 3, 3) + + logits.requires_grad_(True) + logits = logits.to(device) + + def grad_hook(grad): + logits.saved_grad = grad.clone() + + logits.register_hook(grad_hook) + + data = { + "logits": logits, + "targets": targets, + "src_lengths": src_lengths, + "tgt_lengths": tgt_lengths, + "blank": blank, + } + + return data, ref_costs, ref_gradients + + +def compute_with_pytorch_transducer(data): + costs = RNNTLoss(blank=data["blank"], reduction="none")( + acts=data["logits"], + labels=data["targets"], + act_lens=data["src_lengths"], + label_lens=data["tgt_lengths"], + ) + + loss = torch.sum(costs) + loss.backward() + costs = costs.cpu() + gradients = data["logits"].saved_grad.cpu() + return costs, gradients + + +class TransducerTester: + def test_basic_fp16_error(self): + rnnt_loss = RNNTLoss() + acts, labels, act_length, label_length = get_data_basic(self.device) + acts = acts.to(torch.float16) + # RuntimeError raised by log_softmax before reaching transducer's bindings + self.assertRaises( + RuntimeError, rnnt_loss, acts, labels, act_length, label_length + ) + + def test_basic_backward(self): + rnnt_loss = RNNTLoss() + acts, labels, act_length, label_length = get_data_basic(self.device) + loss = rnnt_loss(acts, labels, act_length, label_length) + loss.backward() + + def test_costs_and_gradients_B2_T4_U3_D3_fp32(self): + + data, ref_costs, ref_gradients = get_data_B2_T4_U3_D3( + dtype=torch.float32, device=self.device + ) + logits_shape = data["logits"].shape + costs, gradients = compute_with_pytorch_transducer(data=data) + + atol, rtol = 1e-6, 1e-2 + self.assertEqual(costs, ref_costs, atol=atol, rtol=rtol) + self.assertEqual(logits_shape, gradients.shape) + self.assertEqual(gradients, ref_gradients, atol=atol, rtol=rtol) + + +@common_utils.skipIfNoExtension +class CPUTransducerTester(TransducerTester, common_utils.PytorchTestCase): + device = "cpu" diff --git a/third_party/CMakeLists.txt b/third_party/CMakeLists.txt index 50c7696eb5..1284affa88 100644 --- a/third_party/CMakeLists.txt +++ b/third_party/CMakeLists.txt @@ -1,91 +1,16 @@ -cmake_minimum_required(VERSION 3.1) +cmake_minimum_required(VERSION 3.5) project(torchaudio_third_parties) -include(ExternalProject) -set(INSTALL_DIR ${CMAKE_CURRENT_SOURCE_DIR}/install) -set(ARCHIVE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/archives) -set(COMMON_ARGS --quiet --disable-shared --enable-static --prefix=${INSTALL_DIR} --with-pic --disable-dependency-tracking --disable-debug --disable-examples --disable-doc) +option(BUILD_SOX "Build libsox statically") +option(BUILD_TRANSDUCER "Build transducer statically") -ExternalProject_Add(libmad - PREFIX ${CMAKE_CURRENT_SOURCE_DIR} - DOWNLOAD_DIR ${ARCHIVE_DIR} - URL https://downloads.sourceforge.net/project/mad/libmad/0.15.1b/libmad-0.15.1b.tar.gz - URL_HASH SHA256=bbfac3ed6bfbc2823d3775ebb931087371e142bb0e9bb1bee51a76a6e0078690 - PATCH_COMMAND patch < ${CMAKE_CURRENT_SOURCE_DIR}/patch/libmad.patch - CONFIGURE_COMMAND ${CMAKE_CURRENT_SOURCE_DIR}/src/libmad/configure ${COMMON_ARGS} -) +set(CMAKE_POSITION_INDEPENDENT_CODE ON) -ExternalProject_Add(amr - PREFIX ${CMAKE_CURRENT_SOURCE_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 - CONFIGURE_COMMAND ${CMAKE_CURRENT_SOURCE_DIR}/src/amr/configure ${COMMON_ARGS} -) +if (BUILD_SOX) + add_subdirectory(sox) +endif() -ExternalProject_Add(libmp3lame - PREFIX ${CMAKE_CURRENT_SOURCE_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 - CONFIGURE_COMMAND ${CMAKE_CURRENT_SOURCE_DIR}/src/libmp3lame/configure ${COMMON_ARGS} --enable-nasm -) - -ExternalProject_Add(libogg - PREFIX ${CMAKE_CURRENT_SOURCE_DIR} - DOWNLOAD_DIR ${ARCHIVE_DIR} - URL https://ftp.osuosl.org/pub/xiph/releases/ogg/libogg-1.3.3.tar.gz - URL_HASH SHA256=c2e8a485110b97550f453226ec644ebac6cb29d1caef2902c007edab4308d985 - CONFIGURE_COMMAND ${CMAKE_CURRENT_SOURCE_DIR}/src/libogg/configure ${COMMON_ARGS} -) - -ExternalProject_Add(libflac - PREFIX ${CMAKE_CURRENT_SOURCE_DIR} - DEPENDS libogg - DOWNLOAD_DIR ${ARCHIVE_DIR} - URL https://ftp.osuosl.org/pub/xiph/releases/flac/flac-1.3.2.tar.xz - URL_HASH SHA256=91cfc3ed61dc40f47f050a109b08610667d73477af6ef36dcad31c31a4a8d53f - CONFIGURE_COMMAND ${CMAKE_CURRENT_SOURCE_DIR}/build_codec_helper.sh ${CMAKE_CURRENT_SOURCE_DIR}/src/libflac/configure ${COMMON_ARGS} --with-ogg -) - -ExternalProject_Add(libvorbis - PREFIX ${CMAKE_CURRENT_SOURCE_DIR} - DEPENDS libogg - DOWNLOAD_DIR ${ARCHIVE_DIR} - URL https://ftp.osuosl.org/pub/xiph/releases/vorbis/libvorbis-1.3.6.tar.gz - URL_HASH SHA256=6ed40e0241089a42c48604dc00e362beee00036af2d8b3f46338031c9e0351cb - CONFIGURE_COMMAND ${CMAKE_CURRENT_SOURCE_DIR}/build_codec_helper.sh ${CMAKE_CURRENT_SOURCE_DIR}/src/libvorbis/configure ${COMMON_ARGS} --with-ogg -) - -ExternalProject_Add(libopus - PREFIX ${CMAKE_CURRENT_SOURCE_DIR} - DEPENDS libogg - DOWNLOAD_DIR ${ARCHIVE_DIR} - URL https://ftp.osuosl.org/pub/xiph/releases/opus/opus-1.3.1.tar.gz - URL_HASH SHA256=65b58e1e25b2a114157014736a3d9dfeaad8d41be1c8179866f144a2fb44ff9d - CONFIGURE_COMMAND ${CMAKE_CURRENT_SOURCE_DIR}/build_codec_helper.sh ${CMAKE_CURRENT_SOURCE_DIR}/src/libopus/configure ${COMMON_ARGS} --with-ogg -) - -ExternalProject_Add(opusfile - PREFIX ${CMAKE_CURRENT_SOURCE_DIR} - DEPENDS libopus - DOWNLOAD_DIR ${ARCHIVE_DIR} - STAMP_DIR ${CMAKE_CURRENT_SOURCE_DIR}/src/opusfile-stamp - SOURCE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/src/opusfile - URL https://ftp.osuosl.org/pub/xiph/releases/opus/opusfile-0.12.tar.gz - URL_HASH SHA256=118d8601c12dd6a44f52423e68ca9083cc9f2bfe72da7a8c1acb22a80ae3550b - CONFIGURE_COMMAND ${CMAKE_CURRENT_SOURCE_DIR}/build_codec_helper.sh ${CMAKE_CURRENT_SOURCE_DIR}/src/opusfile/configure ${COMMON_ARGS} --disable-http -) - -ExternalProject_Add(libsox - PREFIX ${CMAKE_CURRENT_SOURCE_DIR} - DEPENDS libogg libflac libvorbis opusfile libmp3lame libmad amr - 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 patch -p0 < ${CMAKE_CURRENT_SOURCE_DIR}/patch/libsox.patch - # 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 - CONFIGURE_COMMAND ${CMAKE_CURRENT_SOURCE_DIR}/build_codec_helper.sh ${CMAKE_CURRENT_SOURCE_DIR}/src/libsox/configure ${COMMON_ARGS} --with-lame --with-flac --with-mad --with-oggvorbis --without-alsa --without-coreaudio --without-png --without-oss --without-sndfile --with-opus --with-amrwb --with-amrnb --disable-openmp -) +if(BUILD_TRANSDUCER) + add_subdirectory(transducer) +endif() diff --git a/third_party/build_codec_helper.sh b/third_party/build_codec_helper.sh deleted file mode 100755 index e7f2614781..0000000000 --- a/third_party/build_codec_helper.sh +++ /dev/null @@ -1,13 +0,0 @@ -#!/usr/bin/env bash -# Helper script for building codecs depending on libogg, such as libopus and opus. -# It is difficult to set environment variable inside of ExternalProject_Add, -# so this script sets necessary environment variables before running the given command - -this_dir="$( cd "$( dirname "${BASH_SOURCE[0]}" )" >/dev/null 2>&1 && pwd )" -install_dir="${this_dir}/install" - -export PKG_CONFIG_PATH="${install_dir}/lib/pkgconfig" -export LDFLAGS="-L${install_dir}/lib ${LDFLAGS}" -export CPPFLAGS="-I${install_dir}/include ${CPPFLAGS}" - -$@ diff --git a/third_party/patch/libsox.patch b/third_party/patch/libsox.patch deleted file mode 100644 index 996bafdd57..0000000000 --- a/third_party/patch/libsox.patch +++ /dev/null @@ -1,24 +0,0 @@ ---- src/formats.c 2014-10-27 02:55:50.000000000 +0000 -+++ src/formats_new.c 2020-11-18 19:14:17.398689371 +0000 -@@ -91,6 +91,21 @@ - - if (ext && !strcasecmp(ext, "snd")) - CHECK(sndr , 7, 1, "" , 0, 2, "\0") -+ -+#if defined HAVE_MP3 && (defined STATIC_MP3 || !defined HAVE_LIBLTDL) -+ // http://www.mp3-tech.org/programmer/frame_header.html -+ // Check the first two bytes are -+ // expected 1111_1111 111X_X01X -+ // mask \xEEE6 (1111_1111 1110_0110) -+ // masked value \xEEE2 (1111_1111 1110_0010) -+ if (len >= 2 && !memcmp(data, "\xFF", 1)) { -+ unsigned char second_byte = data[1]; -+ unsigned char mask = 0xE6; -+ unsigned char expected = 0xE2; -+ if ((second_byte & mask) == expected) -+ return "mp3"; -+ } -+#endif - #undef CHECK - - #if HAVE_MAGIC diff --git a/third_party/sox/CMakeLists.txt b/third_party/sox/CMakeLists.txt new file mode 100644 index 0000000000..dcad72bbfe --- /dev/null +++ b/third_party/sox/CMakeLists.txt @@ -0,0 +1,95 @@ +include(ExternalProject) + +set(INSTALL_DIR ${PROJECT_SOURCE_DIR}/install) +set(ARCHIVE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/archives) +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}" + "CPPFLAGS=-I${INSTALL_DIR}/include $ENV{CPPFLAGS}" +) + +ExternalProject_Add(mad + PREFIX ${CMAKE_CURRENT_BINARY_DIR} + DOWNLOAD_DIR ${ARCHIVE_DIR} + URL https://downloads.sourceforge.net/project/mad/libmad/0.15.1b/libmad-0.15.1b.tar.gz + URL_HASH SHA256=bbfac3ed6bfbc2823d3775ebb931087371e142bb0e9bb1bee51a76a6e0078690 + PATCH_COMMAND patch < ${CMAKE_CURRENT_SOURCE_DIR}/patch/libmad.patch + CONFIGURE_COMMAND ${CMAKE_COMMAND} -E env ${envs} ${CMAKE_CURRENT_BINARY_DIR}/src/mad/configure ${COMMON_ARGS} +) + +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 + CONFIGURE_COMMAND ${CMAKE_COMMAND} -E env ${envs} ${CMAKE_CURRENT_BINARY_DIR}/src/amr/configure ${COMMON_ARGS} +) + +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 + CONFIGURE_COMMAND ${CMAKE_COMMAND} -E env ${envs} ${CMAKE_CURRENT_BINARY_DIR}/src/lame/configure ${COMMON_ARGS} --enable-nasm +) + +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 + CONFIGURE_COMMAND ${CMAKE_COMMAND} -E env ${envs} ${CMAKE_CURRENT_BINARY_DIR}/src/ogg/configure ${COMMON_ARGS} +) + +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 + CONFIGURE_COMMAND ${CMAKE_COMMAND} -E env ${envs} ${CMAKE_CURRENT_BINARY_DIR}/src/flac/configure ${COMMON_ARGS} --with-ogg --disable-cpplibs +) + +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 + CONFIGURE_COMMAND ${CMAKE_COMMAND} -E env ${envs} ${CMAKE_CURRENT_BINARY_DIR}/src/vorbis/configure ${COMMON_ARGS} --with-ogg +) + +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 + CONFIGURE_COMMAND ${CMAKE_COMMAND} -E env ${envs} ${CMAKE_CURRENT_BINARY_DIR}/src/opus/configure ${COMMON_ARGS} --with-ogg +) + +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 + CONFIGURE_COMMAND ${CMAKE_COMMAND} -E env ${envs} ${CMAKE_CURRENT_BINARY_DIR}/src/opusfile/configure ${COMMON_ARGS} --disable-http +) + +ExternalProject_Add(sox + PREFIX ${CMAKE_CURRENT_BINARY_DIR} + DEPENDS ogg flac vorbis opusfile lame mad amr + 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 + # 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 + CONFIGURE_COMMAND ${CMAKE_COMMAND} -E env ${envs} ${CMAKE_CURRENT_BINARY_DIR}/src/sox/configure ${COMMON_ARGS} --with-lame --with-flac --with-mad --with-oggvorbis --without-alsa --without-coreaudio --without-png --without-oss --without-sndfile --with-opus --with-amrwb --with-amrnb --disable-openmp --without-sndio --without-pulseaudio +) diff --git a/third_party/patch/libmad.patch b/third_party/sox/patch/libmad.patch similarity index 100% rename from third_party/patch/libmad.patch rename to third_party/sox/patch/libmad.patch diff --git a/third_party/transducer/CMakeLists.txt b/third_party/transducer/CMakeLists.txt new file mode 100755 index 0000000000..c35f0c8552 --- /dev/null +++ b/third_party/transducer/CMakeLists.txt @@ -0,0 +1,27 @@ +ADD_DEFINITIONS(-DRNNT_DISABLE_OMP) + +IF(APPLE) + ADD_DEFINITIONS(-DAPPLE) + EXEC_PROGRAM(uname ARGS -v OUTPUT_VARIABLE DARWIN_VERSION) + STRING(REGEX MATCH "[0-9]+" DARWIN_VERSION ${DARWIN_VERSION}) + MESSAGE(STATUS "DARWIN_VERSION=${DARWIN_VERSION}") + + # for el capitain have to use rpath + IF(DARWIN_VERSION LESS 15) + SET(CMAKE_SKIP_RPATH TRUE) + ENDIF() + +ELSE() + # always skip for linux + SET(CMAKE_SKIP_RPATH TRUE) +ENDIF() + +ADD_LIBRARY(warprnnt STATIC submodule/src/rnnt_entrypoint.cpp) +target_include_directories(warprnnt PUBLIC submodule/include) +set_target_properties(warprnnt PROPERTIES PUBLIC_HEADER submodule/include/rnnt.h) + + +INSTALL( + TARGETS warprnnt + ARCHIVE DESTINATION "lib" + PUBLIC_HEADER DESTINATION "include") diff --git a/torchaudio/backend/_soundfile_backend.py b/torchaudio/backend/_soundfile_backend.py index 83d3cbc3cf..719224b827 100644 --- a/torchaudio/backend/_soundfile_backend.py +++ b/torchaudio/backend/_soundfile_backend.py @@ -12,7 +12,7 @@ @_mod_utils.requires_module("soundfile") -def info(filepath: str) -> AudioMetaData: +def info(filepath: str, format: Optional[str] = None) -> AudioMetaData: """Get signal information of an audio file. Args: @@ -20,6 +20,8 @@ def info(filepath: str) -> AudioMetaData: This functionalso handles ``pathlib.Path`` objects, but is annotated as ``str`` for the consistency with "sox_io" backend, which has a restriction on type annotation for TorchScript compiler compatiblity. + format (str, optional): + Not used. PySoundFile does not accept format hint. Returns: AudioMetaData: meta data of the given audio. @@ -45,6 +47,7 @@ def load( num_frames: int = -1, normalize: bool = True, channels_first: bool = True, + format: Optional[str] = None, ) -> Tuple[torch.Tensor, int]: """Load audio data from file. @@ -79,10 +82,12 @@ def load( ``[-1.0, 1.0]``. Args: - filepath (str or pathlib.Path): Path to audio file. - This functionalso handles ``pathlib.Path`` objects, but is annotated as ``str`` - for the consistency with "sox_io" backend, which has a restriction on type annotation - for TorchScript compiler compatiblity. + filepath (path-like object or file-like object): + Source of audio data. + Note: + * This argument is intentionally annotated as ``str`` only, + for the consistency with "sox_io" backend, which has a restriction + on type annotation due to TorchScript compiler compatiblity. frame_offset (int): Number of frames to skip before start reading data. num_frames (int): @@ -99,9 +104,11 @@ def load( channels_first (bool): When True, the returned Tensor has dimension ``[channel, time]``. Otherwise, the returned Tensor's dimension is ``[time, channel]``. + format (str, optional): + Not used. PySoundFile does not accept format hint. Returns: - torch.Tensor: + Tuple[torch.Tensor, int]: Resulting Tensor and sample rate. If the input file has integer wav format and normalization is off, then it has integer type, else ``float32`` type. If ``channels_first=True``, it has ``[channel, time]`` else ``[time, channel]``. diff --git a/torchaudio/backend/sox_io_backend.py b/torchaudio/backend/sox_io_backend.py index 5293223977..1e6d417cb8 100644 --- a/torchaudio/backend/sox_io_backend.py +++ b/torchaudio/backend/sox_io_backend.py @@ -1,3 +1,4 @@ +import os from typing import Tuple, Optional import torch @@ -5,24 +6,32 @@ module_utils as _mod_utils, ) +import torchaudio from .common import AudioMetaData @_mod_utils.requires_module('torchaudio._torchaudio') -def info(filepath: str) -> AudioMetaData: +def info( + filepath: str, + format: Optional[str] = None, +) -> AudioMetaData: """Get signal information of an audio file. Args: filepath (str or pathlib.Path): Path to audio file. This function also handles ``pathlib.Path`` objects, but is annotated as ``str`` for TorchScript compatibility. + format (str, optional): + Override the format detection with the given format. + Providing the argument might help when libsox can not infer the format + from header or extension, Returns: AudioMetaData: Metadata of the given audio. """ # Cast to str in case type is `pathlib.Path` filepath = str(filepath) - sinfo = torch.ops.torchaudio.sox_io_get_info(filepath) + sinfo = torch.ops.torchaudio.sox_io_get_info(filepath, format) return AudioMetaData(sinfo.get_sample_rate(), sinfo.get_num_frames(), sinfo.get_num_channels()) @@ -33,6 +42,7 @@ def load( num_frames: int = -1, normalize: bool = True, channels_first: bool = True, + format: Optional[str] = None, ) -> Tuple[torch.Tensor, int]: """Load audio data from file. @@ -74,9 +84,17 @@ def load( ``[-1.0, 1.0]``. Args: - filepath (str or pathlib.Path): - Path to audio file. This function also handles ``pathlib.Path`` objects, but is - annotated as ``str`` for TorchScript compiler compatibility. + filepath (path-like object or file-like object): + Source of audio data. When the function is not compiled by TorchScript, + (e.g. ``torch.jit.script``), the following types are accepted; + * ``path-like``: file path + * ``file-like``: Object with ``read(size: int) -> bytes`` method, + which returns byte string of at most ``size`` length. + When the function is compiled by TorchScript, only ``str`` type is allowed. + + Note: + * This argument is intentionally annotated as ``str`` only due to + TorchScript compiler compatibility. frame_offset (int): Number of frames to skip before start reading data. num_frames (int): @@ -93,17 +111,26 @@ def load( channels_first (bool): When True, the returned Tensor has dimension ``[channel, time]``. Otherwise, the returned Tensor's dimension is ``[time, channel]``. + format (str, optional): + Override the format detection with the given format. + Providing the argument might help when libsox can not infer the format + from header or extension, Returns: - torch.Tensor: + Tuple[torch.Tensor, int]: Resulting Tensor and sample rate. If the input file has integer wav format and normalization is off, then it has integer type, else ``float32`` type. If ``channels_first=True``, it has ``[channel, time]`` else ``[time, channel]``. """ - # Cast to str in case type is `pathlib.Path` - filepath = str(filepath) + if not torch.jit.is_scripting(): + if hasattr(filepath, 'read'): + return torchaudio._torchaudio.load_audio_fileobj( + filepath, frame_offset, num_frames, normalize, channels_first, format) + signal = torch.ops.torchaudio.sox_io_load_audio_file( + os.fspath(filepath), frame_offset, num_frames, normalize, channels_first, format) + return signal.get_tensor(), signal.get_sample_rate() signal = torch.ops.torchaudio.sox_io_load_audio_file( - filepath, frame_offset, num_frames, normalize, channels_first) + filepath, frame_offset, num_frames, normalize, channels_first, format) return signal.get_tensor(), signal.get_sample_rate() diff --git a/torchaudio/csrc/sox.cpp b/torchaudio/csrc/pybind.cpp similarity index 52% rename from torchaudio/csrc/sox.cpp rename to torchaudio/csrc/pybind.cpp index 3be7d01314..caf9ad9b19 100644 --- a/torchaudio/csrc/sox.cpp +++ b/torchaudio/csrc/pybind.cpp @@ -1,182 +1,7 @@ -#include +#include +#include +#include -#include -#include -#include -#include - -namespace torch { -namespace audio { -namespace { -/// Helper struct to safely close the sox_format_t descriptor. -struct SoxDescriptor { - explicit SoxDescriptor(sox_format_t* fd) noexcept : fd_(fd) {} - SoxDescriptor(const SoxDescriptor& other) = delete; - SoxDescriptor(SoxDescriptor&& other) = delete; - SoxDescriptor& operator=(const SoxDescriptor& other) = delete; - SoxDescriptor& operator=(SoxDescriptor&& other) = delete; - ~SoxDescriptor() { - if (fd_ != nullptr) { - sox_close(fd_); - } - } - sox_format_t* operator->() noexcept { - return fd_; - } - sox_format_t* get() noexcept { - return fd_; - } - - private: - sox_format_t* fd_; -}; - -int64_t write_audio(SoxDescriptor& fd, at::Tensor tensor) { - std::vector buffer(tensor.numel()); - - AT_DISPATCH_ALL_TYPES(tensor.scalar_type(), "write_audio_buffer", [&] { - auto* data = tensor.data_ptr(); - std::copy(data, data + tensor.numel(), buffer.begin()); - }); - - const auto samples_written = - sox_write(fd.get(), buffer.data(), buffer.size()); - - return samples_written; -} - -void read_audio( - SoxDescriptor& fd, - at::Tensor output, - int64_t buffer_length) { - std::vector buffer(buffer_length); - - int number_of_channels = fd->signal.channels; - const int64_t samples_read = sox_read(fd.get(), buffer.data(), buffer_length); - if (samples_read == 0) { - throw std::runtime_error( - "Error reading audio file: empty file or read failed in sox_read"); - } - - output.resize_({samples_read / number_of_channels, number_of_channels}); - output = output.contiguous(); - - AT_DISPATCH_ALL_TYPES(output.scalar_type(), "read_audio_buffer", [&] { - auto* data = output.data_ptr(); - std::copy(buffer.begin(), buffer.begin() + samples_read, data); - }); -} -} // namespace - -std::tuple get_info( - const std::string& file_name - ) { - SoxDescriptor fd(sox_open_read( - file_name.c_str(), - /*signal=*/nullptr, - /*encoding=*/nullptr, - /*filetype=*/nullptr)); - if (fd.get() == nullptr) { - throw std::runtime_error("Error opening audio file"); - } - return std::make_tuple(fd->signal, fd->encoding); -} - -int read_audio_file( - const std::string& file_name, - at::Tensor output, - bool ch_first, - int64_t nframes, - int64_t offset, - sox_signalinfo_t* si, - sox_encodinginfo_t* ei, - const char* ft) { - - SoxDescriptor fd(sox_open_read(file_name.c_str(), si, ei, ft)); - if (fd.get() == nullptr) { - throw std::runtime_error("Error opening audio file"); - } - - // signal info - - const int number_of_channels = fd->signal.channels; - const int sample_rate = fd->signal.rate; - const int64_t total_length = fd->signal.length; - - // multiply offset and number of frames by number of channels - offset *= number_of_channels; - nframes *= number_of_channels; - - if (total_length == 0) { - throw std::runtime_error("Error reading audio file: unknown length"); - } - if (offset > total_length) { - throw std::runtime_error("Offset past EOF"); - } - - // calculate buffer length - int64_t buffer_length = total_length; - if (offset > 0) { - buffer_length -= offset; - } - if (nframes > 0 && buffer_length > nframes) { - buffer_length = nframes; - } - - // seek to offset point before reading data - if (sox_seek(fd.get(), offset, 0) == SOX_EOF) { - throw std::runtime_error("sox_seek reached EOF, try reducing offset or num_samples"); - } - - // read data and fill output tensor - read_audio(fd, output, buffer_length); - - // L x C -> C x L, if desired - if (ch_first) { - output.transpose_(1, 0); - } - - return sample_rate; -} - -void write_audio_file( - const std::string& file_name, - const at::Tensor& tensor, - sox_signalinfo_t* si, - sox_encodinginfo_t* ei, - const char* file_type) { - if (!tensor.is_contiguous()) { - throw std::runtime_error( - "Error writing audio file: input tensor must be contiguous"); - } - -#if SOX_LIB_VERSION_CODE >= 918272 // >= 14.3.0 - si->mult = nullptr; -#endif - - SoxDescriptor fd(sox_open_write( - file_name.c_str(), - si, - ei, - file_type, - /*oob=*/nullptr, - /*overwrite=*/nullptr)); - - if (fd.get() == nullptr) { - throw std::runtime_error( - "Error writing audio file: could not open file for writing"); - } - - const auto samples_written = write_audio(fd, tensor); - - if (samples_written != tensor.numel()) { - throw std::runtime_error( - "Error writing audio file: could not write entire buffer"); - } -} - -} // namespace audio -} // namespace torch PYBIND11_MODULE(_torchaudio, m) { py::class_(m, "sox_signalinfo_t") @@ -271,4 +96,8 @@ PYBIND11_MODULE(_torchaudio, m) { "get_info", &torch::audio::get_info, "Gets information about an audio file"); + m.def( + "load_audio_fileobj", + &torchaudio::sox_io::load_audio_fileobj, + "Load audio from file object."); } diff --git a/torchaudio/csrc/sox_effects.cpp b/torchaudio/csrc/sox/effects.cpp similarity index 51% rename from torchaudio/csrc/sox_effects.cpp rename to torchaudio/csrc/sox/effects.cpp index 7bd24b6bc2..ffc85b92ed 100644 --- a/torchaudio/csrc/sox_effects.cpp +++ b/torchaudio/csrc/sox/effects.cpp @@ -1,7 +1,7 @@ #include -#include -#include -#include +#include +#include +#include using namespace torchaudio::sox_utils; @@ -92,13 +92,14 @@ c10::intrusive_ptr apply_effects_file( const std::string path, std::vector> effects, c10::optional& normalize, - c10::optional& channels_first) { + c10::optional& channels_first, + c10::optional& format) { // Open input file SoxFormat sf(sox_open_read( path.c_str(), /*signal=*/nullptr, /*encoding=*/nullptr, - /*filetype=*/nullptr)); + /*filetype=*/format.has_value() ? format.value().c_str() : nullptr)); validate_input_file(sf); @@ -134,5 +135,88 @@ c10::intrusive_ptr apply_effects_file( tensor, chain.getOutputSampleRate(), channels_first_); } +#ifdef TORCH_API_INCLUDE_EXTENSION_H + +std::tuple apply_effects_fileobj( + py::object fileobj, + std::vector> effects, + c10::optional& normalize, + c10::optional& channels_first, + c10::optional& format) { + + // Streaming decoding over file-like object is tricky because libsox operates on FILE pointer. + // The folloing is what `sox` and `play` commands do + // - file input -> FILE pointer + // - URL input -> call wget in suprocess and pipe the data -> FILE pointer + // - stdin -> FILE pointer + // + // We want to, instead, fetch byte strings chunk by chunk, consume them, and discard. + // + // Here is the approach + // 1. Initialize sox_format_t using sox_open_mem_read, providing the initial chunk of byte string + // This will perform header-based format detection, if necessary, then fill the metadata of + // sox_format_t. Internally, sox_open_mem_read uses fmemopen, which returns FILE* which points the + // buffer of the provided byte string. + // 2. Each time sox reads a chunk from the FILE*, we update the underlying buffer in a way that it + // starts with unseen data, and append the new data read from the given fileobj. + // This will trick libsox as if it keeps reading from the FILE* continuously. + + // Prepare the buffer used throughout the lifecycle of SoxEffectChain. + // Using std::string and let it manage memory. + // 4096 is minimum size required by auto_detect_format + // https://github.com/dmkrepo/libsox/blob/b9dd1a86e71bbd62221904e3e59dfaa9e5e72046/src/formats.c#L40-L48 + const size_t in_buffer_size = 4096; + std::string in_buffer(in_buffer_size, 'x'); + auto* in_buf = const_cast(in_buffer.data()); + + // Fetch the header, and copy it to the buffer. + auto header = static_cast(static_cast(fileobj.attr("read")(4096))); + memcpy(static_cast(in_buf), + static_cast(const_cast(header.data())), header.length()); + + // Open file (this starts reading the header) + SoxFormat sf(sox_open_mem_read( + in_buf, + in_buffer_size, + /*signal=*/nullptr, + /*encoding=*/nullptr, + /*filetype=*/format.has_value() ? format.value().c_str() : nullptr)); + + // In case of streamed data, length can be 0 + validate_input_file(sf, /*check_length=*/false); + + // Prepare output buffer + std::vector out_buffer; + out_buffer.reserve(sf->signal.length); + + // Create and run SoxEffectsChain + const auto dtype = get_dtype(sf->encoding.encoding, sf->signal.precision); + torchaudio::sox_effects_chain::SoxEffectsChain chain( + /*input_encoding=*/sf->encoding, + /*output_encoding=*/get_encodinginfo("wav", dtype, 0.)); + chain.addInputFileObj(sf, in_buf, in_buffer_size, &fileobj); + for (const auto& effect : effects) { + chain.addEffect(effect); + } + chain.addOutputBuffer(&out_buffer); + chain.run(); + + // Create tensor from buffer + bool channels_first_ = channels_first.value_or(true); + auto tensor = convert_to_tensor( + /*buffer=*/out_buffer.data(), + /*num_samples=*/out_buffer.size(), + /*num_channels=*/chain.getOutputNumChannels(), + dtype, + normalize.value_or(true), + channels_first_); + + return std::make_tuple( + tensor, + static_cast(chain.getOutputSampleRate())); +} + +#endif // TORCH_API_INCLUDE_EXTENSION_H + } // namespace sox_effects } // namespace torchaudio diff --git a/torchaudio/csrc/sox_effects.h b/torchaudio/csrc/sox/effects.h similarity index 54% rename from torchaudio/csrc/sox_effects.h rename to torchaudio/csrc/sox/effects.h index 669c86ac39..a2a598b408 100644 --- a/torchaudio/csrc/sox_effects.h +++ b/torchaudio/csrc/sox/effects.h @@ -1,8 +1,12 @@ #ifndef TORCHAUDIO_SOX_EFFECTS_H #define TORCHAUDIO_SOX_EFFECTS_H +#ifdef TORCH_API_INCLUDE_EXTENSION_H +#include +#endif // TORCH_API_INCLUDE_EXTENSION_H + #include -#include +#include namespace torchaudio { namespace sox_effects { @@ -19,7 +23,19 @@ c10::intrusive_ptr apply_effects_file( const std::string path, std::vector> effects, c10::optional& normalize, - c10::optional& channels_first); + c10::optional& channels_first, + c10::optional& format); + +#ifdef TORCH_API_INCLUDE_EXTENSION_H + +std::tuple apply_effects_fileobj( + py::object fileobj, + std::vector> effects, + c10::optional& normalize, + c10::optional& channels_first, + c10::optional& format); + +#endif // TORCH_API_INCLUDE_EXTENSION_H } // namespace sox_effects } // namespace torchaudio diff --git a/torchaudio/csrc/sox_effects_chain.cpp b/torchaudio/csrc/sox/effects_chain.cpp similarity index 64% rename from torchaudio/csrc/sox_effects_chain.cpp rename to torchaudio/csrc/sox/effects_chain.cpp index 449e33be98..37a6f32df8 100644 --- a/torchaudio/csrc/sox_effects_chain.cpp +++ b/torchaudio/csrc/sox/effects_chain.cpp @@ -1,5 +1,5 @@ -#include -#include +#include +#include using namespace torch::indexing; using namespace torchaudio::sox_utils; @@ -198,7 +198,7 @@ void SoxEffectsChain::addInputTensor(TensorSignal* signal) { priv->signal = signal; priv->index = 0; if (sox_add_effect(sec_, e, &interm_sig_, &in_sig_) != SOX_SUCCESS) { - throw std::runtime_error("Failed to add effect: input_tensor"); + throw std::runtime_error("Internal Error: Failed to add effect: input_tensor"); } } @@ -207,7 +207,7 @@ void SoxEffectsChain::addOutputBuffer( SoxEffect e(sox_create_effect(get_tensor_output_handler())); static_cast(e->priv)->buffer = output_buffer; if (sox_add_effect(sec_, e, &interm_sig_, &in_sig_) != SOX_SUCCESS) { - throw std::runtime_error("Failed to add effect: output_tensor"); + throw std::runtime_error("Internal Error: Failed to add effect: output_tensor"); } } @@ -219,7 +219,7 @@ void SoxEffectsChain::addInputFile(sox_format_t* sf) { sox_effect_options(e, 1, opts); if (sox_add_effect(sec_, e, &interm_sig_, &in_sig_) != SOX_SUCCESS) { std::ostringstream stream; - stream << "Failed to add effect: input " << sf->filename; + stream << "Internal Error: Failed to add effect: input " << sf->filename; throw std::runtime_error(stream.str()); } } @@ -230,7 +230,7 @@ void SoxEffectsChain::addOutputFile(sox_format_t* sf) { static_cast(e->priv)->sf = sf; if (sox_add_effect(sec_, e, &interm_sig_, &out_sig_) != SOX_SUCCESS) { std::ostringstream stream; - stream << "Failed to add effect: output " << sf->filename; + stream << "Internal Error: Failed to add effect: output " << sf->filename; throw std::runtime_error(stream.str()); } } @@ -266,7 +266,7 @@ void SoxEffectsChain::addEffect(const std::vector effect) { if (sox_add_effect(sec_, e, &interm_sig_, &in_sig_) != SOX_SUCCESS) { std::ostringstream stream; - stream << "Failed to add effect: \"" << name; + stream << "Internal Error: Failed to add effect: \"" << name; for (size_t i = 1; i < num_args; ++i) { stream << " " << effect[i]; } @@ -283,5 +283,132 @@ int64_t SoxEffectsChain::getOutputSampleRate() { return interm_sig_.rate; } +#ifdef TORCH_API_INCLUDE_EXTENSION_H + +namespace { + +/// helper classes for passing file-like object to SoxEffectChain +struct FileObjInputPriv { + sox_format_t* sf; + py::object* fileobj; + char* buffer; + uint64_t buffer_size; +}; + +/// Callback function to feed byte string +/// https://github.com/dmkrepo/libsox/blob/b9dd1a86e71bbd62221904e3e59dfaa9e5e72046/src/sox.h#L1268-L1278 +int fileobj_input_drain(sox_effect_t* effp, sox_sample_t* obuf, size_t* osamp) { + auto priv = static_cast(effp->priv); + auto sf = priv->sf; + auto fileobj = priv->fileobj; + auto buffer = priv->buffer; + auto buffer_size = priv->buffer_size; + + // 1. Refresh the buffer + // + // NOTE: + // Since the underlying FILE* was opened with `fmemopen`, the only way + // libsox detect EOF is reaching the end of the buffer. (null byte won't help) + // Therefore we need to align the content at the end of buffer, otherwise, + // libsox will keep reading the content beyond intended length. + // + // Before: + // + // |<--------consumed------->|<-remaining->| + // |*************************|-------------| + // ^ ftell + // + // After: + // + // |<-offset->|<-remaining->|<--new data-->| + // |**********|-------------|++++++++++++++| + // ^ ftell + + const auto num_consumed = sf->tell_off; + const auto num_remain = buffer_size - num_consumed; + + // 1.1. First, we fetch the data to see if there is data to fill the buffer + py::bytes chunk_ = fileobj->attr("read")(num_consumed); + const auto num_refill = py::len(chunk_); + const auto offset = buffer_size - (num_remain + num_refill); + + if(num_refill > num_consumed) { + std::ostringstream message; + message << "Tried to read up to " << num_consumed << " bytes but, " + << "received " << num_refill << " bytes. " + << "The given object does not confirm to read protocol of file object."; + throw std::runtime_error(message.str()); + } + + // 1.2. Move the unconsumed data towards the beginning of buffer. + if (num_remain) { + auto src = static_cast(buffer + num_consumed); + auto dst = static_cast(buffer + offset); + memmove(dst, src, num_remain); + } + + // 1.3. Refill the remaining buffer. + if (num_refill) { + auto chunk = static_cast(chunk_); + auto src = static_cast(const_cast(chunk.c_str())); + auto dst = buffer + offset + num_remain; + memcpy(dst, src, num_refill); + } + + // 1.4. Set the file pointer to the new offset + sf->tell_off = offset; + fseek ((FILE*)sf->fp, offset, SEEK_SET); + + // 2. Perform decoding operation + // The following part is practically same as "input" effect + // https://github.com/dmkrepo/libsox/blob/b9dd1a86e71bbd62221904e3e59dfaa9e5e72046/src/input.c#L30-L48 + + // Ensure that it's a multiple of the number of channels + *osamp -= *osamp % effp->out_signal.channels; + + // Read up to *osamp samples into obuf; + // store the actual number read back to *osamp + *osamp = sox_read(sf, obuf, *osamp); + + return *osamp? SOX_SUCCESS : SOX_EOF; +} + +sox_effect_handler_t* get_fileobj_input_handler() { + static sox_effect_handler_t handler{/*name=*/"input_fileobj_object", + /*usage=*/NULL, + /*flags=*/SOX_EFF_MCHAN, + /*getopts=*/NULL, + /*start=*/NULL, + /*flow=*/NULL, + /*drain=*/fileobj_input_drain, + /*stop=*/NULL, + /*kill=*/NULL, + /*priv_size=*/sizeof(FileObjInputPriv)}; + return &handler; +} + +} // namespace + +void SoxEffectsChain::addInputFileObj( + sox_format_t* sf, + char* buffer, + uint64_t buffer_size, + py::object* fileobj) { + in_sig_ = sf->signal; + interm_sig_ = in_sig_; + + SoxEffect e(sox_create_effect(get_fileobj_input_handler())); + auto priv = static_cast(e->priv); + priv->sf = sf; + priv->fileobj = fileobj; + priv->buffer = buffer; + priv->buffer_size = buffer_size; + if (sox_add_effect(sec_, e, &interm_sig_, &in_sig_) != SOX_SUCCESS) { + throw std::runtime_error("Internal Error: Failed to add effect: input fileobj"); + } +} + +#endif // TORCH_API_INCLUDE_EXTENSION_H + } // namespace sox_effects_chain } // namespace torchaudio diff --git a/torchaudio/csrc/sox_effects_chain.h b/torchaudio/csrc/sox/effects_chain.h similarity index 78% rename from torchaudio/csrc/sox_effects_chain.h rename to torchaudio/csrc/sox/effects_chain.h index fa55182281..b096b3eb3d 100644 --- a/torchaudio/csrc/sox_effects_chain.h +++ b/torchaudio/csrc/sox/effects_chain.h @@ -2,8 +2,11 @@ #define TORCHAUDIO_SOX_EFFECTS_CHAIN_H #include -#include -#include +#include + +#ifdef TORCH_API_INCLUDE_EXTENSION_H +#include +#endif // TORCH_API_INCLUDE_EXTENSION_H namespace torchaudio { namespace sox_effects_chain { @@ -34,6 +37,16 @@ class SoxEffectsChain { void addEffect(const std::vector effect); int64_t getOutputNumChannels(); int64_t getOutputSampleRate(); + +#ifdef TORCH_API_INCLUDE_EXTENSION_H + + void addInputFileObj( + sox_format_t* sf, + char* buffer, + uint64_t buffer_size, + py::object* fileobj); + +#endif // TORCH_API_INCLUDE_EXTENSION_H }; } // namespace sox_effects_chain diff --git a/torchaudio/csrc/sox_io.cpp b/torchaudio/csrc/sox/io.cpp similarity index 72% rename from torchaudio/csrc/sox_io.cpp rename to torchaudio/csrc/sox/io.cpp index 9acab1c030..e381be14f8 100644 --- a/torchaudio/csrc/sox_io.cpp +++ b/torchaudio/csrc/sox/io.cpp @@ -1,8 +1,8 @@ #include -#include -#include -#include -#include +#include +#include +#include +#include using namespace torch::indexing; using namespace torchaudio::sox_utils; @@ -30,12 +30,14 @@ int64_t SignalInfo::getNumFrames() const { return num_frames; } -c10::intrusive_ptr get_info(const std::string& path) { +c10::intrusive_ptr get_info( + const std::string& path, + c10::optional& format) { SoxFormat sf(sox_open_read( path.c_str(), /*signal=*/nullptr, /*encoding=*/nullptr, - /*filetype=*/nullptr)); + /*filetype=*/format.has_value() ? format.value().c_str() : nullptr)); if (static_cast(sf) == nullptr) { throw std::runtime_error("Error opening audio file"); @@ -47,12 +49,11 @@ c10::intrusive_ptr get_info(const std::string& path) { static_cast(sf->signal.length / sf->signal.channels)); } -c10::intrusive_ptr load_audio_file( - const std::string& path, +namespace { + +std::vector> get_effects( c10::optional& frame_offset, - c10::optional& num_frames, - c10::optional& normalize, - c10::optional& channels_first) { + c10::optional& num_frames) { const auto offset = frame_offset.value_or(0); if (offset < 0) { throw std::runtime_error( @@ -76,9 +77,21 @@ c10::intrusive_ptr load_audio_file( os_offset << offset << "s"; effects.emplace_back(std::vector{"trim", os_offset.str()}); } + return effects; +} + +} // namespace +c10::intrusive_ptr load_audio_file( + const std::string& path, + c10::optional& frame_offset, + c10::optional& num_frames, + c10::optional& normalize, + c10::optional& channels_first, + c10::optional& format) { + auto effects = get_effects(frame_offset, num_frames); return torchaudio::sox_effects::apply_effects_file( - path, effects, normalize, channels_first); + path, effects, normalize, channels_first, format); } void save_audio_file( @@ -120,5 +133,21 @@ void save_audio_file( chain.run(); } +#ifdef TORCH_API_INCLUDE_EXTENSION_H + +std::tuple load_audio_fileobj( + py::object fileobj, + c10::optional& frame_offset, + c10::optional& num_frames, + c10::optional& normalize, + c10::optional& channels_first, + c10::optional& format) { + auto effects = get_effects(frame_offset, num_frames); + return torchaudio::sox_effects::apply_effects_fileobj( + fileobj, effects, normalize, channels_first, format); +} + +#endif // TORCH_API_INCLUDE_EXTENSION_H + } // namespace sox_io } // namespace torchaudio diff --git a/torchaudio/csrc/sox_io.h b/torchaudio/csrc/sox/io.h similarity index 56% rename from torchaudio/csrc/sox_io.h rename to torchaudio/csrc/sox/io.h index d62997243e..d6e5310077 100644 --- a/torchaudio/csrc/sox_io.h +++ b/torchaudio/csrc/sox/io.h @@ -1,8 +1,12 @@ #ifndef TORCHAUDIO_SOX_IO_H #define TORCHAUDIO_SOX_IO_H +#ifdef TORCH_API_INCLUDE_EXTENSION_H +#include +#endif // TORCH_API_INCLUDE_EXTENSION_H + #include -#include +#include namespace torchaudio { namespace sox_io { @@ -21,20 +25,35 @@ struct SignalInfo : torch::CustomClassHolder { int64_t getNumFrames() const; }; -c10::intrusive_ptr get_info(const std::string& path); +c10::intrusive_ptr get_info( + const std::string& path, + c10::optional& format); c10::intrusive_ptr load_audio_file( const std::string& path, c10::optional& frame_offset, c10::optional& num_frames, c10::optional& normalize, - c10::optional& channels_first); + c10::optional& channels_first, + c10::optional& format); void save_audio_file( const std::string& file_name, const c10::intrusive_ptr& signal, const double compression = 0.); +#ifdef TORCH_API_INCLUDE_EXTENSION_H + +std::tuple load_audio_fileobj( + py::object fileobj, + c10::optional& frame_offset, + c10::optional& num_frames, + c10::optional& normalize, + c10::optional& channels_first, + c10::optional& format); + +#endif // TORCH_API_INCLUDE_EXTENSION_H + } // namespace sox_io } // namespace torchaudio diff --git a/torchaudio/csrc/sox/legacy.cpp b/torchaudio/csrc/sox/legacy.cpp new file mode 100644 index 0000000000..97e1d1d32b --- /dev/null +++ b/torchaudio/csrc/sox/legacy.cpp @@ -0,0 +1,174 @@ +#include + +namespace torch { +namespace audio { +namespace { +/// Helper struct to safely close the sox_format_t descriptor. +struct SoxDescriptor { + explicit SoxDescriptor(sox_format_t* fd) noexcept : fd_(fd) {} + SoxDescriptor(const SoxDescriptor& other) = delete; + SoxDescriptor(SoxDescriptor&& other) = delete; + SoxDescriptor& operator=(const SoxDescriptor& other) = delete; + SoxDescriptor& operator=(SoxDescriptor&& other) = delete; + ~SoxDescriptor() { + if (fd_ != nullptr) { + sox_close(fd_); + } + } + sox_format_t* operator->() noexcept { + return fd_; + } + sox_format_t* get() noexcept { + return fd_; + } + + private: + sox_format_t* fd_; +}; + +int64_t write_audio(SoxDescriptor& fd, at::Tensor tensor) { + std::vector buffer(tensor.numel()); + + AT_DISPATCH_ALL_TYPES(tensor.scalar_type(), "write_audio_buffer", [&] { + auto* data = tensor.data_ptr(); + std::copy(data, data + tensor.numel(), buffer.begin()); + }); + + const auto samples_written = + sox_write(fd.get(), buffer.data(), buffer.size()); + + return samples_written; +} + +void read_audio( + SoxDescriptor& fd, + at::Tensor output, + int64_t buffer_length) { + std::vector buffer(buffer_length); + + int number_of_channels = fd->signal.channels; + const int64_t samples_read = sox_read(fd.get(), buffer.data(), buffer_length); + if (samples_read == 0) { + throw std::runtime_error( + "Error reading audio file: empty file or read failed in sox_read"); + } + + output.resize_({samples_read / number_of_channels, number_of_channels}); + output = output.contiguous(); + + AT_DISPATCH_ALL_TYPES(output.scalar_type(), "read_audio_buffer", [&] { + auto* data = output.data_ptr(); + std::copy(buffer.begin(), buffer.begin() + samples_read, data); + }); +} +} // namespace + +std::tuple get_info( + const std::string& file_name + ) { + SoxDescriptor fd(sox_open_read( + file_name.c_str(), + /*signal=*/nullptr, + /*encoding=*/nullptr, + /*filetype=*/nullptr)); + if (fd.get() == nullptr) { + throw std::runtime_error("Error opening audio file"); + } + return std::make_tuple(fd->signal, fd->encoding); +} + +int read_audio_file( + const std::string& file_name, + at::Tensor output, + bool ch_first, + int64_t nframes, + int64_t offset, + sox_signalinfo_t* si, + sox_encodinginfo_t* ei, + const char* ft) { + + SoxDescriptor fd(sox_open_read(file_name.c_str(), si, ei, ft)); + if (fd.get() == nullptr) { + throw std::runtime_error("Error opening audio file"); + } + + // signal info + + const int number_of_channels = fd->signal.channels; + const int sample_rate = fd->signal.rate; + const int64_t total_length = fd->signal.length; + + // multiply offset and number of frames by number of channels + offset *= number_of_channels; + nframes *= number_of_channels; + + if (total_length == 0) { + throw std::runtime_error("Error reading audio file: unknown length"); + } + if (offset > total_length) { + throw std::runtime_error("Offset past EOF"); + } + + // calculate buffer length + int64_t buffer_length = total_length; + if (offset > 0) { + buffer_length -= offset; + } + if (nframes > 0 && buffer_length > nframes) { + buffer_length = nframes; + } + + // seek to offset point before reading data + if (sox_seek(fd.get(), offset, 0) == SOX_EOF) { + throw std::runtime_error("sox_seek reached EOF, try reducing offset or num_samples"); + } + + // read data and fill output tensor + read_audio(fd, output, buffer_length); + + // L x C -> C x L, if desired + if (ch_first) { + output.transpose_(1, 0); + } + + return sample_rate; +} + +void write_audio_file( + const std::string& file_name, + const at::Tensor& tensor, + sox_signalinfo_t* si, + sox_encodinginfo_t* ei, + const char* file_type) { + if (!tensor.is_contiguous()) { + throw std::runtime_error( + "Error writing audio file: input tensor must be contiguous"); + } + +#if SOX_LIB_VERSION_CODE >= 918272 // >= 14.3.0 + si->mult = nullptr; +#endif + + SoxDescriptor fd(sox_open_write( + file_name.c_str(), + si, + ei, + file_type, + /*oob=*/nullptr, + /*overwrite=*/nullptr)); + + if (fd.get() == nullptr) { + throw std::runtime_error( + "Error writing audio file: could not open file for writing"); + } + + const auto samples_written = write_audio(fd, tensor); + + if (samples_written != tensor.numel()) { + throw std::runtime_error( + "Error writing audio file: could not write entire buffer"); + } +} + +} // namespace audio +} // namespace torch diff --git a/torchaudio/csrc/sox.h b/torchaudio/csrc/sox/legacy.h similarity index 91% rename from torchaudio/csrc/sox.h rename to torchaudio/csrc/sox/legacy.h index 1344031330..6b3f8383b2 100644 --- a/torchaudio/csrc/sox.h +++ b/torchaudio/csrc/sox/legacy.h @@ -1,14 +1,5 @@ #include - -#include -#include -#include - -#include - -namespace at { -struct Tensor; -} // namespace at +#include namespace torch { namespace audio { diff --git a/torchaudio/csrc/register.cpp b/torchaudio/csrc/sox/register.cpp similarity index 85% rename from torchaudio/csrc/register.cpp rename to torchaudio/csrc/sox/register.cpp index a1ec8f2254..7c65bebe2d 100644 --- a/torchaudio/csrc/register.cpp +++ b/torchaudio/csrc/sox/register.cpp @@ -1,11 +1,8 @@ -#ifndef TORCHAUDIO_REGISTER_H -#define TORCHAUDIO_REGISTER_H +#include +#include +#include -#include -#include -#include - -TORCH_LIBRARY(torchaudio, m) { +TORCH_LIBRARY_FRAGMENT(torchaudio, m) { ////////////////////////////////////////////////////////////////////////////// // sox_utils.h ////////////////////////////////////////////////////////////////////////////// @@ -49,7 +46,14 @@ TORCH_LIBRARY(torchaudio, m) { m.def("torchaudio::sox_io_get_info", &torchaudio::sox_io::get_info); m.def( - "torchaudio::sox_io_load_audio_file", + "torchaudio::sox_io_load_audio_file(" + "str path," + "int? frame_offset=None," + "int? num_frames=None," + "bool? normalize=True," + "bool? channels_first=False," + "str? format=None" + ") -> __torch__.torch.classes.torchaudio.TensorSignal", &torchaudio::sox_io::load_audio_file); m.def( "torchaudio::sox_io_save_audio_file", @@ -71,4 +75,3 @@ TORCH_LIBRARY(torchaudio, m) { "torchaudio::sox_effects_apply_effects_file", &torchaudio::sox_effects::apply_effects_file); } -#endif diff --git a/torchaudio/csrc/sox_utils.cpp b/torchaudio/csrc/sox/utils.cpp similarity index 97% rename from torchaudio/csrc/sox_utils.cpp rename to torchaudio/csrc/sox/utils.cpp index 656cc63348..44f00084e8 100644 --- a/torchaudio/csrc/sox_utils.cpp +++ b/torchaudio/csrc/sox/utils.cpp @@ -1,6 +1,6 @@ #include #include -#include +#include namespace torchaudio { namespace sox_utils { @@ -92,15 +92,15 @@ SoxFormat::operator sox_format_t*() const noexcept { return fd_; } -void validate_input_file(const SoxFormat& sf) { +void validate_input_file(const SoxFormat& sf, bool check_length) { if (static_cast(sf) == nullptr) { throw std::runtime_error("Error loading audio file: failed to open file."); } if (sf->encoding.encoding == SOX_ENCODING_UNKNOWN) { throw std::runtime_error("Error loading audio file: unknown encoding."); } - if (sf->signal.length == 0) { - throw std::runtime_error("Error reading audio file: unkown length."); + if (check_length && sf->signal.length == 0) { + throw std::runtime_error("Error reading audio file: unknown length."); } } diff --git a/torchaudio/csrc/sox_utils.h b/torchaudio/csrc/sox/utils.h similarity index 98% rename from torchaudio/csrc/sox_utils.h rename to torchaudio/csrc/sox/utils.h index c9037e9e2f..ee8d1baa66 100644 --- a/torchaudio/csrc/sox_utils.h +++ b/torchaudio/csrc/sox/utils.h @@ -67,7 +67,7 @@ struct SoxFormat { /// /// Verify that input file is found, has known encoding, and not empty -void validate_input_file(const SoxFormat& sf); +void validate_input_file(const SoxFormat& sf, bool check_length=true); /// /// Verify that input Tensor is 2D, CPU and either uin8, int16, int32 or float32 diff --git a/torchaudio/csrc/transducer.cpp b/torchaudio/csrc/transducer.cpp new file mode 100644 index 0000000000..3ca7a5ebde --- /dev/null +++ b/torchaudio/csrc/transducer.cpp @@ -0,0 +1,93 @@ +#include +#include +#include +#include + +#include +#include "rnnt.h" + +namespace { + +int64_t cpu_rnnt_loss(torch::Tensor acts, + torch::Tensor labels, + torch::Tensor input_lengths, + torch::Tensor label_lengths, + torch::Tensor costs, + torch::Tensor grads, + int64_t blank_label, + int64_t num_threads) { + + int maxT = acts.size(1); + int maxU = acts.size(2); + int minibatch_size = acts.size(0); + int alphabet_size = acts.size(3); + + rnntOptions options; + memset(&options, 0, sizeof(options)); + options.maxT = maxT; + options.maxU = maxU; + options.blank_label = blank_label; + options.batch_first = true; + options.loc = RNNT_CPU; + options.num_threads = num_threads; + + // have to use at least one + options.num_threads = std::max(options.num_threads, (unsigned int) 1); + + size_t cpu_size_bytes = 0; + switch (acts.scalar_type()) { + case torch::ScalarType::Float: + { + get_workspace_size(maxT, maxU, minibatch_size, + false, &cpu_size_bytes); + + std::vector cpu_workspace(cpu_size_bytes / sizeof(float), 0); + + compute_rnnt_loss(acts.data_ptr(), grads.data_ptr(), + labels.data_ptr(), label_lengths.data_ptr(), + input_lengths.data_ptr(), alphabet_size, + minibatch_size, costs.data_ptr(), + cpu_workspace.data(), options); + + return 0; + } + case torch::ScalarType::Double: + { + get_workspace_size(maxT, maxU, minibatch_size, + false, &cpu_size_bytes, + sizeof(double)); + + std::vector cpu_workspace(cpu_size_bytes / sizeof(double), 0); + + compute_rnnt_loss_fp64(acts.data_ptr(), grads.data_ptr(), + labels.data_ptr(), label_lengths.data_ptr(), + input_lengths.data_ptr(), alphabet_size, + minibatch_size, costs.data_ptr(), + cpu_workspace.data(), options); + + return 0; + } + default: + TORCH_CHECK(false, + std::string(__func__) + " not implemented for '" + toString(acts.scalar_type()) + "'" + ); + } + return -1; +} + +} // namespace + +TORCH_LIBRARY_IMPL(torchaudio, CPU, m) { + m.impl("rnnt_loss", &cpu_rnnt_loss); +} + +TORCH_LIBRARY_FRAGMENT(torchaudio, m) { + m.def("rnnt_loss(Tensor acts," + "Tensor labels," + "Tensor input_lengths," + "Tensor label_lengths," + "Tensor costs," + "Tensor grads," + "int blank_label," + "int num_threads) -> int"); +} diff --git a/torchaudio/datasets/commonvoice.py b/torchaudio/datasets/commonvoice.py index d387a8ca2a..75fd84843f 100644 --- a/torchaudio/datasets/commonvoice.py +++ b/torchaudio/datasets/commonvoice.py @@ -1,26 +1,28 @@ -import os import csv +import os import warnings from pathlib import Path from typing import List, Dict, Tuple, Union, Optional -import torchaudio from torch import Tensor from torch.utils.data import Dataset +import torchaudio + def load_commonvoice_item(line: List[str], header: List[str], path: str, - folder_audio: str) -> Tuple[Tensor, int, Dict[str, str]]: + folder_audio: str, + ext_audio: str) -> Tuple[Tensor, int, Dict[str, str]]: # Each line as the following data: # client_id, path, sentence, up_votes, down_votes, age, gender, accent assert header[1] == "path" fileid = line[1] - filename = os.path.join(path, folder_audio, fileid) - + if not filename.endswith(ext_audio): + filename += ext_audio waveform, sample_rate = torchaudio.load(filename) dic = dict(zip(header, line)) @@ -95,7 +97,7 @@ def __getitem__(self, n: int) -> Tuple[Tensor, int, Dict[str, str]]: ``up_votes``, ``down_votes``, ``age``, ``gender`` and ``accent``. """ line = self._walker[n] - return load_commonvoice_item(line, self._header, self._path, self._folder_audio) + return load_commonvoice_item(line, self._header, self._path, self._folder_audio, self._ext_audio) def __len__(self) -> int: return len(self._walker) diff --git a/torchaudio/datasets/utils.py b/torchaudio/datasets/utils.py index c187d0d814..189866374f 100644 --- a/torchaudio/datasets/utils.py +++ b/torchaudio/datasets/utils.py @@ -1,18 +1,15 @@ -import errno import hashlib import logging import os -import sys import tarfile import threading +import urllib +import urllib.request import zipfile -from _io import TextIOWrapper from queue import Queue -from typing import Any, Iterable, List, Optional, Tuple, Union +from typing import Any, Iterable, List, Optional import torch -import urllib -import urllib.request from torch.utils.data import Dataset from torch.utils.model_zoo import tqdm @@ -41,11 +38,11 @@ def stream_url(url: str, req.headers["Range"] = "bytes={}-".format(start_byte) with urllib.request.urlopen(req) as upointer, tqdm( - unit="B", - unit_scale=True, - unit_divisor=1024, - total=url_size, - disable=not progress_bar, + unit="B", + unit_scale=True, + unit_divisor=1024, + total=url_size, + disable=not progress_bar, ) as pbar: num_bytes = 0 @@ -203,42 +200,6 @@ def extract_archive(from_path: str, to_path: Optional[str] = None, overwrite: bo raise NotImplementedError("We currently only support tar.gz, tgz, and zip achives.") -def walk_files(root: str, - suffix: Union[str, Tuple[str]], - prefix: bool = False, - remove_suffix: bool = False) -> Iterable[str]: - """List recursively all files ending with a suffix at a given root - Args: - root (str): Path to directory whose folders need to be listed - suffix (str or tuple): Suffix of the files to match, e.g. '.png' or ('.jpg', '.png'). - It uses the Python "str.endswith" method and is passed directly - prefix (bool, optional): If true, prepends the full path to each result, otherwise - only returns the name of the files found (Default: ``False``) - remove_suffix (bool, optional): If true, removes the suffix to each result defined in suffix, - otherwise will return the result as found (Default: ``False``). - """ - - root = os.path.expanduser(root) - - for dirpath, dirs, files in os.walk(root): - dirs.sort() - # `dirs` is the list used in os.walk function and by sorting it in-place here, we change the - # behavior of os.walk to traverse sub directory alphabetically - # see also - # https://stackoverflow.com/questions/6670029/can-i-force-python3s-os-walk-to-visit-directories-in-alphabetical-order-how#comment71993866_6670926 - files.sort() - for f in files: - if f.endswith(suffix): - - if remove_suffix: - f = f[: -len(suffix)] - - if prefix: - f = os.path.join(dirpath, f) - - yield f - - class _DiskCache(Dataset): """ Wrap a dataset so that, whenever a new item is returned, it is saved to disk. diff --git a/torchaudio/datasets/vctk.py b/torchaudio/datasets/vctk.py index c71962bad8..4e845502d6 100644 --- a/torchaudio/datasets/vctk.py +++ b/torchaudio/datasets/vctk.py @@ -1,11 +1,12 @@ import os import warnings -from typing import Any, Tuple, Union from pathlib import Path +from typing import Tuple, Union -import torchaudio from torch import Tensor from torch.utils.data import Dataset + +import torchaudio from torchaudio.datasets.utils import ( download_url, extract_archive, @@ -66,8 +67,6 @@ class VCTK(Dataset): Giving ``download=True`` will result in error as the dataset is no longer publicly available. downsample (bool, optional): Not used. - transform (callable, optional): Optional transform applied on waveform. (default: ``None``) - target_transform (callable, optional): Optional transform applied on utterance. (default: ``None``) """ _folder_txt = "txt" @@ -81,9 +80,7 @@ def __init__(self, url: str = URL, folder_in_archive: str = FOLDER_IN_ARCHIVE, download: bool = False, - downsample: bool = False, - transform: Any = None, - target_transform: Any = None) -> None: + downsample: bool = False) -> None: if downsample: warnings.warn( @@ -92,17 +89,7 @@ def __init__(self, "and suppress this warning." ) - if transform is not None or target_transform is not None: - warnings.warn( - "In the next version, transforms will not be part of the dataset. " - "Please remove the option `transform=True` and " - "`target_transform=True` to suppress this warning." - ) - self.downsample = downsample - self.transform = transform - self.target_transform = target_transform - # Get string representation of 'root' in case Path object is passed root = os.fspath(root) @@ -149,10 +136,6 @@ def __getitem__(self, n: int) -> Tuple[Tensor, int, str, str, str]: # return item waveform, sample_rate, utterance, speaker_id, utterance_id = item - if self.transform is not None: - waveform = self.transform(waveform) - if self.target_transform is not None: - utterance = self.target_transform(utterance) return waveform, sample_rate, utterance, speaker_id, utterance_id def __len__(self) -> int: @@ -182,12 +165,12 @@ class VCTK_092(Dataset): """ def __init__( - self, - root: str, - mic_id: str = "mic2", - download: bool = False, - url: str = URL, - audio_ext=".flac", + self, + root: str, + mic_id: str = "mic2", + download: bool = False, + url: str = URL, + audio_ext=".flac", ): if mic_id not in ["mic1", "mic2"]: raise RuntimeError( @@ -233,7 +216,7 @@ def __init__( continue utterance_dir = os.path.join(self._txt_dir, speaker_id) for utterance_file in sorted( - f for f in os.listdir(utterance_dir) if f.endswith(".txt") + f for f in os.listdir(utterance_dir) if f.endswith(".txt") ): utterance_id = os.path.splitext(utterance_file)[0] audio_path_mic = os.path.join( diff --git a/torchaudio/datasets/yesno.py b/torchaudio/datasets/yesno.py index 21d67f8ecc..7178b8332c 100644 --- a/torchaudio/datasets/yesno.py +++ b/torchaudio/datasets/yesno.py @@ -1,11 +1,11 @@ import os -import warnings -from typing import Any, List, Tuple, Union from pathlib import Path +from typing import List, Tuple, Union -import torchaudio from torch import Tensor from torch.utils.data import Dataset + +import torchaudio from torchaudio.datasets.utils import ( download_url, extract_archive, @@ -15,7 +15,7 @@ FOLDER_IN_ARCHIVE = "waves_yesno" _CHECKSUMS = { "http://www.openslr.org/resources/1/waves_yesno.tar.gz": - "962ff6e904d2df1126132ecec6978786" + "962ff6e904d2df1126132ecec6978786" } @@ -41,8 +41,6 @@ class YESNO(Dataset): The top-level directory of the dataset. (default: ``"waves_yesno"``) download (bool, optional): Whether to download the dataset if it is not found at root path. (default: ``False``). - transform (callable, optional): Optional transform applied on waveform. (default: ``None``) - target_transform (callable, optional): Optional transform applied on utterance. (default: ``None``) """ _ext_audio = ".wav" @@ -51,19 +49,7 @@ def __init__(self, root: Union[str, Path], url: str = URL, folder_in_archive: str = FOLDER_IN_ARCHIVE, - download: bool = False, - transform: Any = None, - target_transform: Any = None) -> None: - - if transform is not None or target_transform is not None: - warnings.warn( - "In the next version, transforms will not be part of the dataset. " - "Please remove the option `transform=True` and " - "`target_transform=True` to suppress this warning." - ) - - self.transform = transform - self.target_transform = target_transform + download: bool = False) -> None: # Get string representation of 'root' in case Path object is passed root = os.fspath(root) @@ -102,10 +88,6 @@ def __getitem__(self, n: int) -> Tuple[Tensor, int, List[int]]: # return item waveform, sample_rate, labels = item - if self.transform is not None: - waveform = self.transform(waveform) - if self.target_transform is not None: - labels = self.target_transform(labels) return waveform, sample_rate, labels def __len__(self) -> int: diff --git a/torchaudio/functional/functional.py b/torchaudio/functional/functional.py index 3fedf93d09..0c07ec0847 100644 --- a/torchaudio/functional/functional.py +++ b/torchaudio/functional/functional.py @@ -70,30 +70,29 @@ def spectrogram( waveform = waveform.reshape(-1, shape[-1]) # default values are consistent with librosa.core.spectrum._spectrogram - spec_f = torch.view_as_real( - torch.stft( - input=waveform, - n_fft=n_fft, - hop_length=hop_length, - win_length=win_length, - window=window, - center=True, - pad_mode="reflect", - normalized=False, - onesided=True, - return_complex=True, - ) + spec_f = torch.stft( + input=waveform, + n_fft=n_fft, + hop_length=hop_length, + win_length=win_length, + window=window, + center=True, + pad_mode="reflect", + normalized=False, + onesided=True, + return_complex=True, ) # unpack batch - spec_f = spec_f.reshape(shape[:-1] + spec_f.shape[-3:]) + spec_f = spec_f.reshape(shape[:-1] + spec_f.shape[-2:]) if normalized: spec_f /= window.pow(2.).sum().sqrt() if power is not None: - spec_f = complex_norm(spec_f, power=power) - - return spec_f + if power == 1.0: + return spec_f.abs() + return spec_f.abs().pow(power) + return torch.view_as_real(spec_f) def griffinlim( diff --git a/torchaudio/prototype/__init__.py b/torchaudio/prototype/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/torchaudio/prototype/transducer.py b/torchaudio/prototype/transducer.py new file mode 100644 index 0000000000..d08ab6ea17 --- /dev/null +++ b/torchaudio/prototype/transducer.py @@ -0,0 +1,159 @@ +import torch +from torch.autograd import Function +from torch.nn import Module +from torchaudio._internal import ( + module_utils as _mod_utils, +) + +__all__ = ["rnnt_loss", "RNNTLoss"] + + +class _RNNT(Function): + @staticmethod + def forward(ctx, acts, labels, act_lens, label_lens, blank, reduction): + """ + See documentation for RNNTLoss. + """ + + device = acts.device + check_inputs(acts, labels, act_lens, label_lens) + + acts = acts.to("cpu") + labels = labels.to("cpu") + act_lens = act_lens.to("cpu") + label_lens = label_lens.to("cpu") + + loss_func = torch.ops.torchaudio.rnnt_loss + + grads = torch.zeros_like(acts) + minibatch_size = acts.size(0) + costs = torch.zeros(minibatch_size, dtype=acts.dtype) + + loss_func(acts, labels, act_lens, label_lens, costs, grads, blank, 0) + + if reduction in ["sum", "mean"]: + costs = costs.sum().unsqueeze_(-1) + if reduction == "mean": + costs /= minibatch_size + grads /= minibatch_size + + costs = costs.to(device) + ctx.grads = grads.to(device) + + return costs + + @staticmethod + def backward(ctx, grad_output): + grad_output = grad_output.view(-1, 1, 1, 1).to(ctx.grads) + return ctx.grads.mul_(grad_output), None, None, None, None, None + + +@_mod_utils.requires_module("torchaudio._torchaudio") +def rnnt_loss(acts, labels, act_lens, label_lens, blank=0, reduction="mean"): + """Compute the RNN Transducer Loss. + + The RNN Transducer loss (`Graves 2012 `__) extends the CTC loss by defining + a distribution over output sequences of all lengths, and by jointly modelling both input-output and output-output + dependencies. + + The implementation uses `warp-transducer `__. + + Args: + acts (Tensor): Tensor of dimension (batch, time, label, class) containing output from network + before applying ``torch.nn.functional.log_softmax``. + labels (Tensor): Tensor of dimension (batch, max label length) containing the labels padded by zero + act_lens (Tensor): Tensor of dimension (batch) containing the length of each output sequence + label_lens (Tensor): Tensor of dimension (batch) containing the length of each output sequence + blank (int): blank label. (Default: ``0``) + reduction (string): If ``'sum'``, the output losses will be summed. + If ``'mean'``, the output losses will be divided by the target lengths and + then the mean over the batch is taken. If ``'none'``, no reduction will be applied. + (Default: ``'mean'``) + """ + + # NOTE manually done log_softmax for CPU version, + # log_softmax is computed within GPU version. + acts = torch.nn.functional.log_softmax(acts, -1) + return _RNNT.apply(acts, labels, act_lens, label_lens, blank, reduction) + + +@_mod_utils.requires_module("torchaudio._torchaudio") +class RNNTLoss(Module): + """Compute the RNN Transducer Loss. + + The RNN Transducer loss (`Graves 2012 `__) extends the CTC loss by defining + a distribution over output sequences of all lengths, and by jointly modelling both input-output and output-output + dependencies. + + The implementation uses `warp-transducer `__. + + Args: + blank (int): blank label. (Default: ``0``) + reduction (string): If ``'sum'``, the output losses will be summed. + If ``'mean'``, the output losses will be divided by the target lengths and + then the mean over the batch is taken. If ``'none'``, no reduction will be applied. + (Default: ``'mean'``) + """ + + def __init__(self, blank=0, reduction="mean"): + super(RNNTLoss, self).__init__() + self.blank = blank + self.reduction = reduction + self.loss = _RNNT.apply + + def forward(self, acts, labels, act_lens, label_lens): + """ + Args: + acts (Tensor): Tensor of dimension (batch, time, label, class) containing output from network + before applying ``torch.nn.functional.log_softmax``. + labels (Tensor): Tensor of dimension (batch, max label length) containing the labels padded by zero + act_lens (Tensor): Tensor of dimension (batch) containing the length of each output sequence + label_lens (Tensor): Tensor of dimension (batch) containing the length of each output sequence + """ + + # NOTE manually done log_softmax for CPU version, + # log_softmax is computed within GPU version. + acts = torch.nn.functional.log_softmax(acts, -1) + return self.loss(acts, labels, act_lens, label_lens, self.blank, self.reduction) + + +def check_type(var, t, name): + if var.dtype is not t: + raise TypeError("{} must be {}".format(name, t)) + + +def check_contiguous(var, name): + if not var.is_contiguous(): + raise ValueError("{} must be contiguous".format(name)) + + +def check_dim(var, dim, name): + if len(var.shape) != dim: + raise ValueError("{} must be {}D".format(name, dim)) + + +def check_inputs(log_probs, labels, lengths, label_lengths): + check_type(labels, torch.int32, "labels") + check_type(label_lengths, torch.int32, "label_lengths") + check_type(lengths, torch.int32, "lengths") + check_contiguous(log_probs, "log_probs") + check_contiguous(labels, "labels") + check_contiguous(label_lengths, "label_lengths") + check_contiguous(lengths, "lengths") + + if lengths.shape[0] != log_probs.shape[0]: + raise ValueError("must have a length per example.") + if label_lengths.shape[0] != log_probs.shape[0]: + raise ValueError("must have a label length per example.") + + check_dim(log_probs, 4, "log_probs") + check_dim(labels, 2, "labels") + check_dim(lengths, 1, "lengths") + check_dim(label_lengths, 1, "label_lengths") + max_T = torch.max(lengths) + max_U = torch.max(label_lengths) + T, U = log_probs.shape[1:3] + if T != max_T: + raise ValueError("Input length mismatch") + if U != max_U + 1: + raise ValueError("Output length mismatch") diff --git a/torchaudio/sox_effects/sox_effects.py b/torchaudio/sox_effects/sox_effects.py index 82ee613ba0..7534714965 100644 --- a/torchaudio/sox_effects/sox_effects.py +++ b/torchaudio/sox_effects/sox_effects.py @@ -1,4 +1,4 @@ -from typing import List, Tuple +from typing import List, Tuple, Optional import torch @@ -157,6 +157,7 @@ def apply_effects_file( effects: List[List[str]], normalize: bool = True, channels_first: bool = True, + format: Optional[str] = None, ) -> Tuple[torch.Tensor, int]: """Apply sox effects to the audio file and load the resulting data as Tensor @@ -180,6 +181,10 @@ def apply_effects_file( than integer WAV type. channels_first (bool): When True, the returned Tensor has dimension ``[channel, time]``. Otherwise, the returned Tensor's dimension is ``[time, channel]``. + format (str, optional): + Override the format detection with the given format. + Providing the argument might help when libsox can not infer the format + from header or extension, Returns: Tuple[torch.Tensor, int]: Resulting Tensor and sample rate. @@ -249,5 +254,6 @@ def apply_effects_file( """ # Get string representation of 'path' in case Path object is passed path = str(path) - signal = torch.ops.torchaudio.sox_effects_apply_effects_file(path, effects, normalize, channels_first) + signal = torch.ops.torchaudio.sox_effects_apply_effects_file( + path, effects, normalize, channels_first, format) return signal.get_tensor(), signal.get_sample_rate() From 227068af153ec718d62aec755394823f59a30da8 Mon Sep 17 00:00:00 2001 From: Moto Hira Date: Wed, 20 Jan 2021 14:06:25 -0800 Subject: [PATCH 26/73] Import torchaudio #1182 d53e404 Summary: Import torchaudio #1182 d53e404 Reviewed By: datumbox Differential Revision: D25975367 fbshipit-source-id: feac3187a82b0e3de23562fde11fcfc5bb13461d --- .circleci/config.yml | 6 +- .circleci/config.yml.in | 6 +- .circleci/unittest/linux/scripts/run_test.sh | 2 +- .flake8 | 2 +- build_tools/setup_helpers/extension.py | 11 + docs/source/index.rst | 1 + docs/source/transducer.rst | 23 ++ packaging/pkg_helpers.bash | 9 +- setup.py | 5 +- .../functional/functional_cpu_test.py | 11 +- .../librosa_compatibility_test.py | 2 - .../soundfile_backend/save_test.py | 42 ++- .../sox_io_backend/save_test.py | 86 ++++++ torchaudio/backend/_soundfile_backend.py | 18 +- torchaudio/backend/sox_io_backend.py | 44 +-- torchaudio/compliance/kaldi.py | 265 +++++------------- torchaudio/csrc/pybind.cpp | 4 + torchaudio/csrc/sox/effects.cpp | 10 +- torchaudio/csrc/sox/effects_chain.cpp | 79 +++++- torchaudio/csrc/sox/effects_chain.h | 6 + torchaudio/csrc/sox/io.cpp | 100 ++++++- torchaudio/csrc/sox/io.h | 17 +- torchaudio/csrc/sox/utils.cpp | 46 +-- torchaudio/csrc/sox/utils.h | 8 +- torchaudio/datasets/yesno.py | 65 ++--- tox.ini | 4 - 26 files changed, 536 insertions(+), 336 deletions(-) create mode 100644 docs/source/transducer.rst delete mode 100644 tox.ini diff --git a/.circleci/config.yml b/.circleci/config.yml index d51bb3ca96..c40054d0e3 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -112,7 +112,7 @@ jobs: - persist_to_workspace: root: third_party paths: - - archives + - sox/archives binary_linux_wheel: <<: *binary_common @@ -411,7 +411,6 @@ jobs: paths: - conda - env - - third_party/install - run: name: Install torchaudio command: .circleci/unittest/linux/scripts/install.sh @@ -456,7 +455,6 @@ jobs: paths: - conda - env - - third_party/install - run: name: Install torchaudio command: docker run -t --gpus all -e UPLOAD_CHANNEL -v $PWD:$PWD -w $PWD "${image_name}" .circleci/unittest/linux/scripts/install.sh @@ -569,7 +567,6 @@ jobs: paths: - conda - env - - third_party/install - run: name: Install torchaudio command: .circleci/unittest/linux/scripts/install.sh @@ -606,7 +603,6 @@ jobs: paths: - conda - env - - third_party/install - run: name: Run style check command: .circleci/unittest/linux/scripts/run_style_checks.sh diff --git a/.circleci/config.yml.in b/.circleci/config.yml.in index 9f6f41a379..535729d72e 100644 --- a/.circleci/config.yml.in +++ b/.circleci/config.yml.in @@ -112,7 +112,7 @@ jobs: - persist_to_workspace: root: third_party paths: - - archives + - sox/archives binary_linux_wheel: <<: *binary_common @@ -411,7 +411,6 @@ jobs: paths: - conda - env - - third_party/install - run: name: Install torchaudio command: .circleci/unittest/linux/scripts/install.sh @@ -456,7 +455,6 @@ jobs: paths: - conda - env - - third_party/install - run: name: Install torchaudio command: docker run -t --gpus all -e UPLOAD_CHANNEL -v $PWD:$PWD -w $PWD "${image_name}" .circleci/unittest/linux/scripts/install.sh @@ -569,7 +567,6 @@ jobs: paths: - conda - env - - third_party/install - run: name: Install torchaudio command: .circleci/unittest/linux/scripts/install.sh @@ -606,7 +603,6 @@ jobs: paths: - conda - env - - third_party/install - run: name: Run style check command: .circleci/unittest/linux/scripts/run_style_checks.sh diff --git a/.circleci/unittest/linux/scripts/run_test.sh b/.circleci/unittest/linux/scripts/run_test.sh index 2f9c10476d..e9016d266c 100755 --- a/.circleci/unittest/linux/scripts/run_test.sh +++ b/.circleci/unittest/linux/scripts/run_test.sh @@ -17,4 +17,4 @@ declare -a args=( ) cd test -pytest "${args[@]}" torchaudio_unittest -k "not fileobj" +pytest "${args[@]}" torchaudio_unittest diff --git a/.flake8 b/.flake8 index 9d0eaed2bd..b4a5069f16 100644 --- a/.flake8 +++ b/.flake8 @@ -1,4 +1,4 @@ [flake8] max-line-length = 120 -ignore = E305,E402,E721,E741,F401,F403,F405,F999,W503,W504 +ignore = E305,E402,E721,E741,F401,F403,F405,W503,W504,F999 exclude = build,docs/source,_ext,third_party diff --git a/build_tools/setup_helpers/extension.py b/build_tools/setup_helpers/extension.py index 0dc306f07e..7f0ba7a14f 100644 --- a/build_tools/setup_helpers/extension.py +++ b/build_tools/setup_helpers/extension.py @@ -3,6 +3,7 @@ import subprocess from pathlib import Path +import torch from torch.utils.cpp_extension import ( CppExtension, BuildExtension as TorchBuildExtension @@ -109,12 +110,22 @@ def _get_libraries(): return [] if _BUILD_SOX else ['sox'] +def _get_cxx11_abi(): + try: + value = int(torch._C._GLIBCXX_USE_CXX11_ABI) + except ImportError: + value = 0 + return f'-D_GLIBCXX_USE_CXX11_ABI={value}' + + def _build_third_party(base_build_dir): build_dir = os.path.join(base_build_dir, 'third_party') os.makedirs(build_dir, exist_ok=True) subprocess.run( args=[ 'cmake', + f"-DCMAKE_CXX_FLAGS='{_get_cxx11_abi()}'", + '-DCMAKE_VERBOSE_MAKEFILE:BOOL=ON', f'-DCMAKE_INSTALL_PREFIX={_TP_INSTALL_DIR}', f'-DBUILD_SOX={"ON" if _BUILD_SOX else "OFF"}', f'-DBUILD_TRANSDUCER={"ON" if _BUILD_TRANSDUCER else "OFF"}', diff --git a/docs/source/index.rst b/docs/source/index.rst index 596a636b1b..49ffb9af22 100644 --- a/docs/source/index.rst +++ b/docs/source/index.rst @@ -39,6 +39,7 @@ The :mod:`torchaudio` package consists of I/O, popular datasets and common audio compliance.kaldi kaldi_io utils + transducer .. toctree:: diff --git a/docs/source/transducer.rst b/docs/source/transducer.rst new file mode 100644 index 0000000000..505ab0187c --- /dev/null +++ b/docs/source/transducer.rst @@ -0,0 +1,23 @@ +.. role:: hidden + :class: hidden-section + +torchaudio.prototype.transducer +=============================== + +.. currentmodule:: torchaudio.prototype.transducer + +.. note:: + + The RNN transducer loss is a prototype feature, see `here `_ to learn more about the nomenclature. It is only available within the nightlies, and also needs to be imported explicitly using: :code:`from torchaudio.prototype.transducer import rnnt_loss, RNNTLoss`. + +rnnt_loss +--------- + +.. autofunction:: rnnt_loss + +:hidden:`RNNTLoss` +~~~~~~~~~~~~~~~~~~ + +.. autoclass:: RNNTLoss + + .. automethod:: forward diff --git a/packaging/pkg_helpers.bash b/packaging/pkg_helpers.bash index 635bfa3a14..36760b9484 100644 --- a/packaging/pkg_helpers.bash +++ b/packaging/pkg_helpers.bash @@ -162,13 +162,8 @@ setup_pip_pytorch_version() { # Install latest prerelease version of torch, per our nightlies, consistent # with the requested cuda version pip_install --pre torch -f "https://download.pytorch.org/whl/nightly/${WHEEL_DIR}torch_nightly.html" - if [[ "$CUDA_VERSION" == "cpu" ]]; then - # CUDA and CPU are ABI compatible on the CPU-only parts, so strip - # in this case - export PYTORCH_VERSION="$(pip show torch | grep ^Version: | sed 's/Version: *//' | sed 's/+.\+//')" - else - export PYTORCH_VERSION="$(pip show torch | grep ^Version: | sed 's/Version: *//')" - fi + # CUDA and CPU are ABI compatible on the CPU-only parts, so strip in this case + export PYTORCH_VERSION="$(pip show torch | grep ^Version: | sed 's/Version: *//' | sed 's/+.\+//')" else pip_install "torch==$PYTORCH_VERSION$PYTORCH_VERSION_SUFFIX" \ -f https://download.pytorch.org/whl/torch_stable.html \ diff --git a/setup.py b/setup.py index 8168472ecf..8ecc41c1cc 100644 --- a/setup.py +++ b/setup.py @@ -73,8 +73,9 @@ def run(self): "Operating System :: Microsoft :: Windows", "Operating System :: POSIX", "Programming Language :: C++", - "Programming Language :: Python :: 2.7", - "Programming Language :: Python :: 3", + "Programming Language :: Python :: 3.6", + "Programming Language :: Python :: 3.7", + "Programming Language :: Python :: 3.8", "Programming Language :: Python :: Implementation :: CPython", "Topic :: Multimedia :: Sound/Audio", "Topic :: Scientific/Engineering :: Artificial Intelligence" diff --git a/test/torchaudio_unittest/functional/functional_cpu_test.py b/test/torchaudio_unittest/functional/functional_cpu_test.py index 4073654011..c4ba42391d 100644 --- a/test/torchaudio_unittest/functional/functional_cpu_test.py +++ b/test/torchaudio_unittest/functional/functional_cpu_test.py @@ -1,10 +1,10 @@ import math +import warnings import torch import torchaudio import torchaudio.functional as F from parameterized import parameterized -import pytest import itertools from torchaudio_unittest import common_utils @@ -33,17 +33,20 @@ class TestSpectrogramFloat64(Spectrogram, common_utils.PytorchTestCase): class TestCreateFBMatrix(common_utils.TorchaudioTestCase): def test_no_warning_high_n_freq(self): - with pytest.warns(None) as w: + with warnings.catch_warnings(record=True) as w: + warnings.simplefilter("always") F.create_fb_matrix(288, 0, 8000, 128, 16000) assert len(w) == 0 def test_no_warning_low_n_mels(self): - with pytest.warns(None) as w: + with warnings.catch_warnings(record=True) as w: + warnings.simplefilter("always") F.create_fb_matrix(201, 0, 8000, 89, 16000) assert len(w) == 0 def test_warning(self): - with pytest.warns(None) as w: + with warnings.catch_warnings(record=True) as w: + warnings.simplefilter("always") F.create_fb_matrix(201, 0, 8000, 128, 16000) assert len(w) == 1 diff --git a/test/torchaudio_unittest/librosa_compatibility_test.py b/test/torchaudio_unittest/librosa_compatibility_test.py index e1ef80fa79..92d5baff06 100644 --- a/test/torchaudio_unittest/librosa_compatibility_test.py +++ b/test/torchaudio_unittest/librosa_compatibility_test.py @@ -17,8 +17,6 @@ import librosa import scipy -import pytest - from torchaudio_unittest import common_utils diff --git a/test/torchaudio_unittest/soundfile_backend/save_test.py b/test/torchaudio_unittest/soundfile_backend/save_test.py index a99c69b0c8..5c36e0d126 100644 --- a/test/torchaudio_unittest/soundfile_backend/save_test.py +++ b/test/torchaudio_unittest/soundfile_backend/save_test.py @@ -1,9 +1,9 @@ +import io import itertools from unittest.mock import patch from torchaudio._internal import module_utils as _mod_utils from torchaudio.backend import _soundfile_backend as soundfile_backend -from parameterized import parameterized from torchaudio_unittest.common_utils import ( TempDirMixin, @@ -209,3 +209,43 @@ def test_channels_first(self, channels_first): found = load_wav(path)[0] expected = data if channels_first else data.transpose(1, 0) self.assertEqual(found, expected, atol=1e-4, rtol=1e-8) + + +@skipIfNoModule("soundfile") +class TestFileObject(TempDirMixin, PytorchTestCase): + def _test_fileobj(self, ext): + """Saving audio to file-like object works""" + sample_rate = 16000 + path = self.get_temp_path(f'test.{ext}') + + subtype = 'FLOAT' if ext == 'wav' else None + data = get_wav_data('float32', num_channels=2) + soundfile.write(path, data.numpy().T, sample_rate, subtype=subtype) + expected = soundfile.read(path, dtype='float32')[0] + + fileobj = io.BytesIO() + soundfile_backend.save(fileobj, data, sample_rate, format=ext) + fileobj.seek(0) + found, sr = soundfile.read(fileobj, dtype='float32') + + assert sr == sample_rate + self.assertEqual(expected, found) + + def test_fileobj_wav(self): + """Saving audio via file-like object works""" + self._test_fileobj('wav') + + @skipIfFormatNotSupported("FLAC") + def test_fileobj_flac(self): + """Saving audio via file-like object works""" + self._test_fileobj('flac') + + @skipIfFormatNotSupported("NIST") + def test_fileobj_nist(self): + """Saving audio via file-like object works""" + self._test_fileobj('NIST') + + @skipIfFormatNotSupported("OGG") + def test_fileobj_ogg(self): + """Saving audio via file-like object works""" + self._test_fileobj('OGG') diff --git a/test/torchaudio_unittest/sox_io_backend/save_test.py b/test/torchaudio_unittest/sox_io_backend/save_test.py index b0ee25e01c..3f2faff6d4 100644 --- a/test/torchaudio_unittest/sox_io_backend/save_test.py +++ b/test/torchaudio_unittest/sox_io_backend/save_test.py @@ -1,3 +1,4 @@ +import io import itertools from torchaudio.backend import sox_io_backend @@ -417,3 +418,88 @@ def test_tensor_preserve(self, dtype): sox_io_backend.save(path, data, 8000) self.assertEqual(data, expected) + + +@skipIfNoExtension +@skipIfNoExec('sox') +class TestFileObject(SaveTestBase): + """ + We campare the result of file-like object input against file path input because + `save` function is rigrously tested for file path inputs to match libsox's result, + """ + @parameterized.expand([ + ('wav', None), + ('mp3', 128), + ('mp3', 320), + ('flac', 0), + ('flac', 5), + ('flac', 8), + ('vorbis', -1), + ('vorbis', 10), + ('amb', None), + ]) + def test_fileobj(self, ext, compression): + """Saving audio to file object returns the same result as via file path.""" + sample_rate = 16000 + dtype = 'float32' + num_channels = 2 + num_frames = 16000 + channels_first = True + + data = get_wav_data(dtype, num_channels, num_frames=num_frames) + + ref_path = self.get_temp_path(f'reference.{ext}') + res_path = self.get_temp_path(f'test.{ext}') + sox_io_backend.save( + ref_path, data, channels_first=channels_first, + sample_rate=sample_rate, compression=compression) + with open(res_path, 'wb') as fileobj: + sox_io_backend.save( + fileobj, data, channels_first=channels_first, + sample_rate=sample_rate, compression=compression, format=ext) + + expected_data, _ = sox_io_backend.load(ref_path) + data, sr = sox_io_backend.load(res_path) + + assert sample_rate == sr + self.assertEqual(expected_data, data) + + @parameterized.expand([ + ('wav', None), + ('mp3', 128), + ('mp3', 320), + ('flac', 0), + ('flac', 5), + ('flac', 8), + ('vorbis', -1), + ('vorbis', 10), + ('amb', None), + ]) + def test_bytesio(self, ext, compression): + """Saving audio to BytesIO object returns the same result as via file path.""" + sample_rate = 16000 + dtype = 'float32' + num_channels = 2 + num_frames = 16000 + channels_first = True + + data = get_wav_data(dtype, num_channels, num_frames=num_frames) + + ref_path = self.get_temp_path(f'reference.{ext}') + res_path = self.get_temp_path(f'test.{ext}') + sox_io_backend.save( + ref_path, data, channels_first=channels_first, + sample_rate=sample_rate, compression=compression) + fileobj = io.BytesIO() + sox_io_backend.save( + fileobj, data, channels_first=channels_first, + sample_rate=sample_rate, compression=compression, format=ext) + fileobj.seek(0) + with open(res_path, 'wb') as file_: + file_.write(fileobj.read()) + + expected_data, _ = sox_io_backend.load(ref_path) + data, sr = sox_io_backend.load(res_path) + + assert sample_rate == sr + self.assertEqual(expected_data, data) diff --git a/torchaudio/backend/_soundfile_backend.py b/torchaudio/backend/_soundfile_backend.py index 719224b827..3366780bdb 100644 --- a/torchaudio/backend/_soundfile_backend.py +++ b/torchaudio/backend/_soundfile_backend.py @@ -138,6 +138,7 @@ def save( sample_rate: int, channels_first: bool = True, compression: Optional[float] = None, + format: Optional[str] = None, ): """Save audio data to file. @@ -168,6 +169,9 @@ def save( otherwise ``[time, channel]``. compression (Optional[float]): Not used. It is here only for interface compatibility reson with "sox_io" backend. + format (str, optional): + Output audio format. This is required when the output audio format cannot be infered from + ``filepath``, (such as file extension or ``name`` attribute of the given file object). """ if src.ndim != 2: raise ValueError(f"Expected 2D Tensor, got {src.ndim}D.") @@ -176,8 +180,13 @@ def save( '`save` function of "soundfile" backend does not support "compression" parameter. ' "The argument is silently ignored." ) + if hasattr(filepath, 'write'): + if format is None: + raise RuntimeError('`format` is required when saving to file object.') + ext = format + else: + ext = str(filepath).split(".")[-1].lower() - ext = str(filepath).split(".")[-1].lower() if ext != "wav": subtype = None elif src.dtype == torch.uint8: @@ -193,17 +202,16 @@ def save( else: raise ValueError(f"Unsupported dtype for WAV: {src.dtype}") - format_ = None # sph is a extension used in TED-LIUM but soundfile does not recognize it as NIST format, # so we extend the extensions manually here - if ext in ["nis", "nist", "sph"]: - format_ = "NIST" + if ext in ["nis", "nist", "sph"] and format is None: + format = "NIST" if channels_first: src = src.t() soundfile.write( - file=filepath, data=src, samplerate=sample_rate, subtype=subtype, format=format_ + file=filepath, data=src, samplerate=sample_rate, subtype=subtype, format=format ) diff --git a/torchaudio/backend/sox_io_backend.py b/torchaudio/backend/sox_io_backend.py index 1e6d417cb8..18296ef7e2 100644 --- a/torchaudio/backend/sox_io_backend.py +++ b/torchaudio/backend/sox_io_backend.py @@ -134,6 +134,25 @@ def load( return signal.get_tensor(), signal.get_sample_rate() +@torch.jit.unused +def _save( + filepath: str, + src: torch.Tensor, + sample_rate: int, + channels_first: bool = True, + compression: Optional[float] = None, + format: Optional[str] = None, +): + if hasattr(filepath, 'write'): + if format is None: + raise RuntimeError('`format` is required when saving to file object.') + torchaudio._torchaudio.save_audio_fileobj( + filepath, src, sample_rate, channels_first, compression, format) + else: + torch.ops.torchaudio.sox_io_save_audio_file( + os.fspath(filepath), src, sample_rate, channels_first, compression, format) + + @_mod_utils.requires_module('torchaudio._torchaudio') def save( filepath: str, @@ -141,6 +160,7 @@ def save( sample_rate: int, channels_first: bool = True, compression: Optional[float] = None, + format: Optional[str] = None, ): """Save audio data to file. @@ -184,23 +204,15 @@ def save( | and lowest quality. Default: ``3``. See the detail at http://sox.sourceforge.net/soxformat.html. + format (str, optional): + Output audio format. This is required when the output audio format cannot be infered from + ``filepath``, (such as file extension or ``name`` attribute of the given file object). """ - # Cast to str in case type is `pathlib.Path` - filepath = str(filepath) - if compression is None: - ext = str(filepath).split('.')[-1].lower() - if ext in ['wav', 'sph', 'amb', 'amr-nb']: - compression = 0. - elif ext == 'mp3': - compression = -4.5 - elif ext == 'flac': - compression = 8. - elif ext in ['ogg', 'vorbis']: - compression = 3. - else: - raise RuntimeError(f'Unsupported file type: "{ext}"') - signal = torch.classes.torchaudio.TensorSignal(src, sample_rate, channels_first) - torch.ops.torchaudio.sox_io_save_audio_file(filepath, signal, compression) + if not torch.jit.is_scripting(): + _save(filepath, src, sample_rate, channels_first, compression, format) + return + torch.ops.torchaudio.sox_io_save_audio_file( + filepath, src, sample_rate, channels_first, compression, format) @_mod_utils.requires_module('torchaudio._torchaudio') diff --git a/torchaudio/compliance/kaldi.py b/torchaudio/compliance/kaldi.py index afabebeb6a..5b47ef3350 100644 --- a/torchaudio/compliance/kaldi.py +++ b/torchaudio/compliance/kaldi.py @@ -3,6 +3,7 @@ import math import torch from torch import Tensor +from torch.nn import functional as F import torchaudio import torchaudio._internal.fft @@ -752,141 +753,54 @@ def mfcc( return feature -def _get_LR_indices_and_weights(orig_freq: float, - new_freq: float, - output_samples_in_unit: int, - window_width: float, - lowpass_cutoff: float, - lowpass_filter_width: int, - device: torch.device, - dtype: int) -> Tuple[Tensor, Tensor]: - r"""Based on LinearResample::SetIndexesAndWeights where it retrieves the weights for - resampling as well as the indices in which they are valid. LinearResample (LR) means - that the output signal is at linearly spaced intervals (i.e the output signal has a - frequency of ``new_freq``). It uses sinc/bandlimited interpolation to upsample/downsample - the signal. - - The reason why the same filter is not used for multiple convolutions is because the - sinc function could sampled at different points in time. For example, suppose - a signal is sampled at the timestamps (seconds) - 0 16 32 - and we want it to be sampled at the timestamps (seconds) - 0 5 10 15 20 25 30 35 - at the timestamp of 16, the delta timestamps are - 16 11 6 1 4 9 14 19 - at the timestamp of 32, the delta timestamps are - 32 27 22 17 12 8 2 3 - - As we can see from deltas, the sinc function is sampled at different points of time - assuming the center of the sinc function is at 0, 16, and 32 (the deltas [..., 6, 1, 4, ....] - for 16 vs [...., 2, 3, ....] for 32) - - Example, one case is when the ``orig_freq`` and ``new_freq`` are multiples of each other then - there needs to be one filter. - - A windowed filter function (i.e. Hanning * sinc) because the ideal case of sinc function - has infinite support (non-zero for all values) so instead it is truncated and multiplied by - a window function which gives it less-than-perfect rolloff [1]. - - [1] Chapter 16: Windowed-Sinc Filters, https://www.dspguide.com/ch16/1.htm - - Args: - orig_freq (float): The original frequency of the signal - new_freq (float): The desired frequency - output_samples_in_unit (int): The number of output samples in the smallest repeating unit: - num_samp_out = new_freq / Gcd(orig_freq, new_freq) - window_width (float): The width of the window which is nonzero - lowpass_cutoff (float): The filter cutoff in Hz. The filter cutoff needs to be less - than samp_rate_in_hz/2 and less than samp_rate_out_hz/2. - lowpass_filter_width (int): Controls the sharpness of the filter, more == sharper but less - efficient. We suggest around 4 to 10 for normal use - - Returns: - (Tensor, Tensor): A tuple of ``min_input_index`` (which is the minimum indices - where the window is valid, size (``output_samples_in_unit``)) and ``weights`` (which is the weights - which correspond with min_input_index, size (``output_samples_in_unit``, ``max_weight_width``)). - """ - assert lowpass_cutoff < min(orig_freq, new_freq) / 2 - output_t = torch.arange(0., output_samples_in_unit, device=device, dtype=dtype) / new_freq - min_t = output_t - window_width - max_t = output_t + window_width - - min_input_index = torch.ceil(min_t * orig_freq) # size (output_samples_in_unit) - max_input_index = torch.floor(max_t * orig_freq) # size (output_samples_in_unit) - num_indices = max_input_index - min_input_index + 1 # size (output_samples_in_unit) - - max_weight_width = num_indices.max() - # create a group of weights of size (output_samples_in_unit, max_weight_width) - j = torch.arange(max_weight_width, device=device, dtype=dtype).unsqueeze(0) - input_index = min_input_index.unsqueeze(1) + j - delta_t = (input_index / orig_freq) - output_t.unsqueeze(1) - - weights = torch.zeros_like(delta_t) - inside_window_indices = delta_t.abs().lt(window_width) - # raised-cosine (Hanning) window with width `window_width` - weights[inside_window_indices] = 0.5 * (1 + torch.cos(2 * math.pi * lowpass_cutoff / - lowpass_filter_width * delta_t[inside_window_indices])) - - t_eq_zero_indices = delta_t.eq(0.0) - t_not_eq_zero_indices = ~t_eq_zero_indices - # sinc filter function - weights[t_not_eq_zero_indices] *= torch.sin( - 2 * math.pi * lowpass_cutoff * delta_t[t_not_eq_zero_indices]) / (math.pi * delta_t[t_not_eq_zero_indices]) - # limit of the function at t = 0 - weights[t_eq_zero_indices] *= 2 * lowpass_cutoff - - weights /= orig_freq # size (output_samples_in_unit, max_weight_width) - return min_input_index, weights - - -def _lcm(a: int, b: int) -> int: - return abs(a * b) // math.gcd(a, b) - - -def _get_num_LR_output_samples(input_num_samp: int, - samp_rate_in: float, - samp_rate_out: float) -> int: - r"""Based on LinearResample::GetNumOutputSamples. LinearResample (LR) means that - the output signal is at linearly spaced intervals (i.e the output signal has a - frequency of ``new_freq``). It uses sinc/bandlimited interpolation to upsample/downsample - the signal. - - Args: - input_num_samp (int): The number of samples in the input - samp_rate_in (float): The original frequency of the signal - samp_rate_out (float): The desired frequency - - Returns: - int: The number of output samples - """ - # For exact computation, we measure time in "ticks" of 1.0 / tick_freq, - # where tick_freq is the least common multiple of samp_rate_in and - # samp_rate_out. - samp_rate_in = int(samp_rate_in) - samp_rate_out = int(samp_rate_out) - - tick_freq = _lcm(samp_rate_in, samp_rate_out) - ticks_per_input_period = tick_freq // samp_rate_in - - # work out the number of ticks in the time interval - # [ 0, input_num_samp/samp_rate_in ). - interval_length_in_ticks = input_num_samp * ticks_per_input_period - if interval_length_in_ticks <= 0: - return 0 - ticks_per_output_period = tick_freq // samp_rate_out - # Get the last output-sample in the closed interval, i.e. replacing [ ) with - # [ ]. Note: integer division rounds down. See - # http://en.wikipedia.org/wiki/Interval_(mathematics) for an explanation of - # the notation. - last_output_samp = interval_length_in_ticks // ticks_per_output_period - # We need the last output-sample in the open interval, so if it takes us to - # the end of the interval exactly, subtract one. - if last_output_samp * ticks_per_output_period == interval_length_in_ticks: - last_output_samp -= 1 - # First output-sample index is zero, so the number of output samples - # is the last output-sample plus one. - num_output_samp = last_output_samp + 1 - return num_output_samp +def _get_sinc_resample_kernel(orig_freq: int, new_freq: int, lowpass_filter_width: int, + device: torch.device, dtype: torch.dtype): + assert lowpass_filter_width > 0 + kernels = [] + base_freq = min(orig_freq, new_freq) + # This will perform antialiasing filtering by removing the highest frequencies. + # At first I thought I only needed this when downsampling, but when upsampling + # you will get edge artifacts without this, as the edge is equivalent to zero padding, + # which will add high freq artifacts. + base_freq *= 0.99 + + # The key idea of the algorithm is that x(t) can be exactly reconstructed from x[i] (tensor) + # using the sinc interpolation formula: + # x(t) = sum_i x[i] sinc(pi * orig_freq * (i / orig_freq - t)) + # We can then sample the function x(t) with a different sample rate: + # y[j] = x(j / new_freq) + # or, + # y[j] = sum_i x[i] sinc(pi * orig_freq * (i / orig_freq - j / new_freq)) + + # We see here that y[j] is the convolution of x[i] with a specific filter, for which + # we take an FIR approximation, stopping when we see at least `lowpass_filter_width` zeros crossing. + # But y[j+1] is going to have a different set of weights and so on, until y[j + new_freq]. + # Indeed: + # y[j + new_freq] = sum_i x[i] sinc(pi * orig_freq * ((i / orig_freq - (j + new_freq) / new_freq)) + # = sum_i x[i] sinc(pi * orig_freq * ((i - orig_freq) / orig_freq - j / new_freq)) + # = sum_i x[i + orig_freq] sinc(pi * orig_freq * (i / orig_freq - j / new_freq)) + # so y[j+new_freq] uses the same filter as y[j], but on a shifted version of x by `orig_freq`. + # This will explain the F.conv1d after, with a stride of orig_freq. + width = math.ceil(lowpass_filter_width * orig_freq / base_freq) + # If orig_freq is still big after GCD reduction, most filters will be very unbalanced, i.e., + # they will have a lot of almost zero values to the left or to the right... + # There is probably a way to evaluate those filters more efficiently, but this is kept for + # future work. + idx = torch.arange(-width, width + orig_freq, device=device, dtype=dtype) + + for i in range(new_freq): + t = (-i / new_freq + idx / orig_freq) * base_freq + t = t.clamp_(-lowpass_filter_width, lowpass_filter_width) + t *= math.pi + # we do not use torch.hann_window here as we need to evaluate the window + # at spectifics positions, not over a regular grid. + window = torch.cos(t / lowpass_filter_width / 2)**2 + kernel = torch.where(t == 0, torch.tensor(1.).to(t), torch.sin(t) / t) + kernel.mul_(window) + kernels.append(kernel) + + scale = base_freq / orig_freq + return torch.stack(kernels).view(new_freq, 1, -1).mul_(scale), width def resample_waveform(waveform: Tensor, @@ -912,72 +826,21 @@ def resample_waveform(waveform: Tensor, Returns: Tensor: The waveform at the new frequency """ - device, dtype = waveform.device, waveform.dtype - assert waveform.dim() == 2 assert orig_freq > 0.0 and new_freq > 0.0 - min_freq = min(orig_freq, new_freq) - lowpass_cutoff = 0.99 * 0.5 * min_freq - - assert lowpass_cutoff * 2 <= min_freq - - base_freq = math.gcd(int(orig_freq), int(new_freq)) - input_samples_in_unit = int(orig_freq) // base_freq - output_samples_in_unit = int(new_freq) // base_freq - - window_width = lowpass_filter_width / (2.0 * lowpass_cutoff) - first_indices, weights = _get_LR_indices_and_weights( - orig_freq, new_freq, output_samples_in_unit, - window_width, lowpass_cutoff, lowpass_filter_width, device, dtype) - - assert first_indices.dim() == 1 - # TODO figure a better way to do this. conv1d reaches every element i*stride + padding - # all the weights have the same stride but have different padding. - # Current implementation takes the input and applies the various padding before - # doing a conv1d for that specific weight. - conv_stride = input_samples_in_unit - conv_transpose_stride = output_samples_in_unit - num_channels, wave_len = waveform.size() - window_size = weights.size(1) - tot_output_samp = _get_num_LR_output_samples(wave_len, orig_freq, new_freq) - output = torch.zeros((num_channels, tot_output_samp), - device=device, dtype=dtype) - # eye size: (num_channels, num_channels, 1) - eye = torch.eye(num_channels, device=device, dtype=dtype).unsqueeze(2) - for i in range(first_indices.size(0)): - wave_to_conv = waveform - first_index = int(first_indices[i].item()) - if first_index >= 0: - # trim the signal as the filter will not be applied before the first_index - wave_to_conv = wave_to_conv[..., first_index:] - - # pad the right of the signal to allow partial convolutions meaning compute - # values for partial windows (e.g. end of the window is outside the signal length) - max_unit_index = (tot_output_samp - 1) // output_samples_in_unit - end_index_of_last_window = max_unit_index * conv_stride + window_size - current_wave_len = wave_len - first_index - right_padding = max(0, end_index_of_last_window + 1 - current_wave_len) - - left_padding = max(0, -first_index) - if left_padding != 0 or right_padding != 0: - wave_to_conv = torch.nn.functional.pad(wave_to_conv, (left_padding, right_padding)) - - conv_wave = torch.nn.functional.conv1d( - wave_to_conv.unsqueeze(0), weights[i].repeat(num_channels, 1, 1), - stride=conv_stride, groups=num_channels) - - # we want conv_wave[:, i] to be at output[:, i + n*conv_transpose_stride] - dilated_conv_wave = torch.nn.functional.conv_transpose1d( - conv_wave, eye, stride=conv_transpose_stride).squeeze(0) - - # pad dilated_conv_wave so it reaches the output length if needed. - dialated_conv_wave_len = dilated_conv_wave.size(-1) - left_padding = i - right_padding = max(0, tot_output_samp - (left_padding + dialated_conv_wave_len)) - dilated_conv_wave = torch.nn.functional.pad( - dilated_conv_wave, (left_padding, right_padding))[..., :tot_output_samp] - - output += dilated_conv_wave - - return output + orig_freq = int(orig_freq) + new_freq = int(new_freq) + gcd = math.gcd(orig_freq, new_freq) + orig_freq = orig_freq // gcd + new_freq = new_freq // gcd + + kernel, width = _get_sinc_resample_kernel(orig_freq, new_freq, lowpass_filter_width, + waveform.device, waveform.dtype) + + num_wavs, length = waveform.shape + waveform = F.pad(waveform, (width, width + orig_freq)) + resampled = F.conv1d(waveform[:, None], kernel, stride=orig_freq) + resampled = resampled.transpose(1, 2).reshape(num_wavs, -1) + target_length = int(math.ceil(new_freq * length / orig_freq)) + return resampled[..., :target_length] diff --git a/torchaudio/csrc/pybind.cpp b/torchaudio/csrc/pybind.cpp index caf9ad9b19..eb8c30b96a 100644 --- a/torchaudio/csrc/pybind.cpp +++ b/torchaudio/csrc/pybind.cpp @@ -100,4 +100,8 @@ PYBIND11_MODULE(_torchaudio, m) { "load_audio_fileobj", &torchaudio::sox_io::load_audio_fileobj, "Load audio from file object."); + m.def( + "save_audio_fileobj", + &torchaudio::sox_io::save_audio_fileobj, + "Save audio to file obj."); } diff --git a/torchaudio/csrc/sox/effects.cpp b/torchaudio/csrc/sox/effects.cpp index ffc85b92ed..03f06c2602 100644 --- a/torchaudio/csrc/sox/effects.cpp +++ b/torchaudio/csrc/sox/effects.cpp @@ -59,8 +59,8 @@ c10::intrusive_ptr apply_effects_tensor( // Create SoxEffectsChain const auto dtype = in_tensor.dtype(); torchaudio::sox_effects_chain::SoxEffectsChain chain( - /*input_encoding=*/get_encodinginfo("wav", dtype, 0.), - /*output_encoding=*/get_encodinginfo("wav", dtype, 0.)); + /*input_encoding=*/get_encodinginfo("wav", dtype), + /*output_encoding=*/get_encodinginfo("wav", dtype)); // Prepare output buffer std::vector out_buffer; @@ -112,7 +112,7 @@ c10::intrusive_ptr apply_effects_file( // Create and run SoxEffectsChain torchaudio::sox_effects_chain::SoxEffectsChain chain( /*input_encoding=*/sf->encoding, - /*output_encoding=*/get_encodinginfo("wav", dtype, 0.)); + /*output_encoding=*/get_encodinginfo("wav", dtype)); chain.addInputFile(sf); for (const auto& effect : effects) { @@ -163,7 +163,7 @@ std::tuple apply_effects_fileobj( // Prepare the buffer used throughout the lifecycle of SoxEffectChain. // Using std::string and let it manage memory. - // 4096 is minimum size required by auto_detect_format + // 4096 is minimum size requried by auto_detect_format // https://github.com/dmkrepo/libsox/blob/b9dd1a86e71bbd62221904e3e59dfaa9e5e72046/src/formats.c#L40-L48 const size_t in_buffer_size = 4096; std::string in_buffer(in_buffer_size, 'x'); @@ -193,7 +193,7 @@ std::tuple apply_effects_fileobj( const auto dtype = get_dtype(sf->encoding.encoding, sf->signal.precision); torchaudio::sox_effects_chain::SoxEffectsChain chain( /*input_encoding=*/sf->encoding, - /*output_encoding=*/get_encodinginfo("wav", dtype, 0.)); + /*output_encoding=*/get_encodinginfo("wav", dtype)); chain.addInputFileObj(sf, in_buf, in_buffer_size, &fileobj); for (const auto& effect : effects) { chain.addEffect(effect); diff --git a/torchaudio/csrc/sox/effects_chain.cpp b/torchaudio/csrc/sox/effects_chain.cpp index 37a6f32df8..9c365b72aa 100644 --- a/torchaudio/csrc/sox/effects_chain.cpp +++ b/torchaudio/csrc/sox/effects_chain.cpp @@ -295,6 +295,13 @@ struct FileObjInputPriv { uint64_t buffer_size; }; +struct FileObjOutputPriv { + sox_format_t* sf; + py::object* fileobj; + char** buffer; + size_t* buffer_size; +}; + /// Callback function to feed byte string /// https://github.com/dmkrepo/libsox/blob/b9dd1a86e71bbd62221904e3e59dfaa9e5e72046/src/sox.h#L1268-L1278 int fileobj_input_drain(sox_effect_t* effp, sox_sample_t* obuf, size_t* osamp) { @@ -335,7 +342,7 @@ int fileobj_input_drain(sox_effect_t* effp, sox_sample_t* obuf, size_t* osamp) { if(num_refill > num_consumed) { std::ostringstream message; message << "Tried to read up to " << num_consumed << " bytes but, " - << "received " << num_refill << " bytes. " + << "recieved " << num_refill << " bytes. " << "The given object does not confirm to read protocol of file object."; throw std::runtime_error(message.str()); } @@ -373,6 +380,45 @@ int fileobj_input_drain(sox_effect_t* effp, sox_sample_t* obuf, size_t* osamp) { return *osamp? SOX_SUCCESS : SOX_EOF; } +int fileobj_output_flow( + sox_effect_t* effp, + sox_sample_t const* ibuf, + sox_sample_t* obuf LSX_UNUSED, + size_t* isamp, + size_t* osamp) { + *osamp = 0; + if (*isamp) { + auto priv = static_cast(effp->priv); + auto sf = priv->sf; + auto fp = static_cast(sf->fp); + auto fileobj = priv->fileobj; + auto buffer = priv->buffer; + auto buffer_size = priv->buffer_size; + + // Encode chunk + auto num_samples_written = sox_write(sf, ibuf, *isamp); + fflush(fp); + + // Copy the encoded chunk to python object. + fileobj->attr("write")(py::bytes(*buffer, *buffer_size)); + + // Reset FILE* + sf->tell_off = 0; + fseek(fp, 0, SEEK_SET); + + if (num_samples_written != *isamp) { + if (sf->sox_errno) { + std::ostringstream stream; + stream << sf->sox_errstr << " " << sox_strerror(sf->sox_errno) << " " + << sf->filename; + throw std::runtime_error(stream.str()); + } + return SOX_EOF; + } + } + return SOX_SUCCESS; +} + sox_effect_handler_t* get_fileobj_input_handler() { static sox_effect_handler_t handler{/*name=*/"input_fileobj_object", /*usage=*/NULL, @@ -387,6 +433,20 @@ sox_effect_handler_t* get_fileobj_input_handler() { return &handler; } +sox_effect_handler_t* get_fileobj_output_handler() { + static sox_effect_handler_t handler{/*name=*/"output_fileobj_object", + /*usage=*/NULL, + /*flags=*/SOX_EFF_MCHAN, + /*getopts=*/NULL, + /*start=*/NULL, + /*flow=*/fileobj_output_flow, + /*drain=*/NULL, + /*stop=*/NULL, + /*kill=*/NULL, + /*priv_size=*/sizeof(FileObjOutputPriv)}; + return &handler; +} + } // namespace void SoxEffectsChain::addInputFileObj( @@ -408,6 +468,23 @@ void SoxEffectsChain::addInputFileObj( } } +void SoxEffectsChain::addOutputFileObj( + sox_format_t* sf, + char** buffer, + size_t* buffer_size, + py::object* fileobj) { + out_sig_ = sf->signal; + SoxEffect e(sox_create_effect(get_fileobj_output_handler())); + auto priv = static_cast(e->priv); + priv->sf = sf; + priv->fileobj = fileobj; + priv->buffer = buffer; + priv->buffer_size = buffer_size; + if (sox_add_effect(sec_, e, &interm_sig_, &out_sig_) != SOX_SUCCESS) { + throw std::runtime_error("Internal Error: Failed to add effect: output fileobj"); + } +} + #endif // TORCH_API_INCLUDE_EXTENSION_H } // namespace sox_effects_chain diff --git a/torchaudio/csrc/sox/effects_chain.h b/torchaudio/csrc/sox/effects_chain.h index b096b3eb3d..a4797b3486 100644 --- a/torchaudio/csrc/sox/effects_chain.h +++ b/torchaudio/csrc/sox/effects_chain.h @@ -46,6 +46,12 @@ class SoxEffectsChain { uint64_t buffer_size, py::object* fileobj); + void addOutputFileObj( + sox_format_t* sf, + char** buffer, + size_t* buffer_size, + py::object* fileobj); + #endif // TORCH_API_INCLUDE_EXTENSION_H }; diff --git a/torchaudio/csrc/sox/io.cpp b/torchaudio/csrc/sox/io.cpp index e381be14f8..c6531eb77e 100644 --- a/torchaudio/csrc/sox/io.cpp +++ b/torchaudio/csrc/sox/io.cpp @@ -95,26 +95,31 @@ c10::intrusive_ptr load_audio_file( } void save_audio_file( - const std::string& file_name, - const c10::intrusive_ptr& signal, - const double compression) { - auto tensor = signal->tensor; - + const std::string& path, + torch::Tensor tensor, + int64_t sample_rate, + bool channels_first, + c10::optional compression, + c10::optional format) { validate_input_tensor(tensor); - const auto filetype = get_filetype(file_name); + auto signal = TensorSignal(tensor, sample_rate, channels_first); + + const auto filetype = [&](){ + if (format.has_value()) return format.value(); + return get_filetype(path); + }(); if (filetype == "amr-nb") { - const auto num_channels = tensor.size(signal->channels_first ? 0 : 1); + const auto num_channels = tensor.size(channels_first ? 0 : 1); TORCH_CHECK( num_channels == 1, "amr-nb format only supports single channel audio."); tensor = (unnormalize_wav(tensor) / 65536).to(torch::kInt16); } - const auto signal_info = get_signalinfo(signal.get(), filetype); - const auto encoding_info = - get_encodinginfo(filetype, tensor.dtype(), compression); + const auto signal_info = get_signalinfo(&signal, filetype); + const auto encoding_info = get_encodinginfo(filetype, tensor.dtype(), compression); SoxFormat sf(sox_open_write( - file_name.c_str(), + path.c_str(), &signal_info, &encoding_info, /*filetype=*/filetype.c_str(), @@ -126,9 +131,9 @@ void save_audio_file( } torchaudio::sox_effects_chain::SoxEffectsChain chain( - /*input_encoding=*/get_encodinginfo("wav", tensor.dtype(), 0.), + /*input_encoding=*/get_encodinginfo("wav", tensor.dtype()), /*output_encoding=*/sf->encoding); - chain.addInputTensor(signal.get()); + chain.addInputTensor(&signal); chain.addOutputFile(sf); chain.run(); } @@ -147,6 +152,75 @@ std::tuple load_audio_fileobj( fileobj, effects, normalize, channels_first, format); } +namespace { + +// helper class to automatically release buffer, to be used by save_audio_fileobj +struct AutoReleaseBuffer { + char* ptr; + size_t size; + + AutoReleaseBuffer() : ptr(nullptr), size(0) {} + AutoReleaseBuffer(const AutoReleaseBuffer& other) = delete; + AutoReleaseBuffer(AutoReleaseBuffer&& other) = delete; + AutoReleaseBuffer& operator=(const AutoReleaseBuffer& other) = delete; + AutoReleaseBuffer& operator=(AutoReleaseBuffer&& other) = delete; + ~AutoReleaseBuffer() { + if (ptr) { + free(ptr); + } + } +}; + +} // namespace + +void save_audio_fileobj( + py::object fileobj, + torch::Tensor tensor, + int64_t sample_rate, + bool channels_first, + c10::optional compression, + std::string filetype) { + validate_input_tensor(tensor); + + auto signal = TensorSignal(tensor, sample_rate, channels_first); + + if (filetype == "amr-nb") { + const auto num_channels = tensor.size(channels_first ? 0 : 1); + if (num_channels != 1) { + throw std::runtime_error("amr-nb format only supports single channel audio."); + } + tensor = (unnormalize_wav(tensor) / 65536).to(torch::kInt16); + } + const auto signal_info = get_signalinfo(&signal, filetype); + const auto encoding_info = get_encodinginfo(filetype, tensor.dtype(), compression); + + AutoReleaseBuffer buffer; + + SoxFormat sf(sox_open_memstream_write( + &buffer.ptr, + &buffer.size, + &signal_info, + &encoding_info, + filetype.c_str(), + /*oob=*/nullptr)); + + if (static_cast(sf) == nullptr) { + throw std::runtime_error("Error saving audio file: failed to open memory stream."); + } + + torchaudio::sox_effects_chain::SoxEffectsChain chain( + /*input_encoding=*/get_encodinginfo("wav", tensor.dtype()), + /*output_encoding=*/sf->encoding); + chain.addInputTensor(&signal); + chain.addOutputFileObj(sf, &buffer.ptr, &buffer.size, &fileobj); + chain.run(); + + // Closing the sox_format_t is necessary for flushing the last chunk to the buffer + sf.close(); + + fileobj.attr("write")(py::bytes(buffer.ptr, buffer.size)); +} + #endif // TORCH_API_INCLUDE_EXTENSION_H } // namespace sox_io diff --git a/torchaudio/csrc/sox/io.h b/torchaudio/csrc/sox/io.h index d6e5310077..ac7191527f 100644 --- a/torchaudio/csrc/sox/io.h +++ b/torchaudio/csrc/sox/io.h @@ -38,9 +38,12 @@ c10::intrusive_ptr load_audio_file( c10::optional& format); void save_audio_file( - const std::string& file_name, - const c10::intrusive_ptr& signal, - const double compression = 0.); + const std::string& path, + torch::Tensor tensor, + int64_t sample_rate, + bool channels_first, + c10::optional compression, + c10::optional format); #ifdef TORCH_API_INCLUDE_EXTENSION_H @@ -52,6 +55,14 @@ std::tuple load_audio_fileobj( c10::optional& channels_first, c10::optional& format); +void save_audio_fileobj( + py::object fileobj, + torch::Tensor tensor, + int64_t sample_rate, + bool channels_first, + c10::optional compression, + std::string filetype); + #endif // TORCH_API_INCLUDE_EXTENSION_H } // namespace sox_io diff --git a/torchaudio/csrc/sox/utils.cpp b/torchaudio/csrc/sox/utils.cpp index 44f00084e8..0ea95cbbb3 100644 --- a/torchaudio/csrc/sox/utils.cpp +++ b/torchaudio/csrc/sox/utils.cpp @@ -80,11 +80,8 @@ bool TensorSignal::getChannelsFirst() const { } SoxFormat::SoxFormat(sox_format_t* fd) noexcept : fd_(fd) {} -SoxFormat::~SoxFormat() { - if (fd_ != nullptr) { - sox_close(fd_); - } -} +SoxFormat::~SoxFormat() { close(); } + sox_format_t* SoxFormat::operator->() const noexcept { return fd_; } @@ -92,6 +89,13 @@ SoxFormat::operator sox_format_t*() const noexcept { return fd_; } +void SoxFormat::close() { + if (fd_ != nullptr) { + sox_close(fd_); + fd_ = nullptr; + } +} + void validate_input_file(const SoxFormat& sf, bool check_length) { if (static_cast(sf) == nullptr) { throw std::runtime_error("Error loading audio file: failed to open file."); @@ -286,27 +290,23 @@ sox_signalinfo_t get_signalinfo( sox_encodinginfo_t get_encodinginfo( const std::string filetype, - const caffe2::TypeMeta dtype, - const double compression) { - const double compression_ = [&]() { - if (filetype == "mp3") - return compression; - if (filetype == "flac") - return compression; - if (filetype == "ogg" || filetype == "vorbis") - return compression; - if (filetype == "wav" || filetype == "amb") - return 0.; - if (filetype == "sph") - return 0.; - if (filetype == "amr-nb") - return 0.; - throw std::runtime_error("Unsupported file type: " + filetype); - }(); + const caffe2::TypeMeta dtype) { + return sox_encodinginfo_t{/*encoding=*/get_encoding(filetype, dtype), + /*bits_per_sample=*/get_precision(filetype, dtype), + /*compression=*/HUGE_VAL, + /*reverse_bytes=*/sox_option_default, + /*reverse_nibbles=*/sox_option_default, + /*reverse_bits=*/sox_option_default, + /*opposite_endian=*/sox_false}; +} +sox_encodinginfo_t get_encodinginfo( + const std::string filetype, + const caffe2::TypeMeta dtype, + c10::optional& compression) { return sox_encodinginfo_t{/*encoding=*/get_encoding(filetype, dtype), /*bits_per_sample=*/get_precision(filetype, dtype), - /*compression=*/compression_, + /*compression=*/compression.value_or(HUGE_VAL), /*reverse_bytes=*/sox_option_default, /*reverse_nibbles=*/sox_option_default, /*reverse_bits=*/sox_option_default, diff --git a/torchaudio/csrc/sox/utils.h b/torchaudio/csrc/sox/utils.h index ee8d1baa66..2d434d6f72 100644 --- a/torchaudio/csrc/sox/utils.h +++ b/torchaudio/csrc/sox/utils.h @@ -61,6 +61,8 @@ struct SoxFormat { sox_format_t* operator->() const noexcept; operator sox_format_t*() const noexcept; + void close(); + private: sox_format_t* fd_; }; @@ -116,10 +118,14 @@ sox_signalinfo_t get_signalinfo( const std::string filetype); /// Get sox_encofinginfo_t for saving audoi file +sox_encodinginfo_t get_encodinginfo( + const std::string filetype, + const caffe2::TypeMeta dtype); + sox_encodinginfo_t get_encodinginfo( const std::string filetype, const caffe2::TypeMeta dtype, - const double compression); + c10::optional& compression); } // namespace sox_utils } // namespace torchaudio diff --git a/torchaudio/datasets/yesno.py b/torchaudio/datasets/yesno.py index 7178b8332c..6d0d2c0a5f 100644 --- a/torchaudio/datasets/yesno.py +++ b/torchaudio/datasets/yesno.py @@ -11,23 +11,14 @@ extract_archive, ) -URL = "http://www.openslr.org/resources/1/waves_yesno.tar.gz" -FOLDER_IN_ARCHIVE = "waves_yesno" -_CHECKSUMS = { - "http://www.openslr.org/resources/1/waves_yesno.tar.gz": - "962ff6e904d2df1126132ecec6978786" -} - - -def load_yesno_item(fileid: str, path: str, ext_audio: str) -> Tuple[Tensor, int, List[int]]: - # Read label - labels = [int(c) for c in fileid.split("_")] - # Read wav - file_audio = os.path.join(path, fileid + ext_audio) - waveform, sample_rate = torchaudio.load(file_audio) - - return waveform, sample_rate, labels +_RELEASE_CONFIGS = { + "release1": { + "folder_in_archive": "waves_yesno", + "url": "http://www.openslr.org/resources/1/waves_yesno.tar.gz", + "checksum": "30301975fd8c5cac4040c261c0852f57cfa8adbbad2ce78e77e4986957445f27", + } +} class YESNO(Dataset): @@ -43,25 +34,26 @@ class YESNO(Dataset): Whether to download the dataset if it is not found at root path. (default: ``False``). """ - _ext_audio = ".wav" - - def __init__(self, - root: Union[str, Path], - url: str = URL, - folder_in_archive: str = FOLDER_IN_ARCHIVE, - download: bool = False) -> None: + def __init__( + self, + root: Union[str, Path], + url: str = _RELEASE_CONFIGS["release1"]["url"], + folder_in_archive: str = _RELEASE_CONFIGS["release1"]["folder_in_archive"], + download: bool = False + ) -> None: - # Get string representation of 'root' in case Path object is passed - root = os.fspath(root) + self._parse_filesystem(root, url, folder_in_archive, download) + def _parse_filesystem(self, root: str, url: str, folder_in_archive: str, download: bool) -> None: + root = Path(root) archive = os.path.basename(url) - archive = os.path.join(root, archive) - self._path = os.path.join(root, folder_in_archive) + archive = root / archive + self._path = root / folder_in_archive if download: if not os.path.isdir(self._path): if not os.path.isfile(archive): - checksum = _CHECKSUMS.get(url, None) + checksum = _RELEASE_CONFIGS["release1"]["checksum"] download_url(url, root, hash_value=checksum, hash_type="md5") extract_archive(archive) @@ -70,7 +62,13 @@ def __init__(self, "Dataset not found. Please use `download=True` to download it." ) - self._walker = sorted(str(p.stem) for p in Path(self._path).glob('*' + self._ext_audio)) + self._walker = sorted(str(p.stem) for p in Path(self._path).glob("*.wav")) + + def _load_item(self, fileid: str, path: str): + labels = [int(c) for c in fileid.split("_")] + file_audio = os.path.join(path, fileid + ".wav") + waveform, sample_rate = torchaudio.load(file_audio) + return waveform, sample_rate, labels def __getitem__(self, n: int) -> Tuple[Tensor, int, List[int]]: """Load the n-th sample from the dataset. @@ -82,13 +80,8 @@ def __getitem__(self, n: int) -> Tuple[Tensor, int, List[int]]: tuple: ``(waveform, sample_rate, labels)`` """ fileid = self._walker[n] - item = load_yesno_item(fileid, self._path, self._ext_audio) - - # TODO Upon deprecation, uncomment line below and remove following code - # return item - - waveform, sample_rate, labels = item - return waveform, sample_rate, labels + item = self._load_item(fileid, self._path) + return item def __len__(self) -> int: return len(self._walker) diff --git a/tox.ini b/tox.ini deleted file mode 100644 index 793ccc2c3b..0000000000 --- a/tox.ini +++ /dev/null @@ -1,4 +0,0 @@ -[flake8] -max-line-length = 120 -ignore = E305,E402,E721,E741,F401,F403,F405,F821,F841,F999 -exclude = docs/src,venv,torch/lib/gloo,torch/lib/pybind11,torch/lib/nanopb From d580296c74df83da1569cf2bc45ef95574ccdaeb Mon Sep 17 00:00:00 2001 From: Vincent Quenneville-Belair Date: Mon, 1 Feb 2021 16:03:20 -0800 Subject: [PATCH 27/73] Import #1217 828df46a95310453dda13599a29fa22a1cc049da Summary: Import [#1217](https://github.com/pytorch/audio/pull/1217) 828df46a95310453dda13599a29fa22a1cc049da Reviewed By: cpuhrsch Differential Revision: D26180248 fbshipit-source-id: 34b1e18e86436472f47070c4d3c748a10a4153a3 --- .circleci/config.yml | 120 +------ .circleci/config.yml.in | 120 +------ .circleci/unittest/linux/docker/Dockerfile | 5 +- .../unittest/linux/docker/build_and_push.sh | 11 +- .circleci/unittest/linux/scripts/install.sh | 2 - .../linux/scripts/run-clang-format.py | 340 ++++++++++++++++++ .../linux/scripts/run_style_checks.sh | 26 +- .../batch_consistency_test.py | 11 + .../librosa_compatibility_test.py | 13 + .../soundfile_backend/common.py | 2 +- .../soundfile_backend/info_test.py | 123 ++++++- .../sox_effect/smoke_test.py | 22 +- .../sox_effect/sox_effect_test.py | 161 ++++++++- .../sox_io_backend/info_test.py | 291 ++++++++++++++- .../sox_io_backend/load_test.py | 75 ++++ .../sox_io_backend/save_test.py | 43 ++- .../sox_io_backend/smoke_test.py | 68 ++++ .../torchscript_consistency_impl.py | 19 + test/torchaudio_unittest/transforms_test.py | 16 + third_party/sox/CMakeLists.txt | 122 ++++++- torchaudio/backend/_soundfile_backend.py | 88 ++++- torchaudio/backend/common.py | 14 +- torchaudio/backend/sox_io_backend.py | 68 +++- torchaudio/csrc/pybind.cpp | 165 +++++---- torchaudio/csrc/sox/effects.cpp | 80 +++-- torchaudio/csrc/sox/effects_chain.cpp | 179 ++++----- torchaudio/csrc/sox/io.cpp | 153 +++++++- torchaudio/csrc/sox/io.h | 20 +- torchaudio/csrc/sox/legacy.cpp | 16 +- torchaudio/csrc/sox/legacy.h | 12 +- torchaudio/csrc/sox/register.cpp | 20 +- torchaudio/csrc/sox/utils.cpp | 81 ++++- torchaudio/csrc/sox/utils.h | 14 +- torchaudio/csrc/transducer.cpp | 154 ++++---- torchaudio/datasets/ljspeech.py | 74 ++-- torchaudio/functional/__init__.py | 1 + torchaudio/functional/functional.py | 54 ++- torchaudio/sox_effects/sox_effects.py | 22 +- torchaudio/transforms.py | 98 ++++- 39 files changed, 2214 insertions(+), 689 deletions(-) create mode 100755 .circleci/unittest/linux/scripts/run-clang-format.py diff --git a/.circleci/config.yml b/.circleci/config.yml index c40054d0e3..ef2a4ff76c 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -388,29 +388,16 @@ jobs: unittest_linux_cpu: <<: *binary_common docker: - - image: "pytorch/torchaudio_unittest_base:manylinux" + - image: pytorch/torchaudio_unittest_base:manylinux-20210121 resource_class: 2xlarge+ steps: - checkout - attach_workspace: at: third_party - designate_upload_channel - - generate_cache_key - - restore_cache: - - keys: - - env-v3-linux-{{ arch }}-py<< parameters.python_version >>-{{ checksum ".circleci/unittest/linux/scripts/setup_env.sh" }}-{{ checksum "third_party/CMakeLists.txt" }}-{{ checksum ".cachekey" }} - - run: name: Setup command: .circleci/unittest/linux/scripts/setup_env.sh - - save_cache: - - key: env-v3-linux-{{ arch }}-py<< parameters.python_version >>-{{ checksum ".circleci/unittest/linux/scripts/setup_env.sh" }}-{{ checksum "third_party/CMakeLists.txt" }}-{{ checksum ".cachekey" }} - - paths: - - conda - - env - run: name: Install torchaudio command: .circleci/unittest/linux/scripts/install.sh @@ -430,31 +417,18 @@ jobs: resource_class: gpu.small environment: <<: *environment - image_name: "pytorch/torchaudio_unittest_base:manylinux-cuda10.1" + image_name: pytorch/torchaudio_unittest_base:manylinux-cuda10.1-cudnn7-20210121 steps: - checkout - attach_workspace: at: third_party - designate_upload_channel - - generate_cache_key - - restore_cache: - - keys: - - env-v3-linux-{{ arch }}-py<< parameters.python_version >>-{{ checksum ".circleci/unittest/linux/scripts/setup_env.sh" }}-{{ checksum "third_party/CMakeLists.txt" }}-{{ checksum ".cachekey" }} - - run: name: Pull Docker image command: docker pull --quiet "${image_name}" - run: name: Setup command: docker run -t --gpus all -e PYTHON_VERSION -v $PWD:$PWD -w $PWD "${image_name}" .circleci/unittest/linux/scripts/setup_env.sh - - save_cache: - - key: env-v3-linux-{{ arch }}-py<< parameters.python_version >>-{{ checksum ".circleci/unittest/linux/scripts/setup_env.sh" }}-{{ checksum "third_party/CMakeLists.txt" }}-{{ checksum ".cachekey" }} - - paths: - - conda - - env - run: name: Install torchaudio command: docker run -t --gpus all -e UPLOAD_CHANNEL -v $PWD:$PWD -w $PWD "${image_name}" .circleci/unittest/linux/scripts/install.sh @@ -474,22 +448,9 @@ jobs: steps: - checkout - designate_upload_channel - - generate_cache_key - - restore_cache: - - keys: - - env-v3-windows-{{ arch }}-py<< parameters.python_version >>-{{ checksum ".circleci/unittest/windows/scripts/setup_env.sh" }}-{{ checksum ".cachekey" }} - - run: name: Setup command: .circleci/unittest/windows/scripts/setup_env.sh - - save_cache: - - key: env-v3-windows-{{ arch }}-py<< parameters.python_version >>-{{ checksum ".circleci/unittest/windows/scripts/setup_env.sh" }}-{{ checksum ".cachekey" }} - - paths: - - conda - - env - run: name: Install torchaudio command: .circleci/unittest/windows/scripts/install.sh @@ -512,22 +473,9 @@ jobs: steps: - checkout - designate_upload_channel - - generate_cache_key - - restore_cache: - - keys: - - env-v1-windows-{{ arch }}-py<< parameters.python_version >>-{{ checksum ".circleci/unittest/windows/scripts/setup_env.sh" }}-{{ checksum ".cachekey" }} - - run: name: Setup command: .circleci/unittest/windows/scripts/setup_env.sh - - save_cache: - - key: env-v1-windows-{{ arch }}-py<< parameters.python_version >>-{{ checksum ".circleci/unittest/windows/scripts/setup_env.sh" }}-{{ checksum ".cachekey" }} - - paths: - - conda - - env - run: name: Install torchaudio command: .circleci/unittest/windows/scripts/install.sh @@ -551,22 +499,9 @@ jobs: - attach_workspace: at: third_party - designate_upload_channel - - generate_cache_key - - restore_cache: - - keys: - - env-v3-macos-{{ arch }}-py<< parameters.python_version >>-{{ checksum ".circleci/unittest/linux/scripts/setup_env.sh" }}-{{ checksum "third_party/CMakeLists.txt" }}-{{ checksum ".cachekey" }} - - run: name: Setup command: .circleci/unittest/linux/scripts/setup_env.sh - - save_cache: - - key: env-v3-macos-{{ arch }}-py<< parameters.python_version >>-{{ checksum ".circleci/unittest/linux/scripts/setup_env.sh" }}-{{ checksum "third_party/CMakeLists.txt" }}-{{ checksum ".cachekey" }} - - paths: - - conda - - env - run: name: Install torchaudio command: .circleci/unittest/linux/scripts/install.sh @@ -587,61 +522,13 @@ jobs: steps: - checkout - designate_upload_channel - - generate_cache_key - - restore_cache: - - keys: - - env-v2-linux-{{ arch }}-py<< parameters.python_version >>-{{ checksum ".circleci/unittest/linux/scripts/setup_env.sh" }}-{{ checksum ".cachekey" }} - - run: name: Setup command: .circleci/unittest/linux/scripts/setup_env.sh - - save_cache: - - key: env-v2-linux-{{ arch }}-py<< parameters.python_version >>-{{ checksum ".circleci/unittest/linux/scripts/setup_env.sh" }}-{{ checksum ".cachekey" }} - - paths: - - conda - - env - run: name: Run style check command: .circleci/unittest/linux/scripts/run_style_checks.sh - torchscript_bc_test: - docker: - - image: "pytorch/torchaudio_unittest_base:manylinux" - resource_class: large - steps: - - checkout - - generate_cache_key - - restore_cache: - - keys: - - torchscript-bc-test-release-envs-v1-{{ arch }}-{{ checksum ".cachekey" }} - - - run: - name: Generate Objects - command: | - .circleci/torchscript_bc_test/setup_release_envs.sh - .circleci/torchscript_bc_test/generate_objects.sh - - save_cache: - - key: torchscript-bc-test-release-envs-v1-{{ arch }}-{{ checksum ".cachekey" }} - - paths: - - conda - - envs - - store_artifacts: - path: test/torchscript_bc_test/assets - - persist_to_workspace: - root: . - paths: - - test/torchscript_bc_test/assets - - run: - name: Run BC check test - command: | - .circleci/torchscript_bc_test/setup_master_envs.sh - .circleci/torchscript_bc_test/validate_objects.sh build_docs: <<: *binary_common docker: @@ -793,9 +680,6 @@ workflows: - build_docs unittest: jobs: - - torchscript_bc_test: - requires: - - download_third_parties_nix - download_third_parties_nix: name: download_third_parties_nix - unittest_linux_cpu: diff --git a/.circleci/config.yml.in b/.circleci/config.yml.in index 535729d72e..84e25911a3 100644 --- a/.circleci/config.yml.in +++ b/.circleci/config.yml.in @@ -388,29 +388,16 @@ jobs: unittest_linux_cpu: <<: *binary_common docker: - - image: "pytorch/torchaudio_unittest_base:manylinux" + - image: pytorch/torchaudio_unittest_base:manylinux-20210121 resource_class: 2xlarge+ steps: - checkout - attach_workspace: at: third_party - designate_upload_channel - - generate_cache_key - - restore_cache: - {% raw %} - keys: - - env-v3-linux-{{ arch }}-py<< parameters.python_version >>-{{ checksum ".circleci/unittest/linux/scripts/setup_env.sh" }}-{{ checksum "third_party/CMakeLists.txt" }}-{{ checksum ".cachekey" }} - {% endraw %} - run: name: Setup command: .circleci/unittest/linux/scripts/setup_env.sh - - save_cache: - {% raw %} - key: env-v3-linux-{{ arch }}-py<< parameters.python_version >>-{{ checksum ".circleci/unittest/linux/scripts/setup_env.sh" }}-{{ checksum "third_party/CMakeLists.txt" }}-{{ checksum ".cachekey" }} - {% endraw %} - paths: - - conda - - env - run: name: Install torchaudio command: .circleci/unittest/linux/scripts/install.sh @@ -430,31 +417,18 @@ jobs: resource_class: gpu.small environment: <<: *environment - image_name: "pytorch/torchaudio_unittest_base:manylinux-cuda10.1" + image_name: pytorch/torchaudio_unittest_base:manylinux-cuda10.1-cudnn7-20210121 steps: - checkout - attach_workspace: at: third_party - designate_upload_channel - - generate_cache_key - - restore_cache: - {% raw %} - keys: - - env-v3-linux-{{ arch }}-py<< parameters.python_version >>-{{ checksum ".circleci/unittest/linux/scripts/setup_env.sh" }}-{{ checksum "third_party/CMakeLists.txt" }}-{{ checksum ".cachekey" }} - {% endraw %} - run: name: Pull Docker image command: docker pull --quiet "${image_name}" - run: name: Setup command: docker run -t --gpus all -e PYTHON_VERSION -v $PWD:$PWD -w $PWD "${image_name}" .circleci/unittest/linux/scripts/setup_env.sh - - save_cache: - {% raw %} - key: env-v3-linux-{{ arch }}-py<< parameters.python_version >>-{{ checksum ".circleci/unittest/linux/scripts/setup_env.sh" }}-{{ checksum "third_party/CMakeLists.txt" }}-{{ checksum ".cachekey" }} - {% endraw %} - paths: - - conda - - env - run: name: Install torchaudio command: docker run -t --gpus all -e UPLOAD_CHANNEL -v $PWD:$PWD -w $PWD "${image_name}" .circleci/unittest/linux/scripts/install.sh @@ -474,22 +448,9 @@ jobs: steps: - checkout - designate_upload_channel - - generate_cache_key - - restore_cache: - {% raw %} - keys: - - env-v3-windows-{{ arch }}-py<< parameters.python_version >>-{{ checksum ".circleci/unittest/windows/scripts/setup_env.sh" }}-{{ checksum ".cachekey" }} - {% endraw %} - run: name: Setup command: .circleci/unittest/windows/scripts/setup_env.sh - - save_cache: - {% raw %} - key: env-v3-windows-{{ arch }}-py<< parameters.python_version >>-{{ checksum ".circleci/unittest/windows/scripts/setup_env.sh" }}-{{ checksum ".cachekey" }} - {% endraw %} - paths: - - conda - - env - run: name: Install torchaudio command: .circleci/unittest/windows/scripts/install.sh @@ -512,22 +473,9 @@ jobs: steps: - checkout - designate_upload_channel - - generate_cache_key - - restore_cache: - {% raw %} - keys: - - env-v1-windows-{{ arch }}-py<< parameters.python_version >>-{{ checksum ".circleci/unittest/windows/scripts/setup_env.sh" }}-{{ checksum ".cachekey" }} - {% endraw %} - run: name: Setup command: .circleci/unittest/windows/scripts/setup_env.sh - - save_cache: - {% raw %} - key: env-v1-windows-{{ arch }}-py<< parameters.python_version >>-{{ checksum ".circleci/unittest/windows/scripts/setup_env.sh" }}-{{ checksum ".cachekey" }} - {% endraw %} - paths: - - conda - - env - run: name: Install torchaudio command: .circleci/unittest/windows/scripts/install.sh @@ -551,22 +499,9 @@ jobs: - attach_workspace: at: third_party - designate_upload_channel - - generate_cache_key - - restore_cache: - {% raw %} - keys: - - env-v3-macos-{{ arch }}-py<< parameters.python_version >>-{{ checksum ".circleci/unittest/linux/scripts/setup_env.sh" }}-{{ checksum "third_party/CMakeLists.txt" }}-{{ checksum ".cachekey" }} - {% endraw %} - run: name: Setup command: .circleci/unittest/linux/scripts/setup_env.sh - - save_cache: - {% raw %} - key: env-v3-macos-{{ arch }}-py<< parameters.python_version >>-{{ checksum ".circleci/unittest/linux/scripts/setup_env.sh" }}-{{ checksum "third_party/CMakeLists.txt" }}-{{ checksum ".cachekey" }} - {% endraw %} - paths: - - conda - - env - run: name: Install torchaudio command: .circleci/unittest/linux/scripts/install.sh @@ -587,61 +522,13 @@ jobs: steps: - checkout - designate_upload_channel - - generate_cache_key - - restore_cache: - {% raw %} - keys: - - env-v2-linux-{{ arch }}-py<< parameters.python_version >>-{{ checksum ".circleci/unittest/linux/scripts/setup_env.sh" }}-{{ checksum ".cachekey" }} - {% endraw %} - run: name: Setup command: .circleci/unittest/linux/scripts/setup_env.sh - - save_cache: - {% raw %} - key: env-v2-linux-{{ arch }}-py<< parameters.python_version >>-{{ checksum ".circleci/unittest/linux/scripts/setup_env.sh" }}-{{ checksum ".cachekey" }} - {% endraw %} - paths: - - conda - - env - run: name: Run style check command: .circleci/unittest/linux/scripts/run_style_checks.sh - torchscript_bc_test: - docker: - - image: "pytorch/torchaudio_unittest_base:manylinux" - resource_class: large - steps: - - checkout - - generate_cache_key - - restore_cache: - {% raw %} - keys: - - torchscript-bc-test-release-envs-v1-{{ arch }}-{{ checksum ".cachekey" }} - {% endraw %} - - run: - name: Generate Objects - command: | - .circleci/torchscript_bc_test/setup_release_envs.sh - .circleci/torchscript_bc_test/generate_objects.sh - - save_cache: - {% raw %} - key: torchscript-bc-test-release-envs-v1-{{ arch }}-{{ checksum ".cachekey" }} - {% endraw %} - paths: - - conda - - envs - - store_artifacts: - path: test/torchscript_bc_test/assets - - persist_to_workspace: - root: . - paths: - - test/torchscript_bc_test/assets - - run: - name: Run BC check test - command: | - .circleci/torchscript_bc_test/setup_master_envs.sh - .circleci/torchscript_bc_test/validate_objects.sh build_docs: <<: *binary_common docker: @@ -697,9 +584,6 @@ workflows: {{ build_workflows() }} unittest: jobs: - - torchscript_bc_test: - requires: - - download_third_parties_nix {{ unittest_workflows() }} nightly: jobs: diff --git a/.circleci/unittest/linux/docker/Dockerfile b/.circleci/unittest/linux/docker/Dockerfile index d91b5222a4..c47a896348 100644 --- a/.circleci/unittest/linux/docker/Dockerfile +++ b/.circleci/unittest/linux/docker/Dockerfile @@ -45,14 +45,11 @@ RUN apt update && apt install -y \ gfortran \ git \ libatlas3-base \ + libsndfile1 \ wget \ curl \ make \ file \ - sox \ - libsox-dev \ - libsox-fmt-all \ - cmake \ pkg-config \ && rm -rf /var/lib/apt/lists/* COPY --from=builder /kaldi /kaldi diff --git a/.circleci/unittest/linux/docker/build_and_push.sh b/.circleci/unittest/linux/docker/build_and_push.sh index 8bf33eaaa3..e7ced13ad3 100755 --- a/.circleci/unittest/linux/docker/build_and_push.sh +++ b/.circleci/unittest/linux/docker/build_and_push.sh @@ -7,15 +7,14 @@ if [ $# -ne 1 ]; then exit 1 fi +datestr="$(date "+%Y%m%d")" if [ "$1" = "cpu" ]; then base_image="ubuntu:18.04" - image="pytorch/torchaudio_unittest_base:manylinux" -elif [[ "$1" =~ ^(9.2|10.1)$ ]]; then - base_image="nvidia/cuda:$1-runtime-ubuntu18.04" - image="pytorch/torchaudio_unittest_base:manylinux-cuda$1" + image="pytorch/torchaudio_unittest_base:manylinux-${datestr}" else - printf "Unexpected string: %s" "$1" - exit 1; + base_image="nvidia/cuda:$1-devel-ubuntu18.04" + docker pull "${base_image}" + image="pytorch/torchaudio_unittest_base:manylinux-cuda$1-${datestr}" fi cd "$( dirname "${BASH_SOURCE[0]}" )" diff --git a/.circleci/unittest/linux/scripts/install.sh b/.circleci/unittest/linux/scripts/install.sh index 72b7c9c88f..fd43260194 100755 --- a/.circleci/unittest/linux/scripts/install.sh +++ b/.circleci/unittest/linux/scripts/install.sh @@ -43,8 +43,6 @@ BUILD_TRANSDUCER=1 BUILD_SOX=1 python setup.py install # 3. Install Test tools printf "* Installing test tools\n" if [ "${os}" == Linux ] ; then - # TODO: move this to docker - apt install -y -q libsndfile1 conda install -y -c conda-forge codecov pytest pytest-cov pip install kaldi-io 'librosa>=0.8.0' parameterized SoundFile scipy 'requests>=2.20' else diff --git a/.circleci/unittest/linux/scripts/run-clang-format.py b/.circleci/unittest/linux/scripts/run-clang-format.py new file mode 100755 index 0000000000..fd2913bd70 --- /dev/null +++ b/.circleci/unittest/linux/scripts/run-clang-format.py @@ -0,0 +1,340 @@ +#!/usr/bin/env python +"""A wrapper script around clang-format, suitable for linting multiple files +and to use for continuous integration. + +This is an alternative API for the clang-format command line. +It runs over multiple files and directories in parallel. +A diff output is produced and a sensible exit code is returned. + +""" + +import argparse +import codecs +import difflib +import fnmatch +import io +import multiprocessing +import os +import signal +import subprocess +import sys +import traceback + +from functools import partial + +try: + from subprocess import DEVNULL # py3k +except ImportError: + DEVNULL = open(os.devnull, "wb") + + +DEFAULT_EXTENSIONS = 'c,h,C,H,cpp,hpp,cc,hh,c++,h++,cxx,hxx,cu' + + +class ExitStatus: + SUCCESS = 0 + DIFF = 1 + TROUBLE = 2 + + +def list_files(files, recursive=False, extensions=None, exclude=None): + if extensions is None: + extensions = [] + if exclude is None: + exclude = [] + + out = [] + for file in files: + if recursive and os.path.isdir(file): + for dirpath, dnames, fnames in os.walk(file): + fpaths = [os.path.join(dirpath, fname) for fname in fnames] + for pattern in exclude: + # os.walk() supports trimming down the dnames list + # by modifying it in-place, + # to avoid unnecessary directory listings. + dnames[:] = [ + x for x in dnames + if + not fnmatch.fnmatch(os.path.join(dirpath, x), pattern) + ] + fpaths = [ + x for x in fpaths if not fnmatch.fnmatch(x, pattern) + ] + for f in fpaths: + ext = os.path.splitext(f)[1][1:] + if ext in extensions: + out.append(f) + else: + out.append(file) + return out + + +def make_diff(file, original, reformatted): + return list( + difflib.unified_diff( + original, + reformatted, + fromfile='{}\t(original)'.format(file), + tofile='{}\t(reformatted)'.format(file), + n=3)) + + +class DiffError(Exception): + def __init__(self, message, errs=None): + super(DiffError, self).__init__(message) + self.errs = errs or [] + + +class UnexpectedError(Exception): + def __init__(self, message, exc=None): + super(UnexpectedError, self).__init__(message) + self.formatted_traceback = traceback.format_exc() + self.exc = exc + + +def run_clang_format_diff_wrapper(args, file): + try: + ret = run_clang_format_diff(args, file) + return ret + except DiffError: + raise + except Exception as e: + raise UnexpectedError('{}: {}: {}'.format(file, e.__class__.__name__, + e), e) + + +def run_clang_format_diff(args, file): + try: + with io.open(file, 'r', encoding='utf-8') as f: + original = f.readlines() + except IOError as exc: + raise DiffError(str(exc)) + invocation = [args.clang_format_executable, file] + + # Use of utf-8 to decode the process output. + # + # Hopefully, this is the correct thing to do. + # + # It's done due to the following assumptions (which may be incorrect): + # - clang-format will returns the bytes read from the files as-is, + # without conversion, and it is already assumed that the files use utf-8. + # - if the diagnostics were internationalized, they would use utf-8: + # > Adding Translations to Clang + # > + # > Not possible yet! + # > Diagnostic strings should be written in UTF-8, + # > the client can translate to the relevant code page if needed. + # > Each translation completely replaces the format string + # > for the diagnostic. + # > -- http://clang.llvm.org/docs/InternalsManual.html#internals-diag-translation + + try: + proc = subprocess.Popen( + invocation, + stdout=subprocess.PIPE, + stderr=subprocess.PIPE, + universal_newlines=True, + encoding='utf-8') + except OSError as exc: + raise DiffError( + "Command '{}' failed to start: {}".format( + subprocess.list2cmdline(invocation), exc + ) + ) + proc_stdout = proc.stdout + proc_stderr = proc.stderr + + # hopefully the stderr pipe won't get full and block the process + outs = list(proc_stdout.readlines()) + errs = list(proc_stderr.readlines()) + proc.wait() + if proc.returncode: + raise DiffError( + "Command '{}' returned non-zero exit status {}".format( + subprocess.list2cmdline(invocation), proc.returncode + ), + errs, + ) + return make_diff(file, original, outs), errs + + +def bold_red(s): + return '\x1b[1m\x1b[31m' + s + '\x1b[0m' + + +def colorize(diff_lines): + def bold(s): + return '\x1b[1m' + s + '\x1b[0m' + + def cyan(s): + return '\x1b[36m' + s + '\x1b[0m' + + def green(s): + return '\x1b[32m' + s + '\x1b[0m' + + def red(s): + return '\x1b[31m' + s + '\x1b[0m' + + for line in diff_lines: + if line[:4] in ['--- ', '+++ ']: + yield bold(line) + elif line.startswith('@@ '): + yield cyan(line) + elif line.startswith('+'): + yield green(line) + elif line.startswith('-'): + yield red(line) + else: + yield line + + +def print_diff(diff_lines, use_color): + if use_color: + diff_lines = colorize(diff_lines) + sys.stdout.writelines(diff_lines) + + +def print_trouble(prog, message, use_colors): + error_text = 'error:' + if use_colors: + error_text = bold_red(error_text) + print("{}: {} {}".format(prog, error_text, message), file=sys.stderr) + + +def main(): + parser = argparse.ArgumentParser(description=__doc__) + parser.add_argument( + '--clang-format-executable', + metavar='EXECUTABLE', + help='path to the clang-format executable', + default='clang-format') + parser.add_argument( + '--extensions', + help='comma separated list of file extensions (default: {})'.format( + DEFAULT_EXTENSIONS), + default=DEFAULT_EXTENSIONS) + parser.add_argument( + '-r', + '--recursive', + action='store_true', + help='run recursively over directories') + parser.add_argument('files', metavar='file', nargs='+') + parser.add_argument( + '-q', + '--quiet', + action='store_true') + parser.add_argument( + '-j', + metavar='N', + type=int, + default=0, + help='run N clang-format jobs in parallel' + ' (default number of cpus + 1)') + parser.add_argument( + '--color', + default='auto', + choices=['auto', 'always', 'never'], + help='show colored diff (default: auto)') + parser.add_argument( + '-e', + '--exclude', + metavar='PATTERN', + action='append', + default=[], + help='exclude paths matching the given glob-like pattern(s)' + ' from recursive search') + + args = parser.parse_args() + + # use default signal handling, like diff return SIGINT value on ^C + # https://bugs.python.org/issue14229#msg156446 + signal.signal(signal.SIGINT, signal.SIG_DFL) + try: + signal.SIGPIPE + except AttributeError: + # compatibility, SIGPIPE does not exist on Windows + pass + else: + signal.signal(signal.SIGPIPE, signal.SIG_DFL) + + colored_stdout = False + colored_stderr = False + if args.color == 'always': + colored_stdout = True + colored_stderr = True + elif args.color == 'auto': + colored_stdout = sys.stdout.isatty() + colored_stderr = sys.stderr.isatty() + + version_invocation = [args.clang_format_executable, str("--version")] + try: + subprocess.check_call(version_invocation, stdout=DEVNULL) + except subprocess.CalledProcessError as e: + print_trouble(parser.prog, str(e), use_colors=colored_stderr) + return ExitStatus.TROUBLE + except OSError as e: + print_trouble( + parser.prog, + "Command '{}' failed to start: {}".format( + subprocess.list2cmdline(version_invocation), e + ), + use_colors=colored_stderr, + ) + return ExitStatus.TROUBLE + + retcode = ExitStatus.SUCCESS + files = list_files( + args.files, + recursive=args.recursive, + exclude=args.exclude, + extensions=args.extensions.split(',')) + + if not files: + return + + njobs = args.j + if njobs == 0: + njobs = multiprocessing.cpu_count() + 1 + njobs = min(len(files), njobs) + + if njobs == 1: + # execute directly instead of in a pool, + # less overhead, simpler stacktraces + it = (run_clang_format_diff_wrapper(args, file) for file in files) + pool = None + else: + pool = multiprocessing.Pool(njobs) + it = pool.imap_unordered( + partial(run_clang_format_diff_wrapper, args), files) + while True: + try: + outs, errs = next(it) + except StopIteration: + break + except DiffError as e: + print_trouble(parser.prog, str(e), use_colors=colored_stderr) + retcode = ExitStatus.TROUBLE + sys.stderr.writelines(e.errs) + except UnexpectedError as e: + print_trouble(parser.prog, str(e), use_colors=colored_stderr) + sys.stderr.write(e.formatted_traceback) + retcode = ExitStatus.TROUBLE + # stop at the first unexpected error, + # something could be very wrong, + # don't process all files unnecessarily + if pool: + pool.terminate() + break + else: + sys.stderr.writelines(errs) + if outs == []: + continue + if not args.quiet: + print_diff(outs, use_color=colored_stdout) + if retcode == ExitStatus.SUCCESS: + retcode = ExitStatus.DIFF + return retcode + + +if __name__ == '__main__': + sys.exit(main()) diff --git a/.circleci/unittest/linux/scripts/run_style_checks.sh b/.circleci/unittest/linux/scripts/run_style_checks.sh index 468fa415b5..d47bae71a7 100755 --- a/.circleci/unittest/linux/scripts/run_style_checks.sh +++ b/.circleci/unittest/linux/scripts/run_style_checks.sh @@ -1,28 +1,34 @@ #!/usr/bin/env bash -set -u +set -eux root_dir="$(git rev-parse --show-toplevel)" conda_dir="${root_dir}/conda" env_dir="${root_dir}/env" +this_dir="$( cd "$( dirname "${BASH_SOURCE[0]}" )" >/dev/null 2>&1 && pwd )" eval "$("${conda_dir}/bin/conda" shell.bash hook)" conda activate "${env_dir}" # 1. Install tools conda install flake8 +printf "Installed flake8: " +flake8 --version + clangformat_path="${root_dir}/clang-format" curl https://oss-clang-format.s3.us-east-2.amazonaws.com/linux64/clang-format-linux64 -o "${clangformat_path}" chmod +x "${clangformat_path}" +printf "Installed clang-fortmat" +"${clangformat_path}" --version # 2. Run style checks # We want to run all the style checks even if one of them fail. +set +e + exit_status=0 -printf "\x1b[34mRunning flake8: " -flake8 --version -printf "\x1b[0m\n" +printf "\x1b[34mRunning flake8:\x1b[0m\n" flake8 torchaudio test build_tools/setup_helpers status=$? exit_status="$((exit_status+status))" @@ -30,14 +36,14 @@ if [ "${status}" -ne 0 ]; then printf "\x1b[31mflake8 failed. Check the format of Python files.\x1b[0m\n" fi -printf "\x1b[34mRunning clang-format: " -./clang-format --version -printf "\x1b[0m\n" -git-clang-format --binary ./clang-format origin/master -git diff --exit-code +printf "\x1b[34mRunning clang-format:\x1b[0m\n" +"${this_dir}"/run-clang-format.py \ + -r torchaudio/csrc \ + --clang-format-executable "${clangformat_path}" \ + && git diff --exit-code status=$? exit_status="$((exit_status+status))" if [ "${status}" -ne 0 ]; then - printf "\x1b[31mC++ files are not formatted. Please use git-clang-format to format CPP files.\x1b[0m\n" + printf "\x1b[31mC++ files are not formatted. Please use clang-format to format CPP files.\x1b[0m\n" fi exit $exit_status diff --git a/test/torchaudio_unittest/batch_consistency_test.py b/test/torchaudio_unittest/batch_consistency_test.py index d4edf65e98..78e3cd62f9 100644 --- a/test/torchaudio_unittest/batch_consistency_test.py +++ b/test/torchaudio_unittest/batch_consistency_test.py @@ -283,3 +283,14 @@ def test_batch_Vol(self): # Batch then transform computed = torchaudio.transforms.Vol(gain=1.1)(waveform.repeat(3, 1, 1)) self.assertEqual(computed, expected) + + def test_batch_spectral_centroid(self): + sample_rate = 44100 + waveform = common_utils.get_whitenoise(sample_rate=sample_rate) + + # Single then transform then batch + expected = torchaudio.transforms.SpectralCentroid(sample_rate)(waveform).repeat(3, 1, 1) + + # Batch then transform + computed = torchaudio.transforms.SpectralCentroid(sample_rate)(waveform.repeat(3, 1, 1)) + self.assertEqual(computed, expected) diff --git a/test/torchaudio_unittest/librosa_compatibility_test.py b/test/torchaudio_unittest/librosa_compatibility_test.py index 92d5baff06..9e070b141a 100644 --- a/test/torchaudio_unittest/librosa_compatibility_test.py +++ b/test/torchaudio_unittest/librosa_compatibility_test.py @@ -231,6 +231,19 @@ def assert_compatibilities(self, n_fft, hop_length, power, n_mels, n_mfcc, sampl self.assertEqual( torch_mfcc.type(librosa_mfcc_tensor.dtype), librosa_mfcc_tensor, atol=5e-3, rtol=1e-5) + self.assert_compatibilities_spectral_centroid(sample_rate, n_fft, hop_length, sound, sound_librosa) + + def assert_compatibilities_spectral_centroid(self, sample_rate, n_fft, hop_length, sound, sound_librosa): + spect_centroid = torchaudio.transforms.SpectralCentroid( + sample_rate=sample_rate, n_fft=n_fft, hop_length=hop_length) + out_torch = spect_centroid(sound).squeeze().cpu() + + out_librosa = librosa.feature.spectral_centroid( + y=sound_librosa, sr=sample_rate, n_fft=n_fft, hop_length=hop_length) + out_librosa = torch.from_numpy(out_librosa)[0] + + self.assertEqual(out_torch.type(out_librosa.dtype), out_librosa, atol=1e-5, rtol=1e-5) + def test_basics1(self): kwargs = { 'n_fft': 400, diff --git a/test/torchaudio_unittest/soundfile_backend/common.py b/test/torchaudio_unittest/soundfile_backend/common.py index 4da0873fa1..8f991fb0f8 100644 --- a/test/torchaudio_unittest/soundfile_backend/common.py +++ b/test/torchaudio_unittest/soundfile_backend/common.py @@ -26,7 +26,7 @@ def skipIfFormatNotSupported(fmt): import soundfile fmts = soundfile.available_formats() - return skipIf(fmt not in fmts, f'"{fmt}" is not supported by sondfile') + return skipIf(fmt not in fmts, f'"{fmt}" is not supported by soundfile') return skipIf(True, '"soundfile" not available.') diff --git a/test/torchaudio_unittest/soundfile_backend/info_test.py b/test/torchaudio_unittest/soundfile_backend/info_test.py index 71acb20689..d4aa2b2b2e 100644 --- a/test/torchaudio_unittest/soundfile_backend/info_test.py +++ b/test/torchaudio_unittest/soundfile_backend/info_test.py @@ -1,3 +1,7 @@ +from unittest.mock import patch +import warnings +import tarfile + import torch from torchaudio.backend import _soundfile_backend as soundfile_backend from torchaudio._internal import module_utils as _mod_utils @@ -9,6 +13,8 @@ get_wav_data, save_wav, ) +# TODO refactor and move these to common location +from torchaudio_unittest.sox_io_backend.info_test import get_encoding, get_bits_per_sample from .common import skipIfFormatNotSupported, parameterize if _mod_utils.is_module_available("soundfile"): @@ -32,22 +38,8 @@ def test_wav(self, dtype, sample_rate, num_channels): assert info.sample_rate == sample_rate assert info.num_frames == sample_rate * duration assert info.num_channels == num_channels - - @parameterize( - ["float32", "int32", "int16", "uint8"], [8000, 16000], [4, 8, 16, 32], - ) - def test_wav_multiple_channels(self, dtype, sample_rate, num_channels): - """`soundfile_backend.info` can check wav file with channels more than 2 correctly""" - duration = 1 - path = self.get_temp_path("data.wav") - data = get_wav_data( - dtype, num_channels, normalize=False, num_frames=duration * sample_rate - ) - save_wav(path, data, sample_rate) - info = soundfile_backend.info(path) - assert info.sample_rate == sample_rate - assert info.num_frames == sample_rate * duration - assert info.num_channels == num_channels + assert info.bits_per_sample == get_bits_per_sample("wav", dtype) + assert info.encoding == get_encoding("wav", dtype) @parameterize([8000, 16000], [1, 2]) @skipIfFormatNotSupported("FLAC") @@ -63,6 +55,8 @@ def test_flac(self, sample_rate, num_channels): assert info.sample_rate == sample_rate assert info.num_frames == num_frames assert info.num_channels == num_channels + assert info.bits_per_sample == 16 + assert info.encoding == "FLAC" @parameterize([8000, 16000], [1, 2]) @skipIfFormatNotSupported("OGG") @@ -78,18 +72,109 @@ def test_ogg(self, sample_rate, num_channels): assert info.sample_rate == sample_rate assert info.num_frames == sample_rate * duration assert info.num_channels == num_channels + assert info.bits_per_sample == 0 + assert info.encoding == "VORBIS" - @parameterize([8000, 16000], [1, 2]) + @parameterize([8000, 16000], [1, 2], [('PCM_24', 24), ('PCM_32', 32)]) @skipIfFormatNotSupported("NIST") - def test_sphere(self, sample_rate, num_channels): + def test_sphere(self, sample_rate, num_channels, subtype_and_bit_depth): """`soundfile_backend.info` can check sph file correctly""" duration = 1 num_frames = sample_rate * duration data = torch.randn(num_frames, num_channels).numpy() path = self.get_temp_path("data.nist") - soundfile.write(path, data, sample_rate) + subtype, bits_per_sample = subtype_and_bit_depth + soundfile.write(path, data, sample_rate, subtype=subtype) info = soundfile_backend.info(path) assert info.sample_rate == sample_rate assert info.num_frames == sample_rate * duration assert info.num_channels == num_channels + assert info.bits_per_sample == bits_per_sample + assert info.encoding == "PCM_S" + + def test_unknown_subtype_warning(self): + """soundfile_backend.info issues a warning when the subtype is unknown + + This will happen if a new subtype is supported in SoundFile: the _SUBTYPE_TO_BITS_PER_SAMPLE + dict should be updated. + """ + def _mock_info_func(_): + class MockSoundFileInfo: + samplerate = 8000 + frames = 356 + channels = 2 + subtype = 'UNSEEN_SUBTYPE' + format = 'UNKNOWN' + return MockSoundFileInfo() + + with patch("soundfile.info", _mock_info_func): + with warnings.catch_warnings(record=True) as w: + info = soundfile_backend.info("foo") + assert len(w) == 1 + assert "UNSEEN_SUBTYPE subtype is unknown to TorchAudio" in str(w[-1].message) + assert info.bits_per_sample == 0 + + +@skipIfNoModule("soundfile") +class TestFileObject(TempDirMixin, PytorchTestCase): + def _test_fileobj(self, ext, subtype, bits_per_sample): + """Query audio via file-like object works""" + duration = 2 + sample_rate = 16000 + num_channels = 2 + num_frames = sample_rate * duration + path = self.get_temp_path(f'test.{ext}') + + data = torch.randn(num_frames, num_channels).numpy() + soundfile.write(path, data, sample_rate, subtype=subtype) + + with open(path, 'rb') as fileobj: + info = soundfile_backend.info(fileobj) + assert info.sample_rate == sample_rate + assert info.num_frames == num_frames + assert info.num_channels == num_channels + assert info.bits_per_sample == bits_per_sample + assert info.encoding == "FLAC" if ext == 'flac' else "PCM_S" + + def test_fileobj_wav(self): + """Loading audio via file-like object works""" + self._test_fileobj('wav', 'PCM_16', 16) + + @skipIfFormatNotSupported("FLAC") + def test_fileobj_flac(self): + """Loading audio via file-like object works""" + self._test_fileobj('flac', 'PCM_16', 16) + + def _test_tarobj(self, ext, subtype, bits_per_sample): + """Query compressed audio via file-like object works""" + duration = 2 + sample_rate = 16000 + num_channels = 2 + num_frames = sample_rate * duration + audio_file = f'test.{ext}' + audio_path = self.get_temp_path(audio_file) + archive_path = self.get_temp_path('archive.tar.gz') + + data = torch.randn(num_frames, num_channels).numpy() + soundfile.write(audio_path, data, sample_rate, subtype=subtype) + + with tarfile.TarFile(archive_path, 'w') as tarobj: + tarobj.add(audio_path, arcname=audio_file) + with tarfile.TarFile(archive_path, 'r') as tarobj: + fileobj = tarobj.extractfile(audio_file) + info = soundfile_backend.info(fileobj) + assert info.sample_rate == sample_rate + assert info.num_frames == num_frames + assert info.num_channels == num_channels + assert info.bits_per_sample == bits_per_sample + assert info.encoding == "FLAC" if ext == 'flac' else "PCM_S" + + def test_tarobj_wav(self): + """Query compressed audio via file-like object works""" + self._test_tarobj('wav', 'PCM_16', 16) + + @skipIfFormatNotSupported("FLAC") + def test_tarobj_flac(self): + """Query compressed audio via file-like object works""" + self._test_tarobj('flac', 'PCM_16', 16) diff --git a/test/torchaudio_unittest/sox_effect/smoke_test.py b/test/torchaudio_unittest/sox_effect/smoke_test.py index 996c62063f..2a8d9e7ff9 100644 --- a/test/torchaudio_unittest/sox_effect/smoke_test.py +++ b/test/torchaudio_unittest/sox_effect/smoke_test.py @@ -43,7 +43,7 @@ def test_apply_effects_tensor(self, args): load_params("sox_effect_test_args.json"), name_func=lambda f, i, p: f'{f.__name__}_{i}_{p.args[0]["effects"][0][0]}', ) - def test_apply_effects(self, args): + def test_apply_effects_file(self, args): """`apply_effects_file` should return identical data as sox command""" dtype = 'int32' channels_first = True @@ -57,3 +57,23 @@ def test_apply_effects(self, args): _found, _sr = sox_effects.apply_effects_file( input_path, effects, normalize=False, channels_first=channels_first) + + @parameterized.expand( + load_params("sox_effect_test_args.json"), + name_func=lambda f, i, p: f'{f.__name__}_{i}_{p.args[0]["effects"][0][0]}', + ) + def test_apply_effects_fileobj(self, args): + """`apply_effects_file` should return identical data as sox command""" + dtype = 'int32' + channels_first = True + effects = args['effects'] + num_channels = args.get("num_channels", 2) + input_sr = args.get("input_sample_rate", 8000) + + input_path = self.get_temp_path('input.wav') + data = get_wav_data(dtype, num_channels, channels_first=channels_first) + save_wav(input_path, data, input_sr, channels_first=channels_first) + + with open(input_path, 'rb') as fileobj: + _found, _sr = sox_effects.apply_effects_file( + fileobj, effects, normalize=False, channels_first=channels_first) diff --git a/test/torchaudio_unittest/sox_effect/sox_effect_test.py b/test/torchaudio_unittest/sox_effect/sox_effect_test.py index c25e376359..ab334613e3 100644 --- a/test/torchaudio_unittest/sox_effect/sox_effect_test.py +++ b/test/torchaudio_unittest/sox_effect/sox_effect_test.py @@ -1,13 +1,19 @@ +import io import itertools from pathlib import Path +import tarfile -from torchaudio import sox_effects from parameterized import parameterized +from torchaudio import sox_effects +from torchaudio._internal import module_utils as _mod_utils from torchaudio_unittest.common_utils import ( TempDirMixin, + HttpServerMixin, PytorchTestCase, skipIfNoExtension, + skipIfNoModule, + skipIfNoExec, get_asset_path, get_sinusoid, get_wav_data, @@ -21,6 +27,10 @@ ) +if _mod_utils.is_module_available("requests"): + import requests + + @skipIfNoExtension class TestSoxEffects(PytorchTestCase): def test_init(self): @@ -262,3 +272,152 @@ def test_mp3(self): path = get_asset_path("mp3_without_ext") _, sr = sox_effects.apply_effects_file(path, effects, format="mp3") assert sr == 16000 + + +@skipIfNoExec('sox') +@skipIfNoExtension +class TestFileObject(TempDirMixin, PytorchTestCase): + @parameterized.expand([ + ('wav', None), + ('mp3', 128), + ('mp3', 320), + ('flac', 0), + ('flac', 5), + ('flac', 8), + ('vorbis', -1), + ('vorbis', 10), + ('amb', None), + ]) + def test_fileobj(self, ext, compression): + """Applying effects via file object works""" + sample_rate = 16000 + channels_first = True + effects = [['band', '300', '10']] + format_ = ext if ext in ['mp3'] else None + input_path = self.get_temp_path(f'input.{ext}') + reference_path = self.get_temp_path('reference.wav') + + sox_utils.gen_audio_file( + input_path, sample_rate, num_channels=2, compression=compression) + sox_utils.run_sox_effect( + input_path, reference_path, effects, output_bitdepth=32) + expected, expected_sr = load_wav(reference_path) + + with open(input_path, 'rb') as fileobj: + found, sr = sox_effects.apply_effects_file( + fileobj, effects, channels_first=channels_first, format=format_) + save_wav(self.get_temp_path('result.wav'), found, sr, channels_first=channels_first) + assert sr == expected_sr + self.assertEqual(found, expected) + + @parameterized.expand([ + ('wav', None), + ('mp3', 128), + ('mp3', 320), + ('flac', 0), + ('flac', 5), + ('flac', 8), + ('vorbis', -1), + ('vorbis', 10), + ('amb', None), + ]) + def test_bytesio(self, ext, compression): + """Applying effects via BytesIO object works""" + sample_rate = 16000 + channels_first = True + effects = [['band', '300', '10']] + format_ = ext if ext in ['mp3'] else None + input_path = self.get_temp_path(f'input.{ext}') + reference_path = self.get_temp_path('reference.wav') + + sox_utils.gen_audio_file( + input_path, sample_rate, num_channels=2, compression=compression) + sox_utils.run_sox_effect( + input_path, reference_path, effects, output_bitdepth=32) + expected, expected_sr = load_wav(reference_path) + + with open(input_path, 'rb') as file_: + fileobj = io.BytesIO(file_.read()) + found, sr = sox_effects.apply_effects_file( + fileobj, effects, channels_first=channels_first, format=format_) + save_wav(self.get_temp_path('result.wav'), found, sr, channels_first=channels_first) + assert sr == expected_sr + self.assertEqual(found, expected) + + @parameterized.expand([ + ('wav', None), + ('mp3', 128), + ('mp3', 320), + ('flac', 0), + ('flac', 5), + ('flac', 8), + ('vorbis', -1), + ('vorbis', 10), + ('amb', None), + ]) + def test_tarfile(self, ext, compression): + """Applying effects to compressed audio via file-like file works""" + sample_rate = 16000 + channels_first = True + effects = [['band', '300', '10']] + format_ = ext if ext in ['mp3'] else None + audio_file = f'input.{ext}' + + input_path = self.get_temp_path(audio_file) + reference_path = self.get_temp_path('reference.wav') + archive_path = self.get_temp_path('archive.tar.gz') + + sox_utils.gen_audio_file( + input_path, sample_rate, num_channels=2, compression=compression) + sox_utils.run_sox_effect( + input_path, reference_path, effects, output_bitdepth=32) + expected, expected_sr = load_wav(reference_path) + + with tarfile.TarFile(archive_path, 'w') as tarobj: + tarobj.add(input_path, arcname=audio_file) + with tarfile.TarFile(archive_path, 'r') as tarobj: + fileobj = tarobj.extractfile(audio_file) + found, sr = sox_effects.apply_effects_file( + fileobj, effects, channels_first=channels_first, format=format_) + save_wav(self.get_temp_path('result.wav'), found, sr, channels_first=channels_first) + assert sr == expected_sr + self.assertEqual(found, expected) + + +@skipIfNoExtension +@skipIfNoExec('sox') +@skipIfNoModule("requests") +class TestFileObjectHttp(HttpServerMixin, PytorchTestCase): + @parameterized.expand([ + ('wav', None), + ('mp3', 128), + ('mp3', 320), + ('flac', 0), + ('flac', 5), + ('flac', 8), + ('vorbis', -1), + ('vorbis', 10), + ('amb', None), + ]) + def test_requests(self, ext, compression): + sample_rate = 16000 + channels_first = True + effects = [['band', '300', '10']] + format_ = ext if ext in ['mp3'] else None + audio_file = f'input.{ext}' + input_path = self.get_temp_path(audio_file) + reference_path = self.get_temp_path('reference.wav') + + sox_utils.gen_audio_file( + input_path, sample_rate, num_channels=2, compression=compression) + sox_utils.run_sox_effect( + input_path, reference_path, effects, output_bitdepth=32) + expected, expected_sr = load_wav(reference_path) + + url = self.get_url(audio_file) + with requests.get(url, stream=True) as resp: + found, sr = sox_effects.apply_effects_file( + resp.raw, effects, channels_first=channels_first, format=format_) + save_wav(self.get_temp_path('result.wav'), found, sr, channels_first=channels_first) + assert sr == expected_sr + self.assertEqual(found, expected) diff --git a/test/torchaudio_unittest/sox_io_backend/info_test.py b/test/torchaudio_unittest/sox_io_backend/info_test.py index 49fc797354..9a26b0d2ea 100644 --- a/test/torchaudio_unittest/sox_io_backend/info_test.py +++ b/test/torchaudio_unittest/sox_io_backend/info_test.py @@ -1,13 +1,19 @@ +import io +import os import itertools -from parameterized import parameterized +import tarfile +from parameterized import parameterized from torchaudio.backend import sox_io_backend +from torchaudio._internal import module_utils as _mod_utils from torchaudio_unittest.common_utils import ( TempDirMixin, + HttpServerMixin, PytorchTestCase, skipIfNoExec, skipIfNoExtension, + skipIfNoModule, get_asset_path, get_wav_data, save_wav, @@ -18,6 +24,34 @@ ) +if _mod_utils.is_module_available("requests"): + import requests + + +def get_encoding(ext, dtype): + exts = { + 'mp3', + 'flac', + 'vorbis', + } + encodings = { + 'float32': 'PCM_F', + 'int32': 'PCM_S', + 'int16': 'PCM_S', + 'uint8': 'PCM_U', + } + return ext.upper() if ext in exts else encodings[dtype] + + +def get_bits_per_sample(ext, dtype): + bits_per_samples = { + 'flac': 24, + 'mp3': 0, + 'vorbis': 0, + } + return bits_per_samples.get(ext, sox_utils.get_bit_depth(dtype)) + + @skipIfNoExec('sox') @skipIfNoExtension class TestInfo(TempDirMixin, PytorchTestCase): @@ -36,6 +70,8 @@ def test_wav(self, dtype, sample_rate, num_channels): assert info.sample_rate == sample_rate assert info.num_frames == sample_rate * duration assert info.num_channels == num_channels + assert info.bits_per_sample == sox_utils.get_bit_depth(dtype) + assert info.encoding == get_encoding('wav', dtype) @parameterized.expand(list(itertools.product( ['float32', 'int32', 'int16', 'uint8'], @@ -52,6 +88,8 @@ def test_wav_multiple_channels(self, dtype, sample_rate, num_channels): assert info.sample_rate == sample_rate assert info.num_frames == sample_rate * duration assert info.num_channels == num_channels + assert info.bits_per_sample == sox_utils.get_bit_depth(dtype) + assert info.encoding == get_encoding('wav', dtype) @parameterized.expand(list(itertools.product( [8000, 16000], @@ -71,6 +109,8 @@ def test_mp3(self, sample_rate, num_channels, bit_rate): # mp3 does not preserve the number of samples # assert info.num_frames == sample_rate * duration assert info.num_channels == num_channels + assert info.bits_per_sample == 0 # bit_per_sample is irrelevant for compressed formats + assert info.encoding == "MP3" @parameterized.expand(list(itertools.product( [8000, 16000], @@ -89,6 +129,8 @@ def test_flac(self, sample_rate, num_channels, compression_level): assert info.sample_rate == sample_rate assert info.num_frames == sample_rate * duration assert info.num_channels == num_channels + assert info.bits_per_sample == 24 # FLAC standard + assert info.encoding == "FLAC" @parameterized.expand(list(itertools.product( [8000, 16000], @@ -107,23 +149,28 @@ def test_vorbis(self, sample_rate, num_channels, quality_level): assert info.sample_rate == sample_rate assert info.num_frames == sample_rate * duration assert info.num_channels == num_channels + assert info.bits_per_sample == 0 # bit_per_sample is irrelevant for compressed formats + assert info.encoding == "VORBIS" @parameterized.expand(list(itertools.product( [8000, 16000], [1, 2], + [16, 32], )), name_func=name_func) - def test_sphere(self, sample_rate, num_channels): + def test_sphere(self, sample_rate, num_channels, bits_per_sample): """`sox_io_backend.info` can check sph file correctly""" duration = 1 path = self.get_temp_path('data.sph') - sox_utils.gen_audio_file(path, sample_rate, num_channels, duration=duration) + sox_utils.gen_audio_file(path, sample_rate, num_channels, duration=duration, bit_depth=bits_per_sample) info = sox_io_backend.info(path) assert info.sample_rate == sample_rate assert info.num_frames == sample_rate * duration assert info.num_channels == num_channels + assert info.bits_per_sample == bits_per_sample + assert info.encoding == "PCM_S" @parameterized.expand(list(itertools.product( - ['float32', 'int32', 'int16', 'uint8'], + ['int32', 'int16', 'uint8'], [8000, 16000], [1, 2], )), name_func=name_func) @@ -131,13 +178,16 @@ def test_amb(self, dtype, sample_rate, num_channels): """`sox_io_backend.info` can check amb file correctly""" duration = 1 path = self.get_temp_path('data.amb') + bits_per_sample = sox_utils.get_bit_depth(dtype) sox_utils.gen_audio_file( path, sample_rate, num_channels, - bit_depth=sox_utils.get_bit_depth(dtype), duration=duration) + bit_depth=bits_per_sample, duration=duration) info = sox_io_backend.info(path) assert info.sample_rate == sample_rate assert info.num_frames == sample_rate * duration assert info.num_channels == num_channels + assert info.bits_per_sample == bits_per_sample + assert info.encoding == get_encoding("amb", dtype) def test_amr_nb(self): """`sox_io_backend.info` can check amr-nb file correctly""" @@ -146,11 +196,48 @@ def test_amr_nb(self): sample_rate = 8000 path = self.get_temp_path('data.amr-nb') sox_utils.gen_audio_file( - path, sample_rate=sample_rate, num_channels=num_channels, bit_depth=16, duration=duration) + path, sample_rate=sample_rate, num_channels=num_channels, bit_depth=16, + duration=duration) + info = sox_io_backend.info(path) + assert info.sample_rate == sample_rate + assert info.num_frames == sample_rate * duration + assert info.num_channels == num_channels + assert info.bits_per_sample == 0 + assert info.encoding == "AMR_NB" + + def test_ulaw(self): + """`sox_io_backend.info` can check ulaw file correctly""" + duration = 1 + num_channels = 1 + sample_rate = 8000 + path = self.get_temp_path('data.wav') + sox_utils.gen_audio_file( + path, sample_rate=sample_rate, num_channels=num_channels, + bit_depth=8, encoding='u-law', + duration=duration) info = sox_io_backend.info(path) assert info.sample_rate == sample_rate assert info.num_frames == sample_rate * duration assert info.num_channels == num_channels + assert info.bits_per_sample == 8 + assert info.encoding == "ULAW" + + def test_alaw(self): + """`sox_io_backend.info` can check ulaw file correctly""" + duration = 1 + num_channels = 1 + sample_rate = 8000 + path = self.get_temp_path('data.wav') + sox_utils.gen_audio_file( + path, sample_rate=sample_rate, num_channels=num_channels, + bit_depth=8, encoding='a-law', + duration=duration) + info = sox_io_backend.info(path) + assert info.sample_rate == sample_rate + assert info.num_frames == sample_rate * duration + assert info.num_channels == num_channels + assert info.bits_per_sample == 8 + assert info.encoding == "ALAW" @skipIfNoExtension @@ -167,6 +254,8 @@ def test_opus(self, bitrate, num_channels, compression_level): assert info.sample_rate == 48000 assert info.num_frames == 32768 assert info.num_channels == num_channels + assert info.bits_per_sample == 0 # bit_per_sample is irrelevant for compressed formats + assert info.encoding == "OPUS" @skipIfNoExtension @@ -184,3 +273,193 @@ def test_mp3(self): path = get_asset_path("mp3_without_ext") sinfo = sox_io_backend.info(path, format="mp3") assert sinfo.sample_rate == 16000 + assert sinfo.num_frames == 81216 + assert sinfo.num_channels == 1 + assert sinfo.bits_per_sample == 0 # bit_per_sample is irrelevant for compressed formats + assert sinfo.encoding == "MP3" + + +class FileObjTestBase(TempDirMixin): + def _gen_file(self, ext, dtype, sample_rate, num_channels, num_frames): + path = self.get_temp_path(f'test.{ext}') + bit_depth = sox_utils.get_bit_depth(dtype) + duration = num_frames / sample_rate + + sox_utils.gen_audio_file( + path, sample_rate, num_channels=num_channels, + encoding=sox_utils.get_encoding(dtype), + bit_depth=bit_depth, + duration=duration) + return path + + +@skipIfNoExtension +@skipIfNoExec('sox') +class TestFileObject(FileObjTestBase, PytorchTestCase): + def _query_fileobj(self, ext, dtype, sample_rate, num_channels, num_frames): + path = self._gen_file(ext, dtype, sample_rate, num_channels, num_frames) + format_ = ext if ext in ['mp3'] else None + with open(path, 'rb') as fileobj: + return sox_io_backend.info(fileobj, format_) + + def _query_bytesio(self, ext, dtype, sample_rate, num_channels, num_frames): + path = self._gen_file(ext, dtype, sample_rate, num_channels, num_frames) + format_ = ext if ext in ['mp3'] else None + with open(path, 'rb') as file_: + fileobj = io.BytesIO(file_.read()) + return sox_io_backend.info(fileobj, format_) + + def _query_tarfile(self, ext, dtype, sample_rate, num_channels, num_frames): + audio_path = self._gen_file(ext, dtype, sample_rate, num_channels, num_frames) + audio_file = os.path.basename(audio_path) + archive_path = self.get_temp_path('archive.tar.gz') + with tarfile.TarFile(archive_path, 'w') as tarobj: + tarobj.add(audio_path, arcname=audio_file) + format_ = ext if ext in ['mp3'] else None + with tarfile.TarFile(archive_path, 'r') as tarobj: + fileobj = tarobj.extractfile(audio_file) + return sox_io_backend.info(fileobj, format_) + + @parameterized.expand([ + ('wav', "float32"), + ('wav', "int32"), + ('wav', "int16"), + ('wav', "uint8"), + ('mp3', "float32"), + ('flac', "float32"), + ('vorbis', "float32"), + ('amb', "int16"), + ]) + def test_fileobj(self, ext, dtype): + """Querying audio via file object works""" + sample_rate = 16000 + num_frames = 3 * sample_rate + num_channels = 2 + sinfo = self._query_fileobj(ext, dtype, sample_rate, num_channels, num_frames) + + bits_per_sample = get_bits_per_sample(ext, dtype) + num_frames = 0 if ext in ['mp3', 'vorbis'] else num_frames + + assert sinfo.sample_rate == sample_rate + assert sinfo.num_channels == num_channels + assert sinfo.num_frames == num_frames + assert sinfo.bits_per_sample == bits_per_sample + assert sinfo.encoding == get_encoding(ext, dtype) + + @parameterized.expand([ + ('wav', "float32"), + ('wav', "int32"), + ('wav', "int16"), + ('wav', "uint8"), + ('mp3', "float32"), + ('flac', "float32"), + ('vorbis', "float32"), + ('amb', "int16"), + ]) + def test_bytesio(self, ext, dtype): + """Querying audio via ByteIO object works for small data""" + sample_rate = 16000 + num_frames = 3 * sample_rate + num_channels = 2 + sinfo = self._query_bytesio(ext, dtype, sample_rate, num_channels, num_frames) + + bits_per_sample = get_bits_per_sample(ext, dtype) + num_frames = 0 if ext in ['mp3', 'vorbis'] else num_frames + + assert sinfo.sample_rate == sample_rate + assert sinfo.num_channels == num_channels + assert sinfo.num_frames == num_frames + assert sinfo.bits_per_sample == bits_per_sample + assert sinfo.encoding == get_encoding(ext, dtype) + + @parameterized.expand([ + ('wav', "float32"), + ('wav', "int32"), + ('wav', "int16"), + ('wav', "uint8"), + ('mp3', "float32"), + ('flac', "float32"), + ('vorbis', "float32"), + ('amb', "int16"), + ]) + def test_bytesio_tiny(self, ext, dtype): + """Querying audio via ByteIO object works for small data""" + sample_rate = 8000 + num_frames = 4 + num_channels = 2 + sinfo = self._query_bytesio(ext, dtype, sample_rate, num_channels, num_frames) + + bits_per_sample = get_bits_per_sample(ext, dtype) + num_frames = 0 if ext in ['mp3', 'vorbis'] else num_frames + + assert sinfo.sample_rate == sample_rate + assert sinfo.num_channels == num_channels + assert sinfo.num_frames == num_frames + assert sinfo.bits_per_sample == bits_per_sample + assert sinfo.encoding == get_encoding(ext, dtype) + + @parameterized.expand([ + ('wav', "float32"), + ('wav', "int32"), + ('wav', "int16"), + ('wav', "uint8"), + ('mp3', "float32"), + ('flac', "float32"), + ('vorbis', "float32"), + ('amb', "int16"), + ]) + def test_tarfile(self, ext, dtype): + """Querying compressed audio via file-like object works""" + sample_rate = 16000 + num_frames = 3.0 * sample_rate + num_channels = 2 + sinfo = self._query_tarfile(ext, dtype, sample_rate, num_channels, num_frames) + + bits_per_sample = get_bits_per_sample(ext, dtype) + num_frames = 0 if ext in ['mp3', 'vorbis'] else num_frames + + assert sinfo.sample_rate == sample_rate + assert sinfo.num_channels == num_channels + assert sinfo.num_frames == num_frames + assert sinfo.bits_per_sample == bits_per_sample + assert sinfo.encoding == get_encoding(ext, dtype) + + +@skipIfNoExtension +@skipIfNoExec('sox') +@skipIfNoModule("requests") +class TestFileObjectHttp(HttpServerMixin, FileObjTestBase, PytorchTestCase): + def _query_http(self, ext, dtype, sample_rate, num_channels, num_frames): + audio_path = self._gen_file(ext, dtype, sample_rate, num_channels, num_frames) + audio_file = os.path.basename(audio_path) + + url = self.get_url(audio_file) + format_ = ext if ext in ['mp3'] else None + with requests.get(url, stream=True) as resp: + return sox_io_backend.info(resp.raw, format=format_) + + @parameterized.expand([ + ('wav', "float32"), + ('wav', "int32"), + ('wav', "int16"), + ('wav', "uint8"), + ('mp3', "float32"), + ('flac', "float32"), + ('vorbis', "float32"), + ('amb', "int16"), + ]) + def test_requests(self, ext, dtype): + """Querying compressed audio via requests works""" + sample_rate = 16000 + num_frames = 3.0 * sample_rate + num_channels = 2 + sinfo = self._query_http(ext, dtype, sample_rate, num_channels, num_frames) + + bits_per_sample = get_bits_per_sample(ext, dtype) + num_frames = 0 if ext in ['mp3', 'vorbis'] else num_frames + + assert sinfo.sample_rate == sample_rate + assert sinfo.num_channels == num_channels + assert sinfo.num_frames == num_frames + assert sinfo.bits_per_sample == bits_per_sample + assert sinfo.encoding == get_encoding(ext, dtype) diff --git a/test/torchaudio_unittest/sox_io_backend/load_test.py b/test/torchaudio_unittest/sox_io_backend/load_test.py index 3a4b0ba8fe..f2a514ea61 100644 --- a/test/torchaudio_unittest/sox_io_backend/load_test.py +++ b/test/torchaudio_unittest/sox_io_backend/load_test.py @@ -380,6 +380,19 @@ def test_mp3(self): assert sr == 16000 +class CloggedFileObj: + def __init__(self, fileobj): + self.fileobj = fileobj + self.buffer = b'' + + def read(self, n): + if not self.buffer: + self.buffer += self.fileobj.read(n) + ret = self.buffer[:2] + self.buffer = self.buffer[2:] + return ret + + @skipIfNoExtension @skipIfNoExec('sox') class TestFileObject(TempDirMixin, PytorchTestCase): @@ -444,6 +457,68 @@ def test_bytesio(self, ext, compression): assert sr == sample_rate self.assertEqual(expected, found) + @parameterized.expand([ + ('wav', None), + ('mp3', 128), + ('mp3', 320), + ('flac', 0), + ('flac', 5), + ('flac', 8), + ('vorbis', -1), + ('vorbis', 10), + ('amb', None), + ]) + def test_bytesio_clogged(self, ext, compression): + """Loading audio via clogged file object returns the same result as via file path. + + This test case validates the case where fileobject returns shorter bytes than requeted. + """ + sample_rate = 16000 + format_ = ext if ext in ['mp3'] else None + path = self.get_temp_path(f'test.{ext}') + + sox_utils.gen_audio_file( + path, sample_rate, num_channels=2, + compression=compression) + expected, _ = sox_io_backend.load(path) + + with open(path, 'rb') as file_: + fileobj = CloggedFileObj(io.BytesIO(file_.read())) + found, sr = sox_io_backend.load(fileobj, format=format_) + + assert sr == sample_rate + self.assertEqual(expected, found) + + @parameterized.expand([ + ('wav', None), + ('mp3', 128), + ('mp3', 320), + ('flac', 0), + ('flac', 5), + ('flac', 8), + ('vorbis', -1), + ('vorbis', 10), + ('amb', None), + ]) + def test_bytesio_tiny(self, ext, compression): + """Loading very small audio via file object returns the same result as via file path. + """ + sample_rate = 16000 + format_ = ext if ext in ['mp3'] else None + path = self.get_temp_path(f'test.{ext}') + + sox_utils.gen_audio_file( + path, sample_rate, num_channels=2, + compression=compression, duration=1 / 1600) + expected, _ = sox_io_backend.load(path) + + with open(path, 'rb') as file_: + fileobj = io.BytesIO(file_.read()) + found, sr = sox_io_backend.load(fileobj, format=format_) + + assert sr == sample_rate + self.assertEqual(expected, found) + @parameterized.expand([ ('wav', None), ('mp3', 128), diff --git a/test/torchaudio_unittest/sox_io_backend/save_test.py b/test/torchaudio_unittest/sox_io_backend/save_test.py index 3f2faff6d4..fc378f9c70 100644 --- a/test/torchaudio_unittest/sox_io_backend/save_test.py +++ b/test/torchaudio_unittest/sox_io_backend/save_test.py @@ -1,6 +1,7 @@ import io import itertools +import torch from torchaudio.backend import sox_io_backend from parameterized import parameterized @@ -24,7 +25,7 @@ def assert_wav(self, dtype, sample_rate, num_channels, num_frames): """`sox_io_backend.save` can save wav format.""" path = self.get_temp_path('data.wav') expected = get_wav_data(dtype, num_channels, num_frames=num_frames) - sox_io_backend.save(path, expected, sample_rate) + sox_io_backend.save(path, expected, sample_rate, dtype=None) found, sr = load_wav(path) assert sample_rate == sr self.assertEqual(found, expected) @@ -68,7 +69,7 @@ def assert_mp3(self, sample_rate, num_channels, bit_rate, duration): save_wav(src_path, data, sample_rate) # 2.1. Convert the original wav to mp3 with torchaudio sox_io_backend.save( - mp3_path, load_wav(src_path)[0], sample_rate, compression=bit_rate) + mp3_path, load_wav(src_path)[0], sample_rate, compression=bit_rate, dtype=None) # 2.2. Convert the mp3 to wav with Sox sox_utils.convert_audio_file(mp3_path, wav_path) # 2.3. Load @@ -99,7 +100,7 @@ def assert_flac(self, sample_rate, num_channels, compression_level, duration): save_wav(src_path, data, sample_rate) # 2.1. Convert the original wav to flac with torchaudio sox_io_backend.save( - flc_path, load_wav(src_path)[0], sample_rate, compression=compression_level) + flc_path, load_wav(src_path)[0], sample_rate, compression=compression_level, dtype=None) # 2.2. Convert the flac to wav with Sox # converting to 32 bit because flac file has 24 bit depth which scipy cannot handle. sox_utils.convert_audio_file(flc_path, wav_path, bit_depth=32) @@ -132,7 +133,7 @@ def _assert_vorbis(self, sample_rate, num_channels, quality_level, duration): save_wav(src_path, data, sample_rate) # 2.1. Convert the original wav to vorbis with torchaudio sox_io_backend.save( - vbs_path, load_wav(src_path)[0], sample_rate, compression=quality_level) + vbs_path, load_wav(src_path)[0], sample_rate, compression=quality_level, dtype=None) # 2.2. Convert the vorbis to wav with Sox sox_utils.convert_audio_file(vbs_path, wav_path) # 2.3. Load @@ -184,7 +185,7 @@ def assert_sphere(self, sample_rate, num_channels, duration): data = get_wav_data('float32', num_channels, normalize=True, num_frames=duration * sample_rate) save_wav(src_path, data, sample_rate) # 2.1. Convert the original wav to sph with torchaudio - sox_io_backend.save(flc_path, load_wav(src_path)[0], sample_rate) + sox_io_backend.save(flc_path, load_wav(src_path)[0], sample_rate, dtype=None) # 2.2. Convert the sph to wav with Sox # converting to 32 bit because sph file has 24 bit depth which scipy cannot handle. sox_utils.convert_audio_file(flc_path, wav_path, bit_depth=32) @@ -216,7 +217,7 @@ def assert_amb(self, dtype, sample_rate, num_channels, duration): data = get_wav_data(dtype, num_channels, normalize=False, num_frames=duration * sample_rate) save_wav(src_path, data, sample_rate) # 2.1. Convert the original wav to amb with torchaudio - sox_io_backend.save(amb_path, load_wav(src_path, normalize=False)[0], sample_rate) + sox_io_backend.save(amb_path, load_wav(src_path, normalize=False)[0], sample_rate, dtype=None) # 2.2. Convert the amb to wav with Sox sox_utils.convert_audio_file(amb_path, wav_path) # 2.3. Load @@ -248,7 +249,7 @@ def assert_amr_nb(self, duration): data = get_wav_data('int16', num_channels, normalize=False, num_frames=duration * sample_rate) save_wav(src_path, data, sample_rate) # 2.1. Convert the original wav to amr_nb with torchaudio - sox_io_backend.save(amr_path, load_wav(src_path, normalize=False)[0], sample_rate) + sox_io_backend.save(amr_path, load_wav(src_path, normalize=False)[0], sample_rate, dtype=None) # 2.2. Convert the amr_nb to wav with Sox sox_utils.convert_audio_file(amr_path, wav_path) # 2.3. Load @@ -389,7 +390,7 @@ def test_channels_first(self, channels_first): path = self.get_temp_path('data.wav') data = get_wav_data('int32', 2, channels_first=channels_first) sox_io_backend.save( - path, data, 8000, channels_first=channels_first) + path, data, 8000, channels_first=channels_first, dtype=None) found = load_wav(path)[0] expected = data if channels_first else data.transpose(1, 0) self.assertEqual(found, expected) @@ -402,7 +403,7 @@ def test_noncontiguous(self, dtype): path = self.get_temp_path('data.wav') expected = get_wav_data(dtype, 4)[::2, ::2] assert not expected.is_contiguous() - sox_io_backend.save(path, expected, 8000) + sox_io_backend.save(path, expected, 8000, dtype=None) found = load_wav(path)[0] self.assertEqual(found, expected) @@ -415,10 +416,24 @@ def test_tensor_preserve(self, dtype): expected = get_wav_data(dtype, 4)[::2, ::2] data = expected.clone() - sox_io_backend.save(path, data, 8000) + sox_io_backend.save(path, data, 8000, dtype=None) self.assertEqual(data, expected) + @parameterized.expand([ + ('float32', torch.tensor([-1.0, -0.5, 0, 0.5, 1.0]).to(torch.float32)), + ('int32', torch.tensor([-2147483648, -1073741824, 0, 1073741824, 2147483647]).to(torch.int32)), + ('int16', torch.tensor([-32768, -16384, 0, 16384, 32767]).to(torch.int16)), + ('uint8', torch.tensor([0, 64, 128, 192, 255]).to(torch.uint8)), + ]) + def test_dtype_conversion(self, dtype, expected): + """`save` performs dtype conversion on float32 src tensors only.""" + path = self.get_temp_path("data.wav") + data = torch.tensor([-1.0, -0.5, 0, 0.5, 1.0]).to(torch.float32).view(-1, 1) + sox_io_backend.save(path, data, 8000, dtype=dtype) + found = load_wav(path, normalize=False)[0] + self.assertEqual(found, expected.view(-1, 1)) + @skipIfNoExtension @skipIfNoExec('sox') @@ -452,11 +467,11 @@ def test_fileobj(self, ext, compression): res_path = self.get_temp_path(f'test.{ext}') sox_io_backend.save( ref_path, data, channels_first=channels_first, - sample_rate=sample_rate, compression=compression) + sample_rate=sample_rate, compression=compression, dtype=None) with open(res_path, 'wb') as fileobj: sox_io_backend.save( fileobj, data, channels_first=channels_first, - sample_rate=sample_rate, compression=compression, format=ext) + sample_rate=sample_rate, compression=compression, format=ext, dtype=None) expected_data, _ = sox_io_backend.load(ref_path) data, sr = sox_io_backend.load(res_path) @@ -489,11 +504,11 @@ def test_bytesio(self, ext, compression): res_path = self.get_temp_path(f'test.{ext}') sox_io_backend.save( ref_path, data, channels_first=channels_first, - sample_rate=sample_rate, compression=compression) + sample_rate=sample_rate, compression=compression, dtype=None) fileobj = io.BytesIO() sox_io_backend.save( fileobj, data, channels_first=channels_first, - sample_rate=sample_rate, compression=compression, format=ext) + sample_rate=sample_rate, compression=compression, format=ext, dtype=None) fileobj.seek(0) with open(res_path, 'wb') as file_: file_.write(fileobj.read()) diff --git a/test/torchaudio_unittest/sox_io_backend/smoke_test.py b/test/torchaudio_unittest/sox_io_backend/smoke_test.py index be734afa77..598a98bd3d 100644 --- a/test/torchaudio_unittest/sox_io_backend/smoke_test.py +++ b/test/torchaudio_unittest/sox_io_backend/smoke_test.py @@ -1,3 +1,4 @@ +import io import itertools import unittest @@ -85,3 +86,70 @@ def test_vorbis(self, sample_rate, num_channels, quality_level): def test_flac(self, sample_rate, num_channels, compression_level): """Run smoke test on flac format""" self.run_smoke_test('flac', sample_rate, num_channels, compression=compression_level) + + +@skipIfNoExtension +class SmokeTestFileObj(TorchaudioTestCase): + """Run smoke test on various audio format + + The purpose of this test suite is to verify that sox_io_backend functionalities do not exhibit + abnormal behaviors. + + This test suite should be able to run without any additional tools (such as sox command), + however without such tools, the correctness of each function cannot be verified. + """ + def run_smoke_test(self, ext, sample_rate, num_channels, *, compression=None, dtype='float32'): + duration = 1 + num_frames = sample_rate * duration + original = get_wav_data(dtype, num_channels, normalize=False, num_frames=num_frames) + + fileobj = io.BytesIO() + # 1. run save + sox_io_backend.save(fileobj, original, sample_rate, compression=compression, format=ext) + # 2. run info + fileobj.seek(0) + info = sox_io_backend.info(fileobj, format=ext) + assert info.sample_rate == sample_rate + assert info.num_channels == num_channels + # 3. run load + fileobj.seek(0) + loaded, sr = sox_io_backend.load(fileobj, normalize=False, format=ext) + assert sr == sample_rate + assert loaded.shape[0] == num_channels + + @parameterized.expand(list(itertools.product( + ['float32', 'int32', 'int16', 'uint8'], + [8000, 16000], + [1, 2], + )), name_func=name_func) + def test_wav(self, dtype, sample_rate, num_channels): + """Run smoke test on wav format""" + self.run_smoke_test('wav', sample_rate, num_channels, dtype=dtype) + + @parameterized.expand(list(itertools.product( + [8000, 16000], + [1, 2], + [-4.2, -0.2, 0, 0.2, 96, 128, 160, 192, 224, 256, 320], + ))) + @skipIfNoMP3 + def test_mp3(self, sample_rate, num_channels, bit_rate): + """Run smoke test on mp3 format""" + self.run_smoke_test('mp3', sample_rate, num_channels, compression=bit_rate) + + @parameterized.expand(list(itertools.product( + [8000, 16000], + [1, 2], + [-1, 0, 1, 2, 3, 3.6, 5, 10], + ))) + def test_vorbis(self, sample_rate, num_channels, quality_level): + """Run smoke test on vorbis format""" + self.run_smoke_test('vorbis', sample_rate, num_channels, compression=quality_level) + + @parameterized.expand(list(itertools.product( + [8000, 16000], + [1, 2], + list(range(9)), + )), name_func=name_func) + def test_flac(self, sample_rate, num_channels, compression_level): + """Run smoke test on flac format""" + self.run_smoke_test('flac', sample_rate, num_channels, compression=compression_level) diff --git a/test/torchaudio_unittest/torchscript_consistency_impl.py b/test/torchaudio_unittest/torchscript_consistency_impl.py index 82c6a300a6..ab681b999b 100644 --- a/test/torchaudio_unittest/torchscript_consistency_impl.py +++ b/test/torchaudio_unittest/torchscript_consistency_impl.py @@ -535,6 +535,20 @@ def func(tensor): self._assert_consistency(func, waveform) + def test_spectral_centroid(self): + + def func(tensor): + sample_rate = 44100 + n_fft = 400 + ws = 400 + hop = 200 + pad = 0 + window = torch.hann_window(ws, device=tensor.device, dtype=tensor.dtype) + return F.spectral_centroid(tensor, sample_rate, pad, window, n_fft, hop, ws) + + tensor = common_utils.get_whitenoise(sample_rate=44100) + self._assert_consistency(func, tensor) + class Transforms(common_utils.TestBaseMixin): """Implements test for Transforms that are performed for different devices""" @@ -624,3 +638,8 @@ def test_Vad(self): filepath = common_utils.get_asset_path("vad-go-mono-32000.wav") waveform, sample_rate = common_utils.load_wav(filepath) self._assert_consistency(T.Vad(sample_rate=sample_rate), waveform) + + def test_SpectralCentroid(self): + sample_rate = 44100 + waveform = common_utils.get_whitenoise(sample_rate=sample_rate) + self._assert_consistency(T.SpectralCentroid(sample_rate=sample_rate), waveform) diff --git a/test/torchaudio_unittest/transforms_test.py b/test/torchaudio_unittest/transforms_test.py index 4a91d40bd9..76628b1315 100644 --- a/test/torchaudio_unittest/transforms_test.py +++ b/test/torchaudio_unittest/transforms_test.py @@ -219,3 +219,19 @@ def test_compute_deltas_twochannel(self): computed = transform(specgram) assert computed.shape == expected.shape, (computed.shape, expected.shape) self.assertEqual(computed, expected, atol=1e-6, rtol=1e-8) + + +class SmokeTest(common_utils.TorchaudioTestCase): + + def test_spectrogram(self): + specgram = transforms.Spectrogram(center=False, pad_mode="reflect", onesided=False) + self.assertEqual(specgram.center, False) + self.assertEqual(specgram.pad_mode, "reflect") + self.assertEqual(specgram.onesided, False) + + def test_melspectrogram(self): + melspecgram = transforms.MelSpectrogram(center=True, pad_mode="reflect", onesided=False) + specgram = melspecgram.spectrogram + self.assertEqual(specgram.center, True) + self.assertEqual(specgram.pad_mode, "reflect") + self.assertEqual(specgram.onesided, False) diff --git a/third_party/sox/CMakeLists.txt b/third_party/sox/CMakeLists.txt index dcad72bbfe..930b84496a 100644 --- a/third_party/sox/CMakeLists.txt +++ b/third_party/sox/CMakeLists.txt @@ -1,6 +1,6 @@ include(ExternalProject) -set(INSTALL_DIR ${PROJECT_SOURCE_DIR}/install) +set(INSTALL_DIR ${CMAKE_CURRENT_SOURCE_DIR}/../install) set(ARCHIVE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/archives) set(COMMON_ARGS --quiet --disable-shared --enable-static --prefix=${INSTALL_DIR} --with-pic --disable-dependency-tracking --disable-debug --disable-examples --disable-doc) @@ -21,6 +21,14 @@ ExternalProject_Add(mad URL_HASH SHA256=bbfac3ed6bfbc2823d3775ebb931087371e142bb0e9bb1bee51a76a6e0078690 PATCH_COMMAND patch < ${CMAKE_CURRENT_SOURCE_DIR}/patch/libmad.patch CONFIGURE_COMMAND ${CMAKE_COMMAND} -E env ${envs} ${CMAKE_CURRENT_BINARY_DIR}/src/mad/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(amr @@ -29,6 +37,14 @@ ExternalProject_Add(amr URL https://sourceforge.net/projects/opencore-amr/files/opencore-amr/opencore-amr-0.1.5.tar.gz URL_HASH SHA256=2c006cb9d5f651bfb5e60156dbff6af3c9d35c7bbcc9015308c0aff1e14cd341 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 @@ -37,6 +53,14 @@ ExternalProject_Add(lame URL https://downloads.sourceforge.net/project/lame/lame/3.99/lame-3.99.5.tar.gz URL_HASH SHA256=24346b4158e4af3bd9f2e194bb23eb473c75fb7377011523353196b19b9a23ff 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 @@ -45,6 +69,14 @@ ExternalProject_Add(ogg URL https://ftp.osuosl.org/pub/xiph/releases/ogg/libogg-1.3.3.tar.gz URL_HASH SHA256=c2e8a485110b97550f453226ec644ebac6cb29d1caef2902c007edab4308d985 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 @@ -54,6 +86,14 @@ ExternalProject_Add(flac URL https://ftp.osuosl.org/pub/xiph/releases/flac/flac-1.3.2.tar.xz URL_HASH SHA256=91cfc3ed61dc40f47f050a109b08610667d73477af6ef36dcad31c31a4a8d53f 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 @@ -63,6 +103,14 @@ ExternalProject_Add(vorbis URL https://ftp.osuosl.org/pub/xiph/releases/vorbis/libvorbis-1.3.6.tar.gz URL_HASH SHA256=6ed40e0241089a42c48604dc00e362beee00036af2d8b3f46338031c9e0351cb 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 @@ -72,6 +120,14 @@ ExternalProject_Add(opus URL https://ftp.osuosl.org/pub/xiph/releases/opus/opus-1.3.1.tar.gz URL_HASH SHA256=65b58e1e25b2a114157014736a3d9dfeaad8d41be1c8179866f144a2fb44ff9d 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 @@ -81,15 +137,73 @@ ExternalProject_Add(opusfile URL https://ftp.osuosl.org/pub/xiph/releases/opus/opusfile-0.12.tar.gz URL_HASH SHA256=118d8601c12dd6a44f52423e68ca9083cc9f2bfe72da7a8c1acb22a80ae3550b 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 + --disable-openmp + --with-amrnb + --with-amrwb + --with-flac + --with-lame + --with-mad + --with-oggvorbis + --with-opus + --without-alsa + --without-ao + --without-coreaudio + --without-oss + --without-id3tag + --without-ladspa + --without-magic + --without-png + --without-pulseaudio + --without-sndfile + --without-sndio + --without-sunaudio + --without-waveaudio + --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/libmad.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 + ) + ExternalProject_Add(sox PREFIX ${CMAKE_CURRENT_BINARY_DIR} DEPENDS ogg flac vorbis opusfile lame mad amr 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 - # 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 - CONFIGURE_COMMAND ${CMAKE_COMMAND} -E env ${envs} ${CMAKE_CURRENT_BINARY_DIR}/src/sox/configure ${COMMON_ARGS} --with-lame --with-flac --with-mad --with-oggvorbis --without-alsa --without-coreaudio --without-png --without-oss --without-sndfile --with-opus --with-amrwb --with-amrnb --disable-openmp --without-sndio --without-pulseaudio + CONFIGURE_COMMAND ${CMAKE_COMMAND} -E env ${envs} ${CMAKE_CURRENT_BINARY_DIR}/src/sox/configure ${COMMON_ARGS} ${SOX_OPTIONS} + BUILD_BYPRODUCTS ${SOX_LIBRARIES} + 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 ) diff --git a/torchaudio/backend/_soundfile_backend.py b/torchaudio/backend/_soundfile_backend.py index 3366780bdb..e3c992b6fd 100644 --- a/torchaudio/backend/_soundfile_backend.py +++ b/torchaudio/backend/_soundfile_backend.py @@ -11,15 +11,87 @@ import soundfile +# Mapping from soundfile subtype to number of bits per sample. +# This is mostly heuristical and the value is set to 0 when it is irrelevant +# (lossy formats) or when it can't be inferred. +# For ADPCM (and G72X) subtypes, it's hard to infer the bit depth because it's not part of the standard: +# According to https://en.wikipedia.org/wiki/Adaptive_differential_pulse-code_modulation#In_telephony, +# the default seems to be 8 bits but it can be compressed further to 4 bits. +# The dict is inspired from +# https://github.com/bastibe/python-soundfile/blob/744efb4b01abc72498a96b09115b42a4cabd85e4/soundfile.py#L66-L94 +_SUBTYPE_TO_BITS_PER_SAMPLE = { + 'PCM_S8': 8, # Signed 8 bit data + 'PCM_16': 16, # Signed 16 bit data + 'PCM_24': 24, # Signed 24 bit data + 'PCM_32': 32, # Signed 32 bit data + 'PCM_U8': 8, # Unsigned 8 bit data (WAV and RAW only) + 'FLOAT': 32, # 32 bit float data + 'DOUBLE': 64, # 64 bit float data + 'ULAW': 8, # U-Law encoded. See https://en.wikipedia.org/wiki/G.711#Types + 'ALAW': 8, # A-Law encoded. See https://en.wikipedia.org/wiki/G.711#Types + 'IMA_ADPCM': 0, # IMA ADPCM. + 'MS_ADPCM': 0, # Microsoft ADPCM. + 'GSM610': 0, # GSM 6.10 encoding. (Wikipedia says 1.625 bit depth?? https://en.wikipedia.org/wiki/Full_Rate) + 'VOX_ADPCM': 0, # OKI / Dialogix ADPCM + 'G721_32': 0, # 32kbs G721 ADPCM encoding. + 'G723_24': 0, # 24kbs G723 ADPCM encoding. + 'G723_40': 0, # 40kbs G723 ADPCM encoding. + 'DWVW_12': 12, # 12 bit Delta Width Variable Word encoding. + 'DWVW_16': 16, # 16 bit Delta Width Variable Word encoding. + 'DWVW_24': 24, # 24 bit Delta Width Variable Word encoding. + 'DWVW_N': 0, # N bit Delta Width Variable Word encoding. + 'DPCM_8': 8, # 8 bit differential PCM (XI only) + 'DPCM_16': 16, # 16 bit differential PCM (XI only) + 'VORBIS': 0, # Xiph Vorbis encoding. (lossy) + 'ALAC_16': 16, # Apple Lossless Audio Codec (16 bit). + 'ALAC_20': 20, # Apple Lossless Audio Codec (20 bit). + 'ALAC_24': 24, # Apple Lossless Audio Codec (24 bit). + 'ALAC_32': 32, # Apple Lossless Audio Codec (32 bit). +} + + +def _get_bit_depth(subtype): + if subtype not in _SUBTYPE_TO_BITS_PER_SAMPLE: + warnings.warn( + f"The {subtype} subtype is unknown to TorchAudio. As a result, the bits_per_sample " + "attribute will be set to 0. If you are seeing this warning, please " + "report by opening an issue on github (after checking for existing/closed ones). " + "You may otherwise ignore this warning." + ) + return _SUBTYPE_TO_BITS_PER_SAMPLE.get(subtype, 0) + + +_SUBTYPE_TO_ENCODING = { + 'PCM_S8': 'PCM_S', + 'PCM_16': 'PCM_S', + 'PCM_24': 'PCM_S', + 'PCM_32': 'PCM_S', + 'PCM_U8': 'PCM_U', + 'FLOAT': 'PCM_F', + 'DOUBLE': 'PCM_F', + 'ULAW': 'ULAW', + 'ALAW': 'ALAW', + 'VORBIS': 'VORBIS', +} + + +def _get_encoding(format: str, subtype: str): + if format == 'FLAC': + return 'FLAC' + return _SUBTYPE_TO_ENCODING.get(subtype, 'UNKNOWN') + + @_mod_utils.requires_module("soundfile") def info(filepath: str, format: Optional[str] = None) -> AudioMetaData: """Get signal information of an audio file. Args: - filepath (str or pathlib.Path): Path to audio file. - This functionalso handles ``pathlib.Path`` objects, but is annotated as ``str`` - for the consistency with "sox_io" backend, which has a restriction on type annotation - for TorchScript compiler compatiblity. + filepath (path-like object or file-like object): + Source of audio data. + Note: + * This argument is intentionally annotated as ``str`` only, + for the consistency with "sox_io" backend, which has a restriction + on type annotation due to TorchScript compiler compatiblity. format (str, optional): Not used. PySoundFile does not accept format hint. @@ -27,7 +99,13 @@ def info(filepath: str, format: Optional[str] = None) -> AudioMetaData: AudioMetaData: meta data of the given audio. """ sinfo = soundfile.info(filepath) - return AudioMetaData(sinfo.samplerate, sinfo.frames, sinfo.channels) + return AudioMetaData( + sinfo.samplerate, + sinfo.frames, + sinfo.channels, + bits_per_sample=_get_bit_depth(sinfo.subtype), + encoding=_get_encoding(sinfo.format, sinfo.subtype), + ) _SUBTYPE2DTYPE = { diff --git a/torchaudio/backend/common.py b/torchaudio/backend/common.py index 135a18caee..c0eb90c994 100644 --- a/torchaudio/backend/common.py +++ b/torchaudio/backend/common.py @@ -12,11 +12,23 @@ class AudioMetaData: :ivar int sample_rate: Sample rate :ivar int num_frames: The number of frames :ivar int num_channels: The number of channels + :ivar int bits_per_sample: The number of bits per sample. This is 0 for lossy formats, + or when it cannot be accurately inferred. + :ivar str encoding: Audio encoding. """ - def __init__(self, sample_rate: int, num_frames: int, num_channels: int): + def __init__( + self, + sample_rate: int, + num_frames: int, + num_channels: int, + bits_per_sample: int, + encoding: str, + ): self.sample_rate = sample_rate self.num_frames = num_frames self.num_channels = num_channels + self.bits_per_sample = bits_per_sample + self.encoding = encoding @_mod_utils.deprecated('Please migrate to `AudioMetaData`.', '0.9.0') diff --git a/torchaudio/backend/sox_io_backend.py b/torchaudio/backend/sox_io_backend.py index 18296ef7e2..513bff4393 100644 --- a/torchaudio/backend/sox_io_backend.py +++ b/torchaudio/backend/sox_io_backend.py @@ -1,4 +1,5 @@ import os +import warnings from typing import Tuple, Optional import torch @@ -10,6 +11,24 @@ from .common import AudioMetaData +@torch.jit.unused +def _info( + filepath: str, + format: Optional[str] = None, +) -> AudioMetaData: + if hasattr(filepath, 'read'): + sinfo = torchaudio._torchaudio.get_info_fileobj(filepath, format) + return AudioMetaData(*sinfo) + sinfo = torch.ops.torchaudio.sox_io_get_info(os.fspath(filepath), format) + return AudioMetaData( + sinfo.get_sample_rate(), + sinfo.get_num_frames(), + sinfo.get_num_channels(), + sinfo.get_bits_per_sample(), + sinfo.get_encoding(), + ) + + @_mod_utils.requires_module('torchaudio._torchaudio') def info( filepath: str, @@ -18,9 +37,21 @@ def info( """Get signal information of an audio file. Args: - filepath (str or pathlib.Path): - Path to audio file. This function also handles ``pathlib.Path`` objects, - but is annotated as ``str`` for TorchScript compatibility. + filepath (path-like object or file-like object): + Source of audio data. When the function is not compiled by TorchScript, + (e.g. ``torch.jit.script``), the following types are accepted; + * ``path-like``: file path + * ``file-like``: Object with ``read(size: int) -> bytes`` method, + which returns byte string of at most ``size`` length. + When the function is compiled by TorchScript, only ``str`` type is allowed. + + Note: + * When the input type is file-like object, this function cannot + get the correct length (``num_samples``) for certain formats, + such as ``mp3`` and ``vorbis``. + In this case, the value of ``num_samples`` is ``0``. + * This argument is intentionally annotated as ``str`` only due to + TorchScript compiler compatibility. format (str, optional): Override the format detection with the given format. Providing the argument might help when libsox can not infer the format @@ -29,10 +60,15 @@ def info( Returns: AudioMetaData: Metadata of the given audio. """ - # Cast to str in case type is `pathlib.Path` - filepath = str(filepath) + if not torch.jit.is_scripting(): + return _info(filepath, format) sinfo = torch.ops.torchaudio.sox_io_get_info(filepath, format) - return AudioMetaData(sinfo.get_sample_rate(), sinfo.get_num_frames(), sinfo.get_num_channels()) + return AudioMetaData( + sinfo.get_sample_rate(), + sinfo.get_num_frames(), + sinfo.get_num_channels(), + sinfo.get_bits_per_sample(), + sinfo.get_encoding()) @_mod_utils.requires_module('torchaudio._torchaudio') @@ -142,15 +178,16 @@ def _save( channels_first: bool = True, compression: Optional[float] = None, format: Optional[str] = None, + dtype: Optional[str] = None, ): if hasattr(filepath, 'write'): if format is None: raise RuntimeError('`format` is required when saving to file object.') torchaudio._torchaudio.save_audio_fileobj( - filepath, src, sample_rate, channels_first, compression, format) + filepath, src, sample_rate, channels_first, compression, format, dtype) else: torch.ops.torchaudio.sox_io_save_audio_file( - os.fspath(filepath), src, sample_rate, channels_first, compression, format) + os.fspath(filepath), src, sample_rate, channels_first, compression, format, dtype) @_mod_utils.requires_module('torchaudio._torchaudio') @@ -161,6 +198,7 @@ def save( channels_first: bool = True, compression: Optional[float] = None, format: Optional[str] = None, + dtype: Optional[str] = None, ): """Save audio data to file. @@ -207,12 +245,22 @@ def save( format (str, optional): Output audio format. This is required when the output audio format cannot be infered from ``filepath``, (such as file extension or ``name`` attribute of the given file object). + dtype (str, optional) + Output tensor dtype. + Valid values: ``"uint8", "int16", "int32", "float32", "float64", None`` + ``dtype=None`` means no conversion is performed. + ``dtype`` parameter is only effective for ``float32`` Tensor. """ + if src.dtype == torch.float32 and dtype is None: + warnings.warn( + '`dtype` default value will be changed to `int16` in 0.9 release.' + 'Specify `dtype` to suppress this warning.' + ) if not torch.jit.is_scripting(): - _save(filepath, src, sample_rate, channels_first, compression, format) + _save(filepath, src, sample_rate, channels_first, compression, format, dtype) return torch.ops.torchaudio.sox_io_save_audio_file( - filepath, src, sample_rate, channels_first, compression, format) + filepath, src, sample_rate, channels_first, compression, format, dtype) @_mod_utils.requires_module('torchaudio._torchaudio') diff --git a/torchaudio/csrc/pybind.cpp b/torchaudio/csrc/pybind.cpp index eb8c30b96a..373b9d0d96 100644 --- a/torchaudio/csrc/pybind.cpp +++ b/torchaudio/csrc/pybind.cpp @@ -1,89 +1,94 @@ #include +#include #include #include - PYBIND11_MODULE(_torchaudio, m) { py::class_(m, "sox_signalinfo_t") - .def(py::init<>()) - .def("__repr__", [](const sox_signalinfo_t &self) { - std::stringstream ss; - ss << "sox_signalinfo_t {\n" - << " rate-> " << self.rate << "\n" - << " channels-> " << self.channels << "\n" - << " precision-> " << self.precision << "\n" - << " length-> " << self.length << "\n" - << " mult-> " << self.mult << "\n" - << "}\n"; - return ss.str(); - }) - .def_readwrite("rate", &sox_signalinfo_t::rate) - .def_readwrite("channels", &sox_signalinfo_t::channels) - .def_readwrite("precision", &sox_signalinfo_t::precision) - .def_readwrite("length", &sox_signalinfo_t::length) - .def_readwrite("mult", &sox_signalinfo_t::mult); + .def(py::init<>()) + .def( + "__repr__", + [](const sox_signalinfo_t& self) { + std::stringstream ss; + ss << "sox_signalinfo_t {\n" + << " rate-> " << self.rate << "\n" + << " channels-> " << self.channels << "\n" + << " precision-> " << self.precision << "\n" + << " length-> " << self.length << "\n" + << " mult-> " << self.mult << "\n" + << "}\n"; + return ss.str(); + }) + .def_readwrite("rate", &sox_signalinfo_t::rate) + .def_readwrite("channels", &sox_signalinfo_t::channels) + .def_readwrite("precision", &sox_signalinfo_t::precision) + .def_readwrite("length", &sox_signalinfo_t::length) + .def_readwrite("mult", &sox_signalinfo_t::mult); py::class_(m, "sox_encodinginfo_t") - .def(py::init<>()) - .def("__repr__", [](const sox_encodinginfo_t &self) { - std::stringstream ss; - ss << "sox_encodinginfo_t {\n" - << " encoding-> " << self.encoding << "\n" - << " bits_per_sample-> " << self.bits_per_sample << "\n" - << " compression-> " << self.compression << "\n" - << " reverse_bytes-> " << self.reverse_bytes << "\n" - << " reverse_nibbles-> " << self.reverse_nibbles << "\n" - << " reverse_bits-> " << self.reverse_bits << "\n" - << " opposite_endian-> " << self.opposite_endian << "\n" - << "}\n"; - return ss.str(); - }) - .def_readwrite("encoding", &sox_encodinginfo_t::encoding) - .def_readwrite("bits_per_sample", &sox_encodinginfo_t::bits_per_sample) - .def_readwrite("compression", &sox_encodinginfo_t::compression) - .def_readwrite("reverse_bytes", &sox_encodinginfo_t::reverse_bytes) - .def_readwrite("reverse_nibbles", &sox_encodinginfo_t::reverse_nibbles) - .def_readwrite("reverse_bits", &sox_encodinginfo_t::reverse_bits) - .def_readwrite("opposite_endian", &sox_encodinginfo_t::opposite_endian); + .def(py::init<>()) + .def( + "__repr__", + [](const sox_encodinginfo_t& self) { + std::stringstream ss; + ss << "sox_encodinginfo_t {\n" + << " encoding-> " << self.encoding << "\n" + << " bits_per_sample-> " << self.bits_per_sample << "\n" + << " compression-> " << self.compression << "\n" + << " reverse_bytes-> " << self.reverse_bytes << "\n" + << " reverse_nibbles-> " << self.reverse_nibbles << "\n" + << " reverse_bits-> " << self.reverse_bits << "\n" + << " opposite_endian-> " << self.opposite_endian << "\n" + << "}\n"; + return ss.str(); + }) + .def_readwrite("encoding", &sox_encodinginfo_t::encoding) + .def_readwrite("bits_per_sample", &sox_encodinginfo_t::bits_per_sample) + .def_readwrite("compression", &sox_encodinginfo_t::compression) + .def_readwrite("reverse_bytes", &sox_encodinginfo_t::reverse_bytes) + .def_readwrite("reverse_nibbles", &sox_encodinginfo_t::reverse_nibbles) + .def_readwrite("reverse_bits", &sox_encodinginfo_t::reverse_bits) + .def_readwrite("opposite_endian", &sox_encodinginfo_t::opposite_endian); py::enum_(m, "sox_encoding_t") - .value("SOX_ENCODING_UNKNOWN", sox_encoding_t::SOX_ENCODING_UNKNOWN) - .value("SOX_ENCODING_SIGN2", sox_encoding_t::SOX_ENCODING_SIGN2) - .value("SOX_ENCODING_UNSIGNED", sox_encoding_t::SOX_ENCODING_UNSIGNED) - .value("SOX_ENCODING_FLOAT", sox_encoding_t::SOX_ENCODING_FLOAT) - .value("SOX_ENCODING_FLOAT_TEXT", sox_encoding_t::SOX_ENCODING_FLOAT_TEXT) - .value("SOX_ENCODING_FLAC", sox_encoding_t::SOX_ENCODING_FLAC) - .value("SOX_ENCODING_HCOM", sox_encoding_t::SOX_ENCODING_HCOM) - .value("SOX_ENCODING_WAVPACK", sox_encoding_t::SOX_ENCODING_WAVPACK) - .value("SOX_ENCODING_WAVPACKF", sox_encoding_t::SOX_ENCODING_WAVPACKF) - .value("SOX_ENCODING_ULAW", sox_encoding_t::SOX_ENCODING_ULAW) - .value("SOX_ENCODING_ALAW", sox_encoding_t::SOX_ENCODING_ALAW) - .value("SOX_ENCODING_G721", sox_encoding_t::SOX_ENCODING_G721) - .value("SOX_ENCODING_G723", sox_encoding_t::SOX_ENCODING_G723) - .value("SOX_ENCODING_CL_ADPCM", sox_encoding_t::SOX_ENCODING_CL_ADPCM) - .value("SOX_ENCODING_CL_ADPCM16", sox_encoding_t::SOX_ENCODING_CL_ADPCM16) - .value("SOX_ENCODING_MS_ADPCM", sox_encoding_t::SOX_ENCODING_MS_ADPCM) - .value("SOX_ENCODING_IMA_ADPCM", sox_encoding_t::SOX_ENCODING_IMA_ADPCM) - .value("SOX_ENCODING_OKI_ADPCM", sox_encoding_t::SOX_ENCODING_OKI_ADPCM) - .value("SOX_ENCODING_DPCM", sox_encoding_t::SOX_ENCODING_DPCM) - .value("SOX_ENCODING_DWVW", sox_encoding_t::SOX_ENCODING_DWVW) - .value("SOX_ENCODING_DWVWN", sox_encoding_t::SOX_ENCODING_DWVWN) - .value("SOX_ENCODING_GSM", sox_encoding_t::SOX_ENCODING_GSM) - .value("SOX_ENCODING_MP3", sox_encoding_t::SOX_ENCODING_MP3) - .value("SOX_ENCODING_VORBIS", sox_encoding_t::SOX_ENCODING_VORBIS) - .value("SOX_ENCODING_AMR_WB", sox_encoding_t::SOX_ENCODING_AMR_WB) - .value("SOX_ENCODING_AMR_NB", sox_encoding_t::SOX_ENCODING_AMR_NB) - .value("SOX_ENCODING_LPC10", sox_encoding_t::SOX_ENCODING_LPC10) - //.value("SOX_ENCODING_OPUS", sox_encoding_t::SOX_ENCODING_OPUS) // creates a compile error - .value("SOX_ENCODINGS", sox_encoding_t::SOX_ENCODINGS) - .export_values(); + .value("SOX_ENCODING_UNKNOWN", sox_encoding_t::SOX_ENCODING_UNKNOWN) + .value("SOX_ENCODING_SIGN2", sox_encoding_t::SOX_ENCODING_SIGN2) + .value("SOX_ENCODING_UNSIGNED", sox_encoding_t::SOX_ENCODING_UNSIGNED) + .value("SOX_ENCODING_FLOAT", sox_encoding_t::SOX_ENCODING_FLOAT) + .value("SOX_ENCODING_FLOAT_TEXT", sox_encoding_t::SOX_ENCODING_FLOAT_TEXT) + .value("SOX_ENCODING_FLAC", sox_encoding_t::SOX_ENCODING_FLAC) + .value("SOX_ENCODING_HCOM", sox_encoding_t::SOX_ENCODING_HCOM) + .value("SOX_ENCODING_WAVPACK", sox_encoding_t::SOX_ENCODING_WAVPACK) + .value("SOX_ENCODING_WAVPACKF", sox_encoding_t::SOX_ENCODING_WAVPACKF) + .value("SOX_ENCODING_ULAW", sox_encoding_t::SOX_ENCODING_ULAW) + .value("SOX_ENCODING_ALAW", sox_encoding_t::SOX_ENCODING_ALAW) + .value("SOX_ENCODING_G721", sox_encoding_t::SOX_ENCODING_G721) + .value("SOX_ENCODING_G723", sox_encoding_t::SOX_ENCODING_G723) + .value("SOX_ENCODING_CL_ADPCM", sox_encoding_t::SOX_ENCODING_CL_ADPCM) + .value("SOX_ENCODING_CL_ADPCM16", sox_encoding_t::SOX_ENCODING_CL_ADPCM16) + .value("SOX_ENCODING_MS_ADPCM", sox_encoding_t::SOX_ENCODING_MS_ADPCM) + .value("SOX_ENCODING_IMA_ADPCM", sox_encoding_t::SOX_ENCODING_IMA_ADPCM) + .value("SOX_ENCODING_OKI_ADPCM", sox_encoding_t::SOX_ENCODING_OKI_ADPCM) + .value("SOX_ENCODING_DPCM", sox_encoding_t::SOX_ENCODING_DPCM) + .value("SOX_ENCODING_DWVW", sox_encoding_t::SOX_ENCODING_DWVW) + .value("SOX_ENCODING_DWVWN", sox_encoding_t::SOX_ENCODING_DWVWN) + .value("SOX_ENCODING_GSM", sox_encoding_t::SOX_ENCODING_GSM) + .value("SOX_ENCODING_MP3", sox_encoding_t::SOX_ENCODING_MP3) + .value("SOX_ENCODING_VORBIS", sox_encoding_t::SOX_ENCODING_VORBIS) + .value("SOX_ENCODING_AMR_WB", sox_encoding_t::SOX_ENCODING_AMR_WB) + .value("SOX_ENCODING_AMR_NB", sox_encoding_t::SOX_ENCODING_AMR_NB) + .value("SOX_ENCODING_LPC10", sox_encoding_t::SOX_ENCODING_LPC10) + //.value("SOX_ENCODING_OPUS", sox_encoding_t::SOX_ENCODING_OPUS) // + // creates a compile error + .value("SOX_ENCODINGS", sox_encoding_t::SOX_ENCODINGS) + .export_values(); py::enum_(m, "sox_option_t") - .value("sox_option_no", sox_option_t::sox_option_no) - .value("sox_option_yes", sox_option_t::sox_option_yes) - .value("sox_option_default", sox_option_t::sox_option_default) - .export_values(); + .value("sox_option_no", sox_option_t::sox_option_no) + .value("sox_option_yes", sox_option_t::sox_option_yes) + .value("sox_option_default", sox_option_t::sox_option_default) + .export_values(); py::enum_(m, "sox_bool") - .value("sox_false", sox_bool::sox_false) - .value("sox_true", sox_bool::sox_true) - .export_values(); + .value("sox_false", sox_bool::sox_false) + .value("sox_true", sox_bool::sox_true) + .export_values(); m.def( "read_audio_file", &torch::audio::read_audio_file, @@ -96,6 +101,10 @@ PYBIND11_MODULE(_torchaudio, m) { "get_info", &torch::audio::get_info, "Gets information about an audio file"); + m.def( + "get_info_fileobj", + &torchaudio::sox_io::get_info_fileobj, + "Get metadata of audio in file object."); m.def( "load_audio_fileobj", &torchaudio::sox_io::load_audio_fileobj, @@ -104,4 +113,8 @@ PYBIND11_MODULE(_torchaudio, m) { "save_audio_fileobj", &torchaudio::sox_io::save_audio_fileobj, "Save audio to file obj."); + m.def( + "apply_effects_fileobj", + &torchaudio::sox_effects::apply_effects_fileobj, + "Decode audio data from file-like obj and apply effects."); } diff --git a/torchaudio/csrc/sox/effects.cpp b/torchaudio/csrc/sox/effects.cpp index 03f06c2602..e195e25731 100644 --- a/torchaudio/csrc/sox/effects.cpp +++ b/torchaudio/csrc/sox/effects.cpp @@ -137,44 +137,65 @@ c10::intrusive_ptr apply_effects_file( #ifdef TORCH_API_INCLUDE_EXTENSION_H +// Streaming decoding over file-like object is tricky because libsox operates on +// FILE pointer. The folloing is what `sox` and `play` commands do +// - file input -> FILE pointer +// - URL input -> call wget in suprocess and pipe the data -> FILE pointer +// - stdin -> FILE pointer +// +// We want to, instead, fetch byte strings chunk by chunk, consume them, and +// discard. +// +// Here is the approach +// 1. Initialize sox_format_t using sox_open_mem_read, providing the initial +// chunk of byte string +// This will perform header-based format detection, if necessary, then fill +// the metadata of sox_format_t. Internally, sox_open_mem_read uses fmemopen, +// which returns FILE* which points the buffer of the provided byte string. +// 2. Each time sox reads a chunk from the FILE*, we update the underlying +// buffer in a way that it +// starts with unseen data, and append the new data read from the given +// fileobj. This will trick libsox as if it keeps reading from the FILE* +// continuously. +// For Step 2. see `fileobj_input_drain` function in effects_chain.cpp std::tuple apply_effects_fileobj( py::object fileobj, std::vector> effects, c10::optional& normalize, c10::optional& channels_first, c10::optional& format) { - - // Streaming decoding over file-like object is tricky because libsox operates on FILE pointer. - // The folloing is what `sox` and `play` commands do - // - file input -> FILE pointer - // - URL input -> call wget in suprocess and pipe the data -> FILE pointer - // - stdin -> FILE pointer + // Prepare the buffer used throughout the lifecycle of SoxEffectChain. // - // We want to, instead, fetch byte strings chunk by chunk, consume them, and discard. + // For certain format (such as FLAC), libsox keeps reading the content at + // the initialization unless it reaches EOF even when the header is properly + // parsed. (Making buffer size 8192, which is way bigger than the header, + // resulted in libsox consuming all the buffer content at the time it opens + // the file.) Therefore buffer has to always contain valid data, except after + // EOF. We default to `sox_get_globals()->bufsiz`* for buffer size and we + // first check if there is enough data to fill the buffer. `read_fileobj` + // repeatedly calls `read` method until it receives the requested length of + // bytes or it reaches EOF. If we get bytes shorter than requested, that means + // the whole audio data are fetched. // - // Here is the approach - // 1. Initialize sox_format_t using sox_open_mem_read, providing the initial chunk of byte string - // This will perform header-based format detection, if necessary, then fill the metadata of - // sox_format_t. Internally, sox_open_mem_read uses fmemopen, which returns FILE* which points the - // buffer of the provided byte string. - // 2. Each time sox reads a chunk from the FILE*, we update the underlying buffer in a way that it - // starts with unseen data, and append the new data read from the given fileobj. - // This will trick libsox as if it keeps reading from the FILE* continuously. - - // Prepare the buffer used throughout the lifecycle of SoxEffectChain. - // Using std::string and let it manage memory. - // 4096 is minimum size requried by auto_detect_format - // https://github.com/dmkrepo/libsox/blob/b9dd1a86e71bbd62221904e3e59dfaa9e5e72046/src/formats.c#L40-L48 - const size_t in_buffer_size = 4096; - std::string in_buffer(in_buffer_size, 'x'); - auto* in_buf = const_cast(in_buffer.data()); - - // Fetch the header, and copy it to the buffer. - auto header = static_cast(static_cast(fileobj.attr("read")(4096))); - memcpy(static_cast(in_buf), - static_cast(const_cast(header.data())), header.length()); + // * This can be changed with `torchaudio.utils.sox_utils.set_buffer_size`. + auto capacity = + (sox_get_globals()->bufsiz > 256) ? sox_get_globals()->bufsiz : 256; + std::string buffer(capacity, '\0'); + auto* in_buf = const_cast(buffer.data()); + auto num_read = read_fileobj(&fileobj, capacity, in_buf); + // If the file is shorter than 256, then libsox cannot read the header. + auto in_buffer_size = (num_read > 256) ? num_read : 256; // Open file (this starts reading the header) + // When opening a file there are two functions that can touches FILE*. + // * `auto_detect_format` + // https://github.com/dmkrepo/libsox/blob/b9dd1a86e71bbd62221904e3e59dfaa9e5e72046/src/formats.c#L43 + // * `startread` handler of detected format. + // https://github.com/dmkrepo/libsox/blob/b9dd1a86e71bbd62221904e3e59dfaa9e5e72046/src/formats.c#L574 + // To see the handler of a particular format, go to + // https://github.com/dmkrepo/libsox/blob/b9dd1a86e71bbd62221904e3e59dfaa9e5e72046/src/.c + // For example, voribs can be found + // https://github.com/dmkrepo/libsox/blob/b9dd1a86e71bbd62221904e3e59dfaa9e5e72046/src/vorbis.c#L97-L158 SoxFormat sf(sox_open_mem_read( in_buf, in_buffer_size, @@ -212,8 +233,7 @@ std::tuple apply_effects_fileobj( channels_first_); return std::make_tuple( - tensor, - static_cast(chain.getOutputSampleRate())); + tensor, static_cast(chain.getOutputSampleRate())); } #endif // TORCH_API_INCLUDE_EXTENSION_H diff --git a/torchaudio/csrc/sox/effects_chain.cpp b/torchaudio/csrc/sox/effects_chain.cpp index 9c365b72aa..80885b296c 100644 --- a/torchaudio/csrc/sox/effects_chain.cpp +++ b/torchaudio/csrc/sox/effects_chain.cpp @@ -123,44 +123,47 @@ int file_output_flow( } sox_effect_handler_t* get_tensor_input_handler() { - static sox_effect_handler_t handler{/*name=*/"input_tensor", - /*usage=*/NULL, - /*flags=*/SOX_EFF_MCHAN, - /*getopts=*/NULL, - /*start=*/NULL, - /*flow=*/NULL, - /*drain=*/tensor_input_drain, - /*stop=*/NULL, - /*kill=*/NULL, - /*priv_size=*/sizeof(TensorInputPriv)}; + static sox_effect_handler_t handler{ + /*name=*/"input_tensor", + /*usage=*/NULL, + /*flags=*/SOX_EFF_MCHAN, + /*getopts=*/NULL, + /*start=*/NULL, + /*flow=*/NULL, + /*drain=*/tensor_input_drain, + /*stop=*/NULL, + /*kill=*/NULL, + /*priv_size=*/sizeof(TensorInputPriv)}; return &handler; } sox_effect_handler_t* get_tensor_output_handler() { - static sox_effect_handler_t handler{/*name=*/"output_tensor", - /*usage=*/NULL, - /*flags=*/SOX_EFF_MCHAN, - /*getopts=*/NULL, - /*start=*/NULL, - /*flow=*/tensor_output_flow, - /*drain=*/NULL, - /*stop=*/NULL, - /*kill=*/NULL, - /*priv_size=*/sizeof(TensorOutputPriv)}; + static sox_effect_handler_t handler{ + /*name=*/"output_tensor", + /*usage=*/NULL, + /*flags=*/SOX_EFF_MCHAN, + /*getopts=*/NULL, + /*start=*/NULL, + /*flow=*/tensor_output_flow, + /*drain=*/NULL, + /*stop=*/NULL, + /*kill=*/NULL, + /*priv_size=*/sizeof(TensorOutputPriv)}; return &handler; } sox_effect_handler_t* get_file_output_handler() { - static sox_effect_handler_t handler{/*name=*/"output_file", - /*usage=*/NULL, - /*flags=*/SOX_EFF_MCHAN, - /*getopts=*/NULL, - /*start=*/NULL, - /*flow=*/file_output_flow, - /*drain=*/NULL, - /*stop=*/NULL, - /*kill=*/NULL, - /*priv_size=*/sizeof(FileOutputPriv)}; + static sox_effect_handler_t handler{ + /*name=*/"output_file", + /*usage=*/NULL, + /*flags=*/SOX_EFF_MCHAN, + /*getopts=*/NULL, + /*start=*/NULL, + /*flow=*/file_output_flow, + /*drain=*/NULL, + /*stop=*/NULL, + /*kill=*/NULL, + /*priv_size=*/sizeof(FileOutputPriv)}; return &handler; } @@ -198,7 +201,8 @@ void SoxEffectsChain::addInputTensor(TensorSignal* signal) { priv->signal = signal; priv->index = 0; if (sox_add_effect(sec_, e, &interm_sig_, &in_sig_) != SOX_SUCCESS) { - throw std::runtime_error("Internal Error: Failed to add effect: input_tensor"); + throw std::runtime_error( + "Internal Error: Failed to add effect: input_tensor"); } } @@ -207,7 +211,8 @@ void SoxEffectsChain::addOutputBuffer( SoxEffect e(sox_create_effect(get_tensor_output_handler())); static_cast(e->priv)->buffer = output_buffer; if (sox_add_effect(sec_, e, &interm_sig_, &in_sig_) != SOX_SUCCESS) { - throw std::runtime_error("Internal Error: Failed to add effect: output_tensor"); + throw std::runtime_error( + "Internal Error: Failed to add effect: output_tensor"); } } @@ -291,6 +296,7 @@ namespace { struct FileObjInputPriv { sox_format_t* sf; py::object* fileobj; + bool eof_reached; char* buffer; uint64_t buffer_size; }; @@ -305,47 +311,54 @@ struct FileObjOutputPriv { /// Callback function to feed byte string /// https://github.com/dmkrepo/libsox/blob/b9dd1a86e71bbd62221904e3e59dfaa9e5e72046/src/sox.h#L1268-L1278 int fileobj_input_drain(sox_effect_t* effp, sox_sample_t* obuf, size_t* osamp) { - auto priv = static_cast(effp->priv); + auto priv = static_cast(effp->priv); auto sf = priv->sf; - auto fileobj = priv->fileobj; auto buffer = priv->buffer; - auto buffer_size = priv->buffer_size; // 1. Refresh the buffer // // NOTE: // Since the underlying FILE* was opened with `fmemopen`, the only way - // libsox detect EOF is reaching the end of the buffer. (null byte won't help) - // Therefore we need to align the content at the end of buffer, otherwise, - // libsox will keep reading the content beyond intended length. + // libsox detect EOF is reaching the end of the buffer. (null byte won't + // help) Therefore we need to align the content at the end of buffer, + // otherwise, libsox will keep reading the content beyond intended length. // // Before: // - // |<--------consumed------->|<-remaining->| - // |*************************|-------------| - // ^ ftell + // |<-------consumed------>|<---remaining--->| + // |***********************|-----------------| + // ^ ftell // // After: // - // |<-offset->|<-remaining->|<--new data-->| - // |**********|-------------|++++++++++++++| + // |<-offset->|<---remaining--->|<-new data->| + // |**********|-----------------|++++++++++++| // ^ ftell - const auto num_consumed = sf->tell_off; - const auto num_remain = buffer_size - num_consumed; + // NOTE: + // Do not use `sf->tell_off` here. Presumably, `tell_off` and `fseek` are + // supposed to be in sync, but there are cases (Vorbis) they are not + // in sync and `tell_off` has seemingly uninitialized value, which + // leads num_remain to be negative and cause segmentation fault + // in `memmove`. + const auto num_consumed = ftell((FILE*)sf->fp); + if (num_consumed > priv->buffer_size) { + throw std::runtime_error("Internal Error: buffer overrun."); + } - // 1.1. First, we fetch the data to see if there is data to fill the buffer - py::bytes chunk_ = fileobj->attr("read")(num_consumed); - const auto num_refill = py::len(chunk_); - const auto offset = buffer_size - (num_remain + num_refill); + const auto num_remain = priv->buffer_size - num_consumed; - if(num_refill > num_consumed) { - std::ostringstream message; - message << "Tried to read up to " << num_consumed << " bytes but, " - << "recieved " << num_refill << " bytes. " - << "The given object does not confirm to read protocol of file object."; - throw std::runtime_error(message.str()); + // 1.1. Fetch the data to see if there is data to fill the buffer + uint64_t num_refill = 0; + std::string chunk(num_consumed, '\0'); + if (num_consumed && !priv->eof_reached) { + num_refill = read_fileobj( + priv->fileobj, num_consumed, const_cast(chunk.data())); + if (num_refill < num_consumed) { + priv->eof_reached = true; + } } + const auto offset = num_consumed - num_refill; // 1.2. Move the unconsumed data towards the beginning of buffer. if (num_remain) { @@ -356,7 +369,6 @@ int fileobj_input_drain(sox_effect_t* effp, sox_sample_t* obuf, size_t* osamp) { // 1.3. Refill the remaining buffer. if (num_refill) { - auto chunk = static_cast(chunk_); auto src = static_cast(const_cast(chunk.c_str())); auto dst = buffer + offset + num_remain; memcpy(dst, src, num_refill); @@ -364,7 +376,7 @@ int fileobj_input_drain(sox_effect_t* effp, sox_sample_t* obuf, size_t* osamp) { // 1.4. Set the file pointer to the new offset sf->tell_off = offset; - fseek ((FILE*)sf->fp, offset, SEEK_SET); + fseek((FILE*)sf->fp, offset, SEEK_SET); // 2. Perform decoding operation // The following part is practically same as "input" effect @@ -377,7 +389,9 @@ int fileobj_input_drain(sox_effect_t* effp, sox_sample_t* obuf, size_t* osamp) { // store the actual number read back to *osamp *osamp = sox_read(sf, obuf, *osamp); - return *osamp? SOX_SUCCESS : SOX_EOF; + // Decoding is finished when fileobject is exhausted and sox can no longer + // decode a sample. + return (priv->eof_reached && !*osamp) ? SOX_EOF : SOX_SUCCESS; } int fileobj_output_flow( @@ -420,30 +434,32 @@ int fileobj_output_flow( } sox_effect_handler_t* get_fileobj_input_handler() { - static sox_effect_handler_t handler{/*name=*/"input_fileobj_object", - /*usage=*/NULL, - /*flags=*/SOX_EFF_MCHAN, - /*getopts=*/NULL, - /*start=*/NULL, - /*flow=*/NULL, - /*drain=*/fileobj_input_drain, - /*stop=*/NULL, - /*kill=*/NULL, - /*priv_size=*/sizeof(FileObjInputPriv)}; + static sox_effect_handler_t handler{ + /*name=*/"input_fileobj_object", + /*usage=*/NULL, + /*flags=*/SOX_EFF_MCHAN, + /*getopts=*/NULL, + /*start=*/NULL, + /*flow=*/NULL, + /*drain=*/fileobj_input_drain, + /*stop=*/NULL, + /*kill=*/NULL, + /*priv_size=*/sizeof(FileObjInputPriv)}; return &handler; } sox_effect_handler_t* get_fileobj_output_handler() { - static sox_effect_handler_t handler{/*name=*/"output_fileobj_object", - /*usage=*/NULL, - /*flags=*/SOX_EFF_MCHAN, - /*getopts=*/NULL, - /*start=*/NULL, - /*flow=*/fileobj_output_flow, - /*drain=*/NULL, - /*stop=*/NULL, - /*kill=*/NULL, - /*priv_size=*/sizeof(FileObjOutputPriv)}; + static sox_effect_handler_t handler{ + /*name=*/"output_fileobj_object", + /*usage=*/NULL, + /*flags=*/SOX_EFF_MCHAN, + /*getopts=*/NULL, + /*start=*/NULL, + /*flow=*/fileobj_output_flow, + /*drain=*/NULL, + /*stop=*/NULL, + /*kill=*/NULL, + /*priv_size=*/sizeof(FileObjOutputPriv)}; return &handler; } @@ -461,10 +477,12 @@ void SoxEffectsChain::addInputFileObj( auto priv = static_cast(e->priv); priv->sf = sf; priv->fileobj = fileobj; + priv->eof_reached = false; priv->buffer = buffer; priv->buffer_size = buffer_size; if (sox_add_effect(sec_, e, &interm_sig_, &in_sig_) != SOX_SUCCESS) { - throw std::runtime_error("Internal Error: Failed to add effect: input fileobj"); + throw std::runtime_error( + "Internal Error: Failed to add effect: input fileobj"); } } @@ -481,7 +499,8 @@ void SoxEffectsChain::addOutputFileObj( priv->buffer = buffer; priv->buffer_size = buffer_size; if (sox_add_effect(sec_, e, &interm_sig_, &out_sig_) != SOX_SUCCESS) { - throw std::runtime_error("Internal Error: Failed to add effect: output fileobj"); + throw std::runtime_error( + "Internal Error: Failed to add effect: output fileobj"); } } diff --git a/torchaudio/csrc/sox/io.cpp b/torchaudio/csrc/sox/io.cpp index c6531eb77e..4594fa4875 100644 --- a/torchaudio/csrc/sox/io.cpp +++ b/torchaudio/csrc/sox/io.cpp @@ -13,10 +13,14 @@ namespace sox_io { SignalInfo::SignalInfo( const int64_t sample_rate_, const int64_t num_channels_, - const int64_t num_frames_) + const int64_t num_frames_, + const int64_t bits_per_sample_, + const std::string encoding_) : sample_rate(sample_rate_), num_channels(num_channels_), - num_frames(num_frames_){}; + num_frames(num_frames_), + bits_per_sample(bits_per_sample_), + encoding(encoding_){}; int64_t SignalInfo::getSampleRate() const { return sample_rate; @@ -30,7 +34,50 @@ int64_t SignalInfo::getNumFrames() const { return num_frames; } -c10::intrusive_ptr get_info( +int64_t SignalInfo::getBitsPerSample() const { + return bits_per_sample; +} + +std::string SignalInfo::getEncoding() const { + return encoding; +} + +namespace { + +std::string get_encoding(sox_encoding_t encoding) { + switch (encoding) { + case SOX_ENCODING_UNKNOWN: + return "UNKNOWN"; + case SOX_ENCODING_SIGN2: + return "PCM_S"; + case SOX_ENCODING_UNSIGNED: + return "PCM_U"; + case SOX_ENCODING_FLOAT: + return "PCM_F"; + case SOX_ENCODING_FLAC: + return "FLAC"; + case SOX_ENCODING_ULAW: + return "ULAW"; + case SOX_ENCODING_ALAW: + return "ALAW"; + case SOX_ENCODING_MP3: + return "MP3"; + case SOX_ENCODING_VORBIS: + return "VORBIS"; + case SOX_ENCODING_AMR_WB: + return "AMR_WB"; + case SOX_ENCODING_AMR_NB: + return "AMR_NB"; + case SOX_ENCODING_OPUS: + return "OPUS"; + default: + return "UNKNOWN"; + } +} + +} // namespace + +c10::intrusive_ptr get_info_file( const std::string& path, c10::optional& format) { SoxFormat sf(sox_open_read( @@ -46,7 +93,9 @@ c10::intrusive_ptr get_info( return c10::make_intrusive( static_cast(sf->signal.rate), static_cast(sf->signal.channels), - static_cast(sf->signal.length / sf->signal.channels)); + static_cast(sf->signal.length / sf->signal.channels), + static_cast(sf->encoding.bits_per_sample), + get_encoding(sf->encoding.encoding)); } namespace { @@ -100,13 +149,23 @@ void save_audio_file( int64_t sample_rate, bool channels_first, c10::optional compression, - c10::optional format) { + c10::optional format, + c10::optional dtype) { validate_input_tensor(tensor); auto signal = TensorSignal(tensor, sample_rate, channels_first); - - const auto filetype = [&](){ - if (format.has_value()) return format.value(); + if (tensor.dtype() != torch::kFloat32 && dtype.has_value()) { + throw std::runtime_error( + "dtype conversion only supported for float32 tensors"); + } + const auto tgt_dtype = + (tensor.dtype() == torch::kFloat32 && dtype.has_value()) + ? get_dtype_from_str(dtype.value()) + : tensor.dtype(); + + const auto filetype = [&]() { + if (format.has_value()) + return format.value(); return get_filetype(path); }(); if (filetype == "amr-nb") { @@ -116,7 +175,7 @@ void save_audio_file( tensor = (unnormalize_wav(tensor) / 65536).to(torch::kInt16); } const auto signal_info = get_signalinfo(&signal, filetype); - const auto encoding_info = get_encodinginfo(filetype, tensor.dtype(), compression); + const auto encoding_info = get_encodinginfo(filetype, tgt_dtype, compression); SoxFormat sf(sox_open_write( path.c_str(), @@ -140,6 +199,57 @@ void save_audio_file( #ifdef TORCH_API_INCLUDE_EXTENSION_H +std::tuple get_info_fileobj( + py::object fileobj, + c10::optional& format) { + // Prepare in-memory file object + // When libsox opens a file, it also reads the header. + // When opening a file there are two functions that might touch FILE* (and the + // underlying buffer). + // * `auto_detect_format` + // https://github.com/dmkrepo/libsox/blob/b9dd1a86e71bbd62221904e3e59dfaa9e5e72046/src/formats.c#L43 + // * `startread` handler of detected format. + // https://github.com/dmkrepo/libsox/blob/b9dd1a86e71bbd62221904e3e59dfaa9e5e72046/src/formats.c#L574 + // To see the handler of a particular format, go to + // https://github.com/dmkrepo/libsox/blob/b9dd1a86e71bbd62221904e3e59dfaa9e5e72046/src/.c + // For example, voribs can be found + // https://github.com/dmkrepo/libsox/blob/b9dd1a86e71bbd62221904e3e59dfaa9e5e72046/src/vorbis.c#L97-L158 + // + // `auto_detect_format` function only requires 256 bytes, but format-dependent + // `startread` handler might require more data. In case of vorbis, the size of + // header is unbounded, but typically 4kB maximum. + // + // "The header size is unbounded, although for streaming a rule-of-thumb of + // 4kB or less is recommended (and Xiph.Org's Vorbis encoder follows this + // suggestion)." + // + // See: + // https://xiph.org/vorbis/doc/Vorbis_I_spec.html + auto capacity = 4096; + std::string buffer(capacity, '\0'); + auto* buf = const_cast(buffer.data()); + auto num_read = read_fileobj(&fileobj, capacity, buf); + // If the file is shorter than 256, then libsox cannot read the header. + auto buf_size = (num_read > 256) ? num_read : 256; + + SoxFormat sf(sox_open_mem_read( + buf, + buf_size, + /*signal=*/nullptr, + /*encoding=*/nullptr, + /*filetype=*/format.has_value() ? format.value().c_str() : nullptr)); + + // In case of streamed data, length can be 0 + validate_input_file(sf, /*check_length=*/false); + + return std::make_tuple( + static_cast(sf->signal.rate), + static_cast(sf->signal.length / sf->signal.channels), + static_cast(sf->signal.channels), + static_cast(sf->encoding.bits_per_sample), + get_encoding(sf->encoding.encoding)); +} + std::tuple load_audio_fileobj( py::object fileobj, c10::optional& frame_offset, @@ -154,7 +264,8 @@ std::tuple load_audio_fileobj( namespace { -// helper class to automatically release buffer, to be used by save_audio_fileobj +// helper class to automatically release buffer, to be used by +// save_audio_fileobj struct AutoReleaseBuffer { char* ptr; size_t size; @@ -179,20 +290,30 @@ void save_audio_fileobj( int64_t sample_rate, bool channels_first, c10::optional compression, - std::string filetype) { + std::string filetype, + c10::optional dtype) { validate_input_tensor(tensor); auto signal = TensorSignal(tensor, sample_rate, channels_first); + if (tensor.dtype() != torch::kFloat32 && dtype.has_value()) { + throw std::runtime_error( + "dtype conversion only supported for float32 tensors"); + } + const auto tgt_dtype = + (tensor.dtype() == torch::kFloat32 && dtype.has_value()) + ? get_dtype_from_str(dtype.value()) + : tensor.dtype(); if (filetype == "amr-nb") { const auto num_channels = tensor.size(channels_first ? 0 : 1); if (num_channels != 1) { - throw std::runtime_error("amr-nb format only supports single channel audio."); + throw std::runtime_error( + "amr-nb format only supports single channel audio."); } tensor = (unnormalize_wav(tensor) / 65536).to(torch::kInt16); } const auto signal_info = get_signalinfo(&signal, filetype); - const auto encoding_info = get_encodinginfo(filetype, tensor.dtype(), compression); + const auto encoding_info = get_encodinginfo(filetype, tgt_dtype, compression); AutoReleaseBuffer buffer; @@ -205,7 +326,8 @@ void save_audio_fileobj( /*oob=*/nullptr)); if (static_cast(sf) == nullptr) { - throw std::runtime_error("Error saving audio file: failed to open memory stream."); + throw std::runtime_error( + "Error saving audio file: failed to open memory stream."); } torchaudio::sox_effects_chain::SoxEffectsChain chain( @@ -215,7 +337,8 @@ void save_audio_fileobj( chain.addOutputFileObj(sf, &buffer.ptr, &buffer.size, &fileobj); chain.run(); - // Closing the sox_format_t is necessary for flushing the last chunk to the buffer + // Closing the sox_format_t is necessary for flushing the last chunk to the + // buffer sf.close(); fileobj.attr("write")(py::bytes(buffer.ptr, buffer.size)); diff --git a/torchaudio/csrc/sox/io.h b/torchaudio/csrc/sox/io.h index ac7191527f..fa1f3d61f9 100644 --- a/torchaudio/csrc/sox/io.h +++ b/torchaudio/csrc/sox/io.h @@ -15,17 +15,23 @@ struct SignalInfo : torch::CustomClassHolder { int64_t sample_rate; int64_t num_channels; int64_t num_frames; + int64_t bits_per_sample; + std::string encoding; SignalInfo( const int64_t sample_rate_, const int64_t num_channels_, - const int64_t num_frames_); + const int64_t num_frames_, + const int64_t bits_per_sample_, + const std::string encoding_); int64_t getSampleRate() const; int64_t getNumChannels() const; int64_t getNumFrames() const; + int64_t getBitsPerSample() const; + std::string getEncoding() const; }; -c10::intrusive_ptr get_info( +c10::intrusive_ptr get_info_file( const std::string& path, c10::optional& format); @@ -43,10 +49,15 @@ void save_audio_file( int64_t sample_rate, bool channels_first, c10::optional compression, - c10::optional format); + c10::optional format, + c10::optional dtype); #ifdef TORCH_API_INCLUDE_EXTENSION_H +std::tuple get_info_fileobj( + py::object fileobj, + c10::optional& format); + std::tuple load_audio_fileobj( py::object fileobj, c10::optional& frame_offset, @@ -61,7 +72,8 @@ void save_audio_fileobj( int64_t sample_rate, bool channels_first, c10::optional compression, - std::string filetype); + std::string filetype, + c10::optional dtype); #endif // TORCH_API_INCLUDE_EXTENSION_H diff --git a/torchaudio/csrc/sox/legacy.cpp b/torchaudio/csrc/sox/legacy.cpp index 97e1d1d32b..858ad15149 100644 --- a/torchaudio/csrc/sox/legacy.cpp +++ b/torchaudio/csrc/sox/legacy.cpp @@ -40,10 +40,7 @@ int64_t write_audio(SoxDescriptor& fd, at::Tensor tensor) { return samples_written; } -void read_audio( - SoxDescriptor& fd, - at::Tensor output, - int64_t buffer_length) { +void read_audio(SoxDescriptor& fd, at::Tensor output, int64_t buffer_length) { std::vector buffer(buffer_length); int number_of_channels = fd->signal.channels; @@ -64,8 +61,7 @@ void read_audio( } // namespace std::tuple get_info( - const std::string& file_name - ) { + const std::string& file_name) { SoxDescriptor fd(sox_open_read( file_name.c_str(), /*signal=*/nullptr, @@ -86,7 +82,6 @@ int read_audio_file( sox_signalinfo_t* si, sox_encodinginfo_t* ei, const char* ft) { - SoxDescriptor fd(sox_open_read(file_name.c_str(), si, ei, ft)); if (fd.get() == nullptr) { throw std::runtime_error("Error opening audio file"); @@ -112,15 +107,16 @@ int read_audio_file( // calculate buffer length int64_t buffer_length = total_length; if (offset > 0) { - buffer_length -= offset; + buffer_length -= offset; } if (nframes > 0 && buffer_length > nframes) { - buffer_length = nframes; + buffer_length = nframes; } // seek to offset point before reading data if (sox_seek(fd.get(), offset, 0) == SOX_EOF) { - throw std::runtime_error("sox_seek reached EOF, try reducing offset or num_samples"); + throw std::runtime_error( + "sox_seek reached EOF, try reducing offset or num_samples"); } // read data and fill output tensor diff --git a/torchaudio/csrc/sox/legacy.h b/torchaudio/csrc/sox/legacy.h index 6b3f8383b2..5869695bfe 100644 --- a/torchaudio/csrc/sox/legacy.h +++ b/torchaudio/csrc/sox/legacy.h @@ -1,7 +1,8 @@ #include #include -namespace torch { namespace audio { +namespace torch { +namespace audio { /// Reads an audio file from the given `path` into the `output` `Tensor` and /// returns the sample rate of the audio file. @@ -30,9 +31,10 @@ void write_audio_file( /// Reads an audio file from the given `path` and returns a tuple of /// sox_signalinfo_t and sox_encodinginfo_t, which contain information about -/// the audio file such as sample rate, length, bit precision, encoding and more. -/// Throws `std::runtime_error` if the audio file could not be opened, or an -/// error occurred during reading of the audio data. +/// the audio file such as sample rate, length, bit precision, encoding and +/// more. Throws `std::runtime_error` if the audio file could not be opened, or +/// an error occurred during reading of the audio data. std::tuple get_info( const std::string& file_name); -}} // namespace torch::audio +} // namespace audio +} // namespace torch diff --git a/torchaudio/csrc/sox/register.cpp b/torchaudio/csrc/sox/register.cpp index 7c65bebe2d..d90a3b6df1 100644 --- a/torchaudio/csrc/sox/register.cpp +++ b/torchaudio/csrc/sox/register.cpp @@ -42,17 +42,21 @@ TORCH_LIBRARY_FRAGMENT(torchaudio, m) { m.class_("SignalInfo") .def("get_sample_rate", &torchaudio::sox_io::SignalInfo::getSampleRate) .def("get_num_channels", &torchaudio::sox_io::SignalInfo::getNumChannels) - .def("get_num_frames", &torchaudio::sox_io::SignalInfo::getNumFrames); + .def("get_num_frames", &torchaudio::sox_io::SignalInfo::getNumFrames) + .def( + "get_bits_per_sample", + &torchaudio::sox_io::SignalInfo::getBitsPerSample) + .def("get_encoding", &torchaudio::sox_io::SignalInfo::getEncoding); - m.def("torchaudio::sox_io_get_info", &torchaudio::sox_io::get_info); + m.def("torchaudio::sox_io_get_info", &torchaudio::sox_io::get_info_file); m.def( "torchaudio::sox_io_load_audio_file(" - "str path," - "int? frame_offset=None," - "int? num_frames=None," - "bool? normalize=True," - "bool? channels_first=False," - "str? format=None" + "str path," + "int? frame_offset=None," + "int? num_frames=None," + "bool? normalize=True," + "bool? channels_first=False," + "str? format=None" ") -> __torch__.torch.classes.torchaudio.TensorSignal", &torchaudio::sox_io::load_audio_file); m.def( diff --git a/torchaudio/csrc/sox/utils.cpp b/torchaudio/csrc/sox/utils.cpp index 0ea95cbbb3..f6bd3c8137 100644 --- a/torchaudio/csrc/sox/utils.cpp +++ b/torchaudio/csrc/sox/utils.cpp @@ -80,7 +80,9 @@ bool TensorSignal::getChannelsFirst() const { } SoxFormat::SoxFormat(sox_format_t* fd) noexcept : fd_(fd) {} -SoxFormat::~SoxFormat() { close(); } +SoxFormat::~SoxFormat() { + close(); +} sox_format_t* SoxFormat::operator->() const noexcept { return fd_; @@ -154,6 +156,24 @@ caffe2::TypeMeta get_dtype( return c10::scalarTypeToTypeMeta(dtype); } +caffe2::TypeMeta get_dtype_from_str(const std::string dtype) { + const auto tgt_dtype = [&]() { + if (dtype == "uint8") + return torch::kUInt8; + else if (dtype == "int16") + return torch::kInt16; + else if (dtype == "int32") + return torch::kInt32; + else if (dtype == "float32") + return torch::kFloat32; + else if (dtype == "float64") + return torch::kFloat64; + else + throw std::runtime_error("Unsupported dtype"); + }(); + return c10::scalarTypeToTypeMeta(tgt_dtype); +} + torch::Tensor convert_to_tensor( sox_sample_t* buffer, const int32_t num_samples, @@ -291,27 +311,58 @@ sox_signalinfo_t get_signalinfo( sox_encodinginfo_t get_encodinginfo( const std::string filetype, const caffe2::TypeMeta dtype) { - return sox_encodinginfo_t{/*encoding=*/get_encoding(filetype, dtype), - /*bits_per_sample=*/get_precision(filetype, dtype), - /*compression=*/HUGE_VAL, - /*reverse_bytes=*/sox_option_default, - /*reverse_nibbles=*/sox_option_default, - /*reverse_bits=*/sox_option_default, - /*opposite_endian=*/sox_false}; + return sox_encodinginfo_t{ + /*encoding=*/get_encoding(filetype, dtype), + /*bits_per_sample=*/get_precision(filetype, dtype), + /*compression=*/HUGE_VAL, + /*reverse_bytes=*/sox_option_default, + /*reverse_nibbles=*/sox_option_default, + /*reverse_bits=*/sox_option_default, + /*opposite_endian=*/sox_false}; } sox_encodinginfo_t get_encodinginfo( const std::string filetype, const caffe2::TypeMeta dtype, c10::optional& compression) { - return sox_encodinginfo_t{/*encoding=*/get_encoding(filetype, dtype), - /*bits_per_sample=*/get_precision(filetype, dtype), - /*compression=*/compression.value_or(HUGE_VAL), - /*reverse_bytes=*/sox_option_default, - /*reverse_nibbles=*/sox_option_default, - /*reverse_bits=*/sox_option_default, - /*opposite_endian=*/sox_false}; + return sox_encodinginfo_t{ + /*encoding=*/get_encoding(filetype, dtype), + /*bits_per_sample=*/get_precision(filetype, dtype), + /*compression=*/compression.value_or(HUGE_VAL), + /*reverse_bytes=*/sox_option_default, + /*reverse_nibbles=*/sox_option_default, + /*reverse_bits=*/sox_option_default, + /*opposite_endian=*/sox_false}; } +#ifdef TORCH_API_INCLUDE_EXTENSION_H + +uint64_t read_fileobj(py::object* fileobj, const uint64_t size, char* buffer) { + uint64_t num_read = 0; + while (num_read < size) { + auto request = size - num_read; + auto chunk = static_cast( + static_cast(fileobj->attr("read")(request))); + auto chunk_len = chunk.length(); + if (chunk_len == 0) { + break; + } + if (chunk_len > request) { + std::ostringstream message; + message + << "Requested up to " << request << " bytes but, " + << "received " << chunk_len << " bytes. " + << "The given object does not confirm to read protocol of file object."; + throw std::runtime_error(message.str()); + } + memcpy(buffer, chunk.data(), chunk_len); + buffer += chunk_len; + num_read += chunk_len; + } + return num_read; +} + +#endif // TORCH_API_INCLUDE_EXTENSION_H + } // namespace sox_utils } // namespace torchaudio diff --git a/torchaudio/csrc/sox/utils.h b/torchaudio/csrc/sox/utils.h index 2d434d6f72..1d99158378 100644 --- a/torchaudio/csrc/sox/utils.h +++ b/torchaudio/csrc/sox/utils.h @@ -4,6 +4,10 @@ #include #include +#ifdef TORCH_API_INCLUDE_EXTENSION_H +#include +#endif // TORCH_API_INCLUDE_EXTENSION_H + namespace torchaudio { namespace sox_utils { @@ -69,7 +73,7 @@ struct SoxFormat { /// /// Verify that input file is found, has known encoding, and not empty -void validate_input_file(const SoxFormat& sf, bool check_length=true); +void validate_input_file(const SoxFormat& sf, bool check_length = true); /// /// Verify that input Tensor is 2D, CPU and either uin8, int16, int32 or float32 @@ -81,6 +85,8 @@ caffe2::TypeMeta get_dtype( const sox_encoding_t encoding, const unsigned precision); +caffe2::TypeMeta get_dtype_from_str(const std::string dtype); + /// /// Convert sox_sample_t buffer to uint8/int16/int32/float32 Tensor /// NOTE: This function might modify the values in the input buffer to @@ -127,6 +133,12 @@ sox_encodinginfo_t get_encodinginfo( const caffe2::TypeMeta dtype, c10::optional& compression); +#ifdef TORCH_API_INCLUDE_EXTENSION_H + +uint64_t read_fileobj(py::object* fileobj, uint64_t size, char* buffer); + +#endif // TORCH_API_INCLUDE_EXTENSION_H + } // namespace sox_utils } // namespace torchaudio #endif diff --git a/torchaudio/csrc/transducer.cpp b/torchaudio/csrc/transducer.cpp index 3ca7a5ebde..f5d06c1ba9 100644 --- a/torchaudio/csrc/transducer.cpp +++ b/torchaudio/csrc/transducer.cpp @@ -8,71 +8,80 @@ namespace { -int64_t cpu_rnnt_loss(torch::Tensor acts, - torch::Tensor labels, - torch::Tensor input_lengths, - torch::Tensor label_lengths, - torch::Tensor costs, - torch::Tensor grads, - int64_t blank_label, - int64_t num_threads) { - - int maxT = acts.size(1); - int maxU = acts.size(2); - int minibatch_size = acts.size(0); - int alphabet_size = acts.size(3); - - rnntOptions options; - memset(&options, 0, sizeof(options)); - options.maxT = maxT; - options.maxU = maxU; - options.blank_label = blank_label; - options.batch_first = true; - options.loc = RNNT_CPU; - options.num_threads = num_threads; - - // have to use at least one - options.num_threads = std::max(options.num_threads, (unsigned int) 1); - - size_t cpu_size_bytes = 0; - switch (acts.scalar_type()) { - case torch::ScalarType::Float: - { - get_workspace_size(maxT, maxU, minibatch_size, - false, &cpu_size_bytes); - - std::vector cpu_workspace(cpu_size_bytes / sizeof(float), 0); - - compute_rnnt_loss(acts.data_ptr(), grads.data_ptr(), - labels.data_ptr(), label_lengths.data_ptr(), - input_lengths.data_ptr(), alphabet_size, - minibatch_size, costs.data_ptr(), - cpu_workspace.data(), options); - - return 0; - } - case torch::ScalarType::Double: - { - get_workspace_size(maxT, maxU, minibatch_size, - false, &cpu_size_bytes, - sizeof(double)); - - std::vector cpu_workspace(cpu_size_bytes / sizeof(double), 0); - - compute_rnnt_loss_fp64(acts.data_ptr(), grads.data_ptr(), - labels.data_ptr(), label_lengths.data_ptr(), - input_lengths.data_ptr(), alphabet_size, - minibatch_size, costs.data_ptr(), - cpu_workspace.data(), options); - - return 0; - } - default: - TORCH_CHECK(false, - std::string(__func__) + " not implemented for '" + toString(acts.scalar_type()) + "'" - ); +int64_t cpu_rnnt_loss( + torch::Tensor acts, + torch::Tensor labels, + torch::Tensor input_lengths, + torch::Tensor label_lengths, + torch::Tensor costs, + torch::Tensor grads, + int64_t blank_label, + int64_t num_threads) { + int maxT = acts.size(1); + int maxU = acts.size(2); + int minibatch_size = acts.size(0); + int alphabet_size = acts.size(3); + + rnntOptions options; + memset(&options, 0, sizeof(options)); + options.maxT = maxT; + options.maxU = maxU; + options.blank_label = blank_label; + options.batch_first = true; + options.loc = RNNT_CPU; + options.num_threads = num_threads; + + // have to use at least one + options.num_threads = std::max(options.num_threads, (unsigned int)1); + + size_t cpu_size_bytes = 0; + switch (acts.scalar_type()) { + case torch::ScalarType::Float: { + get_workspace_size(maxT, maxU, minibatch_size, false, &cpu_size_bytes); + + std::vector cpu_workspace(cpu_size_bytes / sizeof(float), 0); + + compute_rnnt_loss( + acts.data_ptr(), + grads.data_ptr(), + labels.data_ptr(), + label_lengths.data_ptr(), + input_lengths.data_ptr(), + alphabet_size, + minibatch_size, + costs.data_ptr(), + cpu_workspace.data(), + options); + + return 0; + } + case torch::ScalarType::Double: { + get_workspace_size( + maxT, maxU, minibatch_size, false, &cpu_size_bytes, sizeof(double)); + + std::vector cpu_workspace(cpu_size_bytes / sizeof(double), 0); + + compute_rnnt_loss_fp64( + acts.data_ptr(), + grads.data_ptr(), + labels.data_ptr(), + label_lengths.data_ptr(), + input_lengths.data_ptr(), + alphabet_size, + minibatch_size, + costs.data_ptr(), + cpu_workspace.data(), + options); + + return 0; } - return -1; + default: + TORCH_CHECK( + false, + std::string(__func__) + " not implemented for '" + + toString(acts.scalar_type()) + "'"); + } + return -1; } } // namespace @@ -82,12 +91,13 @@ TORCH_LIBRARY_IMPL(torchaudio, CPU, m) { } TORCH_LIBRARY_FRAGMENT(torchaudio, m) { - m.def("rnnt_loss(Tensor acts," - "Tensor labels," - "Tensor input_lengths," - "Tensor label_lengths," - "Tensor costs," - "Tensor grads," - "int blank_label," - "int num_threads) -> int"); + m.def( + "rnnt_loss(Tensor acts," + "Tensor labels," + "Tensor input_lengths," + "Tensor label_lengths," + "Tensor costs," + "Tensor grads," + "int blank_label," + "int num_threads) -> int"); } diff --git a/torchaudio/datasets/ljspeech.py b/torchaudio/datasets/ljspeech.py index 01d3fe7d95..99058dd83e 100644 --- a/torchaudio/datasets/ljspeech.py +++ b/torchaudio/datasets/ljspeech.py @@ -8,31 +8,15 @@ from torch import Tensor from torch.utils.data import Dataset -URL = "https://data.keithito.com/data/speech/LJSpeech-1.1.tar.bz2" -FOLDER_IN_ARCHIVE = "wavs" -_CHECKSUMS = { - "https://data.keithito.com/data/speech/LJSpeech-1.1.tar.bz2": - "be1a30453f28eb8dd26af4101ae40cbf2c50413b1bb21936cbcdc6fae3de8aa5" +_RELEASE_CONFIGS = { + "release1": { + "folder_in_archive": "wavs", + "url": "https://data.keithito.com/data/speech/LJSpeech-1.1.tar.bz2", + "checksum": "be1a30453f28eb8dd26af4101ae40cbf2c50413b1bb21936cbcdc6fae3de8aa5", + } } -def load_ljspeech_item(line: List[str], path: str, ext_audio: str) -> Tuple[Tensor, int, str, str]: - assert len(line) == 3 - fileid, transcript, normalized_transcript = line - fileid_audio = fileid + ext_audio - fileid_audio = os.path.join(path, fileid_audio) - - # Load audio - waveform, sample_rate = torchaudio.load(fileid_audio) - - return ( - waveform, - sample_rate, - transcript, - normalized_transcript, - ) - - class LJSPEECH(Dataset): """Create a Dataset for LJSpeech-1.1. @@ -46,37 +30,36 @@ class LJSPEECH(Dataset): Whether to download the dataset if it is not found at root path. (default: ``False``). """ - _ext_audio = ".wav" - _ext_archive = '.tar.bz2' - def __init__(self, root: Union[str, Path], - url: str = URL, - folder_in_archive: str = FOLDER_IN_ARCHIVE, + url: str = _RELEASE_CONFIGS["release1"]["url"], + folder_in_archive: str = _RELEASE_CONFIGS["release1"]["folder_in_archive"], download: bool = False) -> None: - # Get string representation of 'root' in case Path object is passed - root = os.fspath(root) + self._parse_filesystem(root, url, folder_in_archive, download) + + def _parse_filesystem(self, root: str, url: str, folder_in_archive: str, download: bool) -> None: + root = Path(root) basename = os.path.basename(url) - archive = os.path.join(root, basename) + archive = root / basename - basename = basename.split(self._ext_archive)[0] - folder_in_archive = os.path.join(basename, folder_in_archive) + basename = Path(basename.split(".tar.bz2")[0]) + folder_in_archive = basename / folder_in_archive - self._path = os.path.join(root, folder_in_archive) - self._metadata_path = os.path.join(root, basename, 'metadata.csv') + self._path = root / folder_in_archive + self._metadata_path = root / basename / 'metadata.csv' if download: if not os.path.isdir(self._path): if not os.path.isfile(archive): - checksum = _CHECKSUMS.get(url, None) + checksum = _RELEASE_CONFIGS["release1"]["checksum"] download_url(url, root, hash_value=checksum) extract_archive(archive) with open(self._metadata_path, "r", newline='') as metadata: - walker = csv.reader(metadata, delimiter="|", quoting=csv.QUOTE_NONE) - self._walker = list(walker) + flist = csv.reader(metadata, delimiter="|", quoting=csv.QUOTE_NONE) + self._flist = list(flist) def __getitem__(self, n: int) -> Tuple[Tensor, int, str, str]: """Load the n-th sample from the dataset. @@ -87,8 +70,19 @@ def __getitem__(self, n: int) -> Tuple[Tensor, int, str, str]: Returns: tuple: ``(waveform, sample_rate, transcript, normalized_transcript)`` """ - line = self._walker[n] - return load_ljspeech_item(line, self._path, self._ext_audio) + line = self._flist[n] + fileid, transcript, normalized_transcript = line + fileid_audio = self._path / (fileid + ".wav") + + # Load audio + waveform, sample_rate = torchaudio.load(fileid_audio) + + return ( + waveform, + sample_rate, + transcript, + normalized_transcript, + ) def __len__(self) -> int: - return len(self._walker) + return len(self._flist) diff --git a/torchaudio/functional/__init__.py b/torchaudio/functional/__init__.py index 3d1aa00f86..688708296b 100644 --- a/torchaudio/functional/__init__.py +++ b/torchaudio/functional/__init__.py @@ -16,6 +16,7 @@ phase_vocoder, sliding_window_cmn, spectrogram, + spectral_centroid, ) from .filtering import ( allpass_biquad, diff --git a/torchaudio/functional/functional.py b/torchaudio/functional/functional.py index 0c07ec0847..73941946ec 100644 --- a/torchaudio/functional/functional.py +++ b/torchaudio/functional/functional.py @@ -27,6 +27,7 @@ 'mask_along_axis', 'mask_along_axis_iid', 'sliding_window_cmn', + "spectral_centroid", ] @@ -38,7 +39,10 @@ def spectrogram( hop_length: int, win_length: int, power: Optional[float], - normalized: bool + normalized: bool, + center: bool = True, + pad_mode: str = "reflect", + onesided: bool = True ) -> Tensor: r"""Create a spectrogram or a batch of spectrograms from a raw audio signal. The spectrogram can be either magnitude-only or complex. @@ -54,6 +58,13 @@ def spectrogram( (must be > 0) e.g., 1 for energy, 2 for power, etc. If None, then the complex spectrum is returned instead. normalized (bool): Whether to normalize by magnitude after stft + center (bool, optional): whether to pad :attr:`waveform` on both sides so + that the :math:`t`-th frame is centered at time :math:`t \times \text{hop\_length}`. + Default: ``True`` + pad_mode (string, optional): controls the padding method used when + :attr:`center` is ``True``. Default: ``"reflect"`` + onesided (bool, optional): controls whether to return half of results to + avoid redundancy. Default: ``True`` Returns: Tensor: Dimension (..., freq, time), freq is @@ -76,10 +87,10 @@ def spectrogram( hop_length=hop_length, win_length=win_length, window=window, - center=True, - pad_mode="reflect", + center=center, + pad_mode=pad_mode, normalized=False, - onesided=True, + onesided=onesided, return_complex=True, ) @@ -935,3 +946,38 @@ def sliding_window_cmn( if len(input_shape) == 2: cmn_waveform = cmn_waveform.squeeze(0) return cmn_waveform + + +def spectral_centroid( + waveform: Tensor, + sample_rate: int, + pad: int, + window: Tensor, + n_fft: int, + hop_length: int, + win_length: int, +) -> Tensor: + r""" + Compute the spectral centroid for each channel along the time axis. + + The spectral centroid is defined as the weighted average of the + frequency values, weighted by their magnitude. + + Args: + waveform (Tensor): Tensor of audio of dimension (..., time) + sample_rate (int): Sample rate of the audio waveform + pad (int): Two sided padding of signal + window (Tensor): Window tensor that is applied/multiplied to each frame/window + n_fft (int): Size of FFT + hop_length (int): Length of hop between STFT windows + win_length (int): Window size + + Returns: + Tensor: Dimension (..., time) + """ + specgram = spectrogram(waveform, pad=pad, window=window, n_fft=n_fft, hop_length=hop_length, + win_length=win_length, power=1., normalized=False) + freqs = torch.linspace(0, sample_rate // 2, steps=1 + n_fft // 2, + device=specgram.device).reshape((-1, 1)) + freq_dim = -2 + return (freqs * specgram).sum(dim=freq_dim) / specgram.sum(dim=freq_dim) diff --git a/torchaudio/sox_effects/sox_effects.py b/torchaudio/sox_effects/sox_effects.py index 7534714965..d94a776cd6 100644 --- a/torchaudio/sox_effects/sox_effects.py +++ b/torchaudio/sox_effects/sox_effects.py @@ -1,7 +1,10 @@ +import os +from pathlib import Path from typing import List, Tuple, Optional import torch +import torchaudio from torchaudio._internal import module_utils as _mod_utils from torchaudio.utils.sox_utils import list_effects @@ -170,8 +173,16 @@ def apply_effects_file( rate and leave samples untouched. Args: - path (str or pathlib.Path): Path to the audio file. This function also handles ``pathlib.Path`` objects, but is - annotated as ``str`` for TorchScript compiler compatibility. + path (path-like object or file-like object): + Source of audio data. When the function is not compiled by TorchScript, + (e.g. ``torch.jit.script``), the following types are accepted; + * ``path-like``: file path + * ``file-like``: Object with ``read(size: int) -> bytes`` method, + which returns byte string of at most ``size`` length. + When the function is compiled by TorchScript, only ``str`` type is allowed. + Note: + * This argument is intentionally annotated as ``str`` only for + TorchScript compiler compatibility. effects (List[List[str]]): List of effects. normalize (bool): When ``True``, this function always return ``float32``, and sample values are @@ -252,8 +263,11 @@ def apply_effects_file( >>> for batch in loader: >>> pass """ - # Get string representation of 'path' in case Path object is passed - path = str(path) + if not torch.jit.is_scripting(): + if hasattr(path, 'read'): + return torchaudio._torchaudio.apply_effects_fileobj( + path, effects, normalize, channels_first, format) + path = os.fspath(path) signal = torch.ops.torchaudio.sox_effects_apply_effects_file( path, effects, normalize, channels_first, format) return signal.get_tensor(), signal.get_sample_rate() diff --git a/torchaudio/transforms.py b/torchaudio/transforms.py index 3306491b21..dc7e2ddfe1 100644 --- a/torchaudio/transforms.py +++ b/torchaudio/transforms.py @@ -28,6 +28,7 @@ 'TimeMasking', 'SlidingWindowCmn', 'Vad', + 'SpectralCentroid', ] @@ -46,6 +47,13 @@ class Spectrogram(torch.nn.Module): If None, then the complex spectrum is returned instead. (Default: ``2``) normalized (bool, optional): Whether to normalize by magnitude after stft. (Default: ``False``) wkwargs (dict or None, optional): Arguments for window function. (Default: ``None``) + center (bool, optional): whether to pad :attr:`waveform` on both sides so + that the :math:`t`-th frame is centered at time :math:`t \times \text{hop\_length}`. + Default: ``True`` + pad_mode (string, optional): controls the padding method used when + :attr:`center` is ``True``. Default: ``"reflect"`` + onesided (bool, optional): controls whether to return half of results to + avoid redundancy Default: ``True`` """ __constants__ = ['n_fft', 'win_length', 'hop_length', 'pad', 'power', 'normalized'] @@ -57,7 +65,10 @@ def __init__(self, window_fn: Callable[..., Tensor] = torch.hann_window, power: Optional[float] = 2., normalized: bool = False, - wkwargs: Optional[dict] = None) -> None: + wkwargs: Optional[dict] = None, + center: bool = True, + pad_mode: str = "reflect", + onesided: bool = True) -> None: super(Spectrogram, self).__init__() self.n_fft = n_fft # number of FFT bins. the returned STFT result will have n_fft // 2 + 1 @@ -69,6 +80,9 @@ def __init__(self, self.pad = pad self.power = power self.normalized = normalized + self.center = center + self.pad_mode = pad_mode + self.onesided = onesided def forward(self, waveform: Tensor) -> Tensor: r""" @@ -80,8 +94,19 @@ def forward(self, waveform: Tensor) -> Tensor: ``n_fft // 2 + 1`` where ``n_fft`` is the number of Fourier bins, and time is the number of window hops (n_frame). """ - return F.spectrogram(waveform, self.pad, self.window, self.n_fft, self.hop_length, - self.win_length, self.power, self.normalized) + return F.spectrogram( + waveform, + self.pad, + self.window, + self.n_fft, + self.hop_length, + self.win_length, + self.power, + self.normalized, + self.center, + self.pad_mode, + self.onesided + ) class GriffinLim(torch.nn.Module): @@ -386,6 +411,13 @@ class MelSpectrogram(torch.nn.Module): window_fn (Callable[..., Tensor], optional): A function to create a window tensor that is applied/multiplied to each frame/window. (Default: ``torch.hann_window``) wkwargs (Dict[..., ...] or None, optional): Arguments for window function. (Default: ``None``) + center (bool, optional): whether to pad :attr:`waveform` on both sides so + that the :math:`t`-th frame is centered at time :math:`t \times \text{hop\_length}`. + Default: ``True`` + pad_mode (string, optional): controls the padding method used when + :attr:`center` is ``True``. Default: ``"reflect"`` + onesided (bool, optional): controls whether to return half of results to + avoid redundancy. Default: ``True`` Example >>> waveform, sample_rate = torchaudio.load('test.wav', normalization=True) @@ -405,7 +437,10 @@ def __init__(self, window_fn: Callable[..., Tensor] = torch.hann_window, power: Optional[float] = 2., normalized: bool = False, - wkwargs: Optional[dict] = None) -> None: + wkwargs: Optional[dict] = None, + center: bool = True, + pad_mode: str = "reflect", + onesided: bool = True) -> None: super(MelSpectrogram, self).__init__() self.sample_rate = sample_rate self.n_fft = n_fft @@ -420,7 +455,8 @@ def __init__(self, self.spectrogram = Spectrogram(n_fft=self.n_fft, win_length=self.win_length, hop_length=self.hop_length, pad=self.pad, window_fn=window_fn, power=self.power, - normalized=self.normalized, wkwargs=wkwargs) + normalized=self.normalized, wkwargs=wkwargs, + center=center, pad_mode=pad_mode, onesided=onesided) self.mel_scale = MelScale(self.n_mels, self.sample_rate, self.f_min, self.f_max, self.n_fft // 2 + 1) def forward(self, waveform: Tensor) -> Tensor: @@ -1037,3 +1073,55 @@ def forward(self, waveform: Tensor) -> Tensor: hp_lifter_freq=self.hp_lifter_freq, lp_lifter_freq=self.lp_lifter_freq, ) + + +class SpectralCentroid(torch.nn.Module): + r"""Compute the spectral centroid for each channel along the time axis. + + The spectral centroid is defined as the weighted average of the + frequency values, weighted by their magnitude. + + Args: + sample_rate (int): Sample rate of audio signal. + n_fft (int, optional): Size of FFT, creates ``n_fft // 2 + 1`` bins. (Default: ``400``) + win_length (int or None, optional): Window size. (Default: ``n_fft``) + hop_length (int or None, optional): Length of hop between STFT windows. (Default: ``win_length // 2``) + pad (int, optional): Two sided padding of signal. (Default: ``0``) + window_fn (Callable[..., Tensor], optional): A function to create a window tensor + that is applied/multiplied to each frame/window. (Default: ``torch.hann_window``) + wkwargs (dict or None, optional): Arguments for window function. (Default: ``None``) + + Example + >>> waveform, sample_rate = torchaudio.load('test.wav', normalization=True) + >>> spectral_centroid = transforms.SpectralCentroid(sample_rate)(waveform) # (channel, time) + """ + __constants__ = ['sample_rate', 'n_fft', 'win_length', 'hop_length', 'pad'] + + def __init__(self, + sample_rate: int, + n_fft: int = 400, + win_length: Optional[int] = None, + hop_length: Optional[int] = None, + pad: int = 0, + window_fn: Callable[..., Tensor] = torch.hann_window, + wkwargs: Optional[dict] = None) -> None: + super(SpectralCentroid, self).__init__() + self.sample_rate = sample_rate + self.n_fft = n_fft + self.win_length = win_length if win_length is not None else n_fft + self.hop_length = hop_length if hop_length is not None else self.win_length // 2 + window = window_fn(self.win_length) if wkwargs is None else window_fn(self.win_length, **wkwargs) + self.register_buffer('window', window) + self.pad = pad + + def forward(self, waveform: Tensor) -> Tensor: + r""" + Args: + waveform (Tensor): Tensor of audio of dimension (..., time). + + Returns: + Tensor: Spectral Centroid of size (..., time). + """ + + return F.spectral_centroid(waveform, self.sample_rate, self.pad, self.window, self.n_fft, self.hop_length, + self.win_length) From 587743e19295352f99afb3bc1cbc59d6b3eda9f5 Mon Sep 17 00:00:00 2001 From: Nicolas Hug Date: Thu, 4 Feb 2021 07:54:55 -0800 Subject: [PATCH 28/73] Import torchaudio #1233 135e966d Reviewed By: mthrok Differential Revision: D26228762 fbshipit-source-id: 9acc587adb5e7ca7867d8a5df44ba73166099fd9 --- .../linux/scripts/run_clang_format.py | 340 ++++++++++++++++++ .../linux/scripts/run_style_checks.sh | 2 +- .circleci/unittest/linux/scripts/run_test.sh | 8 + torchaudio/__init__.py | 3 +- torchaudio/backend/sox_io_backend.py | 37 +- torchaudio/csrc/sox/effects.cpp | 51 ++- torchaudio/csrc/sox/effects.h | 10 +- torchaudio/csrc/sox/effects_chain.cpp | 32 +- torchaudio/csrc/sox/effects_chain.h | 5 +- torchaudio/csrc/sox/io.cpp | 72 ++-- torchaudio/csrc/sox/io.h | 24 +- torchaudio/csrc/sox/register.cpp | 81 ----- torchaudio/csrc/sox/utils.cpp | 87 +++-- torchaudio/csrc/sox/utils.h | 32 +- torchaudio/sox_effects/sox_effects.py | 10 +- torchaudio/transforms.py | 25 +- 16 files changed, 537 insertions(+), 282 deletions(-) create mode 100755 .circleci/unittest/linux/scripts/run_clang_format.py delete mode 100644 torchaudio/csrc/sox/register.cpp diff --git a/.circleci/unittest/linux/scripts/run_clang_format.py b/.circleci/unittest/linux/scripts/run_clang_format.py new file mode 100755 index 0000000000..fd2913bd70 --- /dev/null +++ b/.circleci/unittest/linux/scripts/run_clang_format.py @@ -0,0 +1,340 @@ +#!/usr/bin/env python +"""A wrapper script around clang-format, suitable for linting multiple files +and to use for continuous integration. + +This is an alternative API for the clang-format command line. +It runs over multiple files and directories in parallel. +A diff output is produced and a sensible exit code is returned. + +""" + +import argparse +import codecs +import difflib +import fnmatch +import io +import multiprocessing +import os +import signal +import subprocess +import sys +import traceback + +from functools import partial + +try: + from subprocess import DEVNULL # py3k +except ImportError: + DEVNULL = open(os.devnull, "wb") + + +DEFAULT_EXTENSIONS = 'c,h,C,H,cpp,hpp,cc,hh,c++,h++,cxx,hxx,cu' + + +class ExitStatus: + SUCCESS = 0 + DIFF = 1 + TROUBLE = 2 + + +def list_files(files, recursive=False, extensions=None, exclude=None): + if extensions is None: + extensions = [] + if exclude is None: + exclude = [] + + out = [] + for file in files: + if recursive and os.path.isdir(file): + for dirpath, dnames, fnames in os.walk(file): + fpaths = [os.path.join(dirpath, fname) for fname in fnames] + for pattern in exclude: + # os.walk() supports trimming down the dnames list + # by modifying it in-place, + # to avoid unnecessary directory listings. + dnames[:] = [ + x for x in dnames + if + not fnmatch.fnmatch(os.path.join(dirpath, x), pattern) + ] + fpaths = [ + x for x in fpaths if not fnmatch.fnmatch(x, pattern) + ] + for f in fpaths: + ext = os.path.splitext(f)[1][1:] + if ext in extensions: + out.append(f) + else: + out.append(file) + return out + + +def make_diff(file, original, reformatted): + return list( + difflib.unified_diff( + original, + reformatted, + fromfile='{}\t(original)'.format(file), + tofile='{}\t(reformatted)'.format(file), + n=3)) + + +class DiffError(Exception): + def __init__(self, message, errs=None): + super(DiffError, self).__init__(message) + self.errs = errs or [] + + +class UnexpectedError(Exception): + def __init__(self, message, exc=None): + super(UnexpectedError, self).__init__(message) + self.formatted_traceback = traceback.format_exc() + self.exc = exc + + +def run_clang_format_diff_wrapper(args, file): + try: + ret = run_clang_format_diff(args, file) + return ret + except DiffError: + raise + except Exception as e: + raise UnexpectedError('{}: {}: {}'.format(file, e.__class__.__name__, + e), e) + + +def run_clang_format_diff(args, file): + try: + with io.open(file, 'r', encoding='utf-8') as f: + original = f.readlines() + except IOError as exc: + raise DiffError(str(exc)) + invocation = [args.clang_format_executable, file] + + # Use of utf-8 to decode the process output. + # + # Hopefully, this is the correct thing to do. + # + # It's done due to the following assumptions (which may be incorrect): + # - clang-format will returns the bytes read from the files as-is, + # without conversion, and it is already assumed that the files use utf-8. + # - if the diagnostics were internationalized, they would use utf-8: + # > Adding Translations to Clang + # > + # > Not possible yet! + # > Diagnostic strings should be written in UTF-8, + # > the client can translate to the relevant code page if needed. + # > Each translation completely replaces the format string + # > for the diagnostic. + # > -- http://clang.llvm.org/docs/InternalsManual.html#internals-diag-translation + + try: + proc = subprocess.Popen( + invocation, + stdout=subprocess.PIPE, + stderr=subprocess.PIPE, + universal_newlines=True, + encoding='utf-8') + except OSError as exc: + raise DiffError( + "Command '{}' failed to start: {}".format( + subprocess.list2cmdline(invocation), exc + ) + ) + proc_stdout = proc.stdout + proc_stderr = proc.stderr + + # hopefully the stderr pipe won't get full and block the process + outs = list(proc_stdout.readlines()) + errs = list(proc_stderr.readlines()) + proc.wait() + if proc.returncode: + raise DiffError( + "Command '{}' returned non-zero exit status {}".format( + subprocess.list2cmdline(invocation), proc.returncode + ), + errs, + ) + return make_diff(file, original, outs), errs + + +def bold_red(s): + return '\x1b[1m\x1b[31m' + s + '\x1b[0m' + + +def colorize(diff_lines): + def bold(s): + return '\x1b[1m' + s + '\x1b[0m' + + def cyan(s): + return '\x1b[36m' + s + '\x1b[0m' + + def green(s): + return '\x1b[32m' + s + '\x1b[0m' + + def red(s): + return '\x1b[31m' + s + '\x1b[0m' + + for line in diff_lines: + if line[:4] in ['--- ', '+++ ']: + yield bold(line) + elif line.startswith('@@ '): + yield cyan(line) + elif line.startswith('+'): + yield green(line) + elif line.startswith('-'): + yield red(line) + else: + yield line + + +def print_diff(diff_lines, use_color): + if use_color: + diff_lines = colorize(diff_lines) + sys.stdout.writelines(diff_lines) + + +def print_trouble(prog, message, use_colors): + error_text = 'error:' + if use_colors: + error_text = bold_red(error_text) + print("{}: {} {}".format(prog, error_text, message), file=sys.stderr) + + +def main(): + parser = argparse.ArgumentParser(description=__doc__) + parser.add_argument( + '--clang-format-executable', + metavar='EXECUTABLE', + help='path to the clang-format executable', + default='clang-format') + parser.add_argument( + '--extensions', + help='comma separated list of file extensions (default: {})'.format( + DEFAULT_EXTENSIONS), + default=DEFAULT_EXTENSIONS) + parser.add_argument( + '-r', + '--recursive', + action='store_true', + help='run recursively over directories') + parser.add_argument('files', metavar='file', nargs='+') + parser.add_argument( + '-q', + '--quiet', + action='store_true') + parser.add_argument( + '-j', + metavar='N', + type=int, + default=0, + help='run N clang-format jobs in parallel' + ' (default number of cpus + 1)') + parser.add_argument( + '--color', + default='auto', + choices=['auto', 'always', 'never'], + help='show colored diff (default: auto)') + parser.add_argument( + '-e', + '--exclude', + metavar='PATTERN', + action='append', + default=[], + help='exclude paths matching the given glob-like pattern(s)' + ' from recursive search') + + args = parser.parse_args() + + # use default signal handling, like diff return SIGINT value on ^C + # https://bugs.python.org/issue14229#msg156446 + signal.signal(signal.SIGINT, signal.SIG_DFL) + try: + signal.SIGPIPE + except AttributeError: + # compatibility, SIGPIPE does not exist on Windows + pass + else: + signal.signal(signal.SIGPIPE, signal.SIG_DFL) + + colored_stdout = False + colored_stderr = False + if args.color == 'always': + colored_stdout = True + colored_stderr = True + elif args.color == 'auto': + colored_stdout = sys.stdout.isatty() + colored_stderr = sys.stderr.isatty() + + version_invocation = [args.clang_format_executable, str("--version")] + try: + subprocess.check_call(version_invocation, stdout=DEVNULL) + except subprocess.CalledProcessError as e: + print_trouble(parser.prog, str(e), use_colors=colored_stderr) + return ExitStatus.TROUBLE + except OSError as e: + print_trouble( + parser.prog, + "Command '{}' failed to start: {}".format( + subprocess.list2cmdline(version_invocation), e + ), + use_colors=colored_stderr, + ) + return ExitStatus.TROUBLE + + retcode = ExitStatus.SUCCESS + files = list_files( + args.files, + recursive=args.recursive, + exclude=args.exclude, + extensions=args.extensions.split(',')) + + if not files: + return + + njobs = args.j + if njobs == 0: + njobs = multiprocessing.cpu_count() + 1 + njobs = min(len(files), njobs) + + if njobs == 1: + # execute directly instead of in a pool, + # less overhead, simpler stacktraces + it = (run_clang_format_diff_wrapper(args, file) for file in files) + pool = None + else: + pool = multiprocessing.Pool(njobs) + it = pool.imap_unordered( + partial(run_clang_format_diff_wrapper, args), files) + while True: + try: + outs, errs = next(it) + except StopIteration: + break + except DiffError as e: + print_trouble(parser.prog, str(e), use_colors=colored_stderr) + retcode = ExitStatus.TROUBLE + sys.stderr.writelines(e.errs) + except UnexpectedError as e: + print_trouble(parser.prog, str(e), use_colors=colored_stderr) + sys.stderr.write(e.formatted_traceback) + retcode = ExitStatus.TROUBLE + # stop at the first unexpected error, + # something could be very wrong, + # don't process all files unnecessarily + if pool: + pool.terminate() + break + else: + sys.stderr.writelines(errs) + if outs == []: + continue + if not args.quiet: + print_diff(outs, use_color=colored_stdout) + if retcode == ExitStatus.SUCCESS: + retcode = ExitStatus.DIFF + return retcode + + +if __name__ == '__main__': + sys.exit(main()) diff --git a/.circleci/unittest/linux/scripts/run_style_checks.sh b/.circleci/unittest/linux/scripts/run_style_checks.sh index d47bae71a7..d8af8824f5 100755 --- a/.circleci/unittest/linux/scripts/run_style_checks.sh +++ b/.circleci/unittest/linux/scripts/run_style_checks.sh @@ -37,7 +37,7 @@ if [ "${status}" -ne 0 ]; then fi printf "\x1b[34mRunning clang-format:\x1b[0m\n" -"${this_dir}"/run-clang-format.py \ +"${this_dir}"/run_clang_format.py \ -r torchaudio/csrc \ --clang-format-executable "${clangformat_path}" \ && git diff --exit-code diff --git a/.circleci/unittest/linux/scripts/run_test.sh b/.circleci/unittest/linux/scripts/run_test.sh index e9016d266c..cbd96f79a8 100755 --- a/.circleci/unittest/linux/scripts/run_test.sh +++ b/.circleci/unittest/linux/scripts/run_test.sh @@ -5,7 +5,15 @@ set -e eval "$(./conda/bin/conda shell.bash hook)" conda activate ./env +case "$(uname -s)" in + Darwin*) os=MacOSX;; + *) os=Linux +esac + python -m torch.utils.collect_env +if [ "${os}" == Linux ]; then + cat /proc/cpuinfo +fi export TORCHAUDIO_TEST_FAIL_IF_NO_EXTENSION=1 export PATH="${PWD}/third_party/install/bin/:${PATH}" diff --git a/torchaudio/__init__.py b/torchaudio/__init__.py index be46d8a0f6..cbb2ba3370 100644 --- a/torchaudio/__init__.py +++ b/torchaudio/__init__.py @@ -3,10 +3,11 @@ from torchaudio import ( compliance, datasets, + functional, kaldi_io, utils, sox_effects, - transforms + transforms, ) USE_SOUNDFILE_LEGACY_INTERFACE = None diff --git a/torchaudio/backend/sox_io_backend.py b/torchaudio/backend/sox_io_backend.py index 513bff4393..0eaf02118a 100644 --- a/torchaudio/backend/sox_io_backend.py +++ b/torchaudio/backend/sox_io_backend.py @@ -11,24 +11,6 @@ from .common import AudioMetaData -@torch.jit.unused -def _info( - filepath: str, - format: Optional[str] = None, -) -> AudioMetaData: - if hasattr(filepath, 'read'): - sinfo = torchaudio._torchaudio.get_info_fileobj(filepath, format) - return AudioMetaData(*sinfo) - sinfo = torch.ops.torchaudio.sox_io_get_info(os.fspath(filepath), format) - return AudioMetaData( - sinfo.get_sample_rate(), - sinfo.get_num_frames(), - sinfo.get_num_channels(), - sinfo.get_bits_per_sample(), - sinfo.get_encoding(), - ) - - @_mod_utils.requires_module('torchaudio._torchaudio') def info( filepath: str, @@ -61,14 +43,12 @@ def info( AudioMetaData: Metadata of the given audio. """ if not torch.jit.is_scripting(): - return _info(filepath, format) + if hasattr(filepath, 'read'): + sinfo = torchaudio._torchaudio.get_info_fileobj(filepath, format) + return AudioMetaData(*sinfo) + filepath = os.fspath(filepath) sinfo = torch.ops.torchaudio.sox_io_get_info(filepath, format) - return AudioMetaData( - sinfo.get_sample_rate(), - sinfo.get_num_frames(), - sinfo.get_num_channels(), - sinfo.get_bits_per_sample(), - sinfo.get_encoding()) + return AudioMetaData(*sinfo) @_mod_utils.requires_module('torchaudio._torchaudio') @@ -162,12 +142,9 @@ def load( if hasattr(filepath, 'read'): return torchaudio._torchaudio.load_audio_fileobj( filepath, frame_offset, num_frames, normalize, channels_first, format) - signal = torch.ops.torchaudio.sox_io_load_audio_file( - os.fspath(filepath), frame_offset, num_frames, normalize, channels_first, format) - return signal.get_tensor(), signal.get_sample_rate() - signal = torch.ops.torchaudio.sox_io_load_audio_file( + filepath = os.fspath(filepath) + return torch.ops.torchaudio.sox_io_load_audio_file( filepath, frame_offset, num_frames, normalize, channels_first, format) - return signal.get_tensor(), signal.get_sample_rate() @torch.jit.unused diff --git a/torchaudio/csrc/sox/effects.cpp b/torchaudio/csrc/sox/effects.cpp index e195e25731..eb4bf24549 100644 --- a/torchaudio/csrc/sox/effects.cpp +++ b/torchaudio/csrc/sox/effects.cpp @@ -50,24 +50,25 @@ void shutdown_sox_effects() { } } -c10::intrusive_ptr apply_effects_tensor( - const c10::intrusive_ptr& input_signal, - std::vector> effects) { - auto in_tensor = input_signal->getTensor(); - validate_input_tensor(in_tensor); +std::tuple apply_effects_tensor( + torch::Tensor waveform, + int64_t sample_rate, + std::vector> effects, + bool channels_first) { + validate_input_tensor(waveform); // Create SoxEffectsChain - const auto dtype = in_tensor.dtype(); + const auto dtype = waveform.dtype(); torchaudio::sox_effects_chain::SoxEffectsChain chain( - /*input_encoding=*/get_encodinginfo("wav", dtype), - /*output_encoding=*/get_encodinginfo("wav", dtype)); + /*input_encoding=*/get_tensor_encodinginfo(dtype), + /*output_encoding=*/get_tensor_encodinginfo(dtype)); // Prepare output buffer std::vector out_buffer; - out_buffer.reserve(in_tensor.numel()); + out_buffer.reserve(waveform.numel()); // Build and run effects chain - chain.addInputTensor(input_signal.get()); + chain.addInputTensor(&waveform, sample_rate, channels_first); for (const auto& effect : effects) { chain.addEffect(effect); } @@ -75,7 +76,6 @@ c10::intrusive_ptr apply_effects_tensor( chain.run(); // Create tensor from buffer - const auto channels_first = input_signal->getChannelsFirst(); auto out_tensor = convert_to_tensor( /*buffer=*/out_buffer.data(), /*num_samples=*/out_buffer.size(), @@ -84,11 +84,11 @@ c10::intrusive_ptr apply_effects_tensor( /*noramlize=*/false, channels_first); - return c10::make_intrusive( - out_tensor, chain.getOutputSampleRate(), channels_first); + return std::tuple( + out_tensor, chain.getOutputSampleRate()); } -c10::intrusive_ptr apply_effects_file( +std::tuple apply_effects_file( const std::string path, std::vector> effects, c10::optional& normalize, @@ -112,7 +112,7 @@ c10::intrusive_ptr apply_effects_file( // Create and run SoxEffectsChain torchaudio::sox_effects_chain::SoxEffectsChain chain( /*input_encoding=*/sf->encoding, - /*output_encoding=*/get_encodinginfo("wav", dtype)); + /*output_encoding=*/get_tensor_encodinginfo(dtype)); chain.addInputFile(sf); for (const auto& effect : effects) { @@ -131,8 +131,8 @@ c10::intrusive_ptr apply_effects_file( normalize.value_or(true), channels_first_); - return c10::make_intrusive( - tensor, chain.getOutputSampleRate(), channels_first_); + return std::tuple( + tensor, chain.getOutputSampleRate()); } #ifdef TORCH_API_INCLUDE_EXTENSION_H @@ -214,7 +214,7 @@ std::tuple apply_effects_fileobj( const auto dtype = get_dtype(sf->encoding.encoding, sf->signal.precision); torchaudio::sox_effects_chain::SoxEffectsChain chain( /*input_encoding=*/sf->encoding, - /*output_encoding=*/get_encodinginfo("wav", dtype)); + /*output_encoding=*/get_tensor_encodinginfo(dtype)); chain.addInputFileObj(sf, in_buf, in_buffer_size, &fileobj); for (const auto& effect : effects) { chain.addEffect(effect); @@ -238,5 +238,20 @@ std::tuple apply_effects_fileobj( #endif // TORCH_API_INCLUDE_EXTENSION_H +TORCH_LIBRARY_FRAGMENT(torchaudio, m) { + m.def( + "torchaudio::sox_effects_initialize_sox_effects", + &torchaudio::sox_effects::initialize_sox_effects); + m.def( + "torchaudio::sox_effects_shutdown_sox_effects", + &torchaudio::sox_effects::shutdown_sox_effects); + m.def( + "torchaudio::sox_effects_apply_effects_tensor", + &torchaudio::sox_effects::apply_effects_tensor); + m.def( + "torchaudio::sox_effects_apply_effects_file", + &torchaudio::sox_effects::apply_effects_file); +} + } // namespace sox_effects } // namespace torchaudio diff --git a/torchaudio/csrc/sox/effects.h b/torchaudio/csrc/sox/effects.h index a2a598b408..8ce9757824 100644 --- a/torchaudio/csrc/sox/effects.h +++ b/torchaudio/csrc/sox/effects.h @@ -15,11 +15,13 @@ void initialize_sox_effects(); void shutdown_sox_effects(); -c10::intrusive_ptr apply_effects_tensor( - const c10::intrusive_ptr& input_signal, - std::vector> effects); +std::tuple apply_effects_tensor( + torch::Tensor waveform, + int64_t sample_rate, + std::vector> effects, + bool channels_first); -c10::intrusive_ptr apply_effects_file( +std::tuple apply_effects_file( const std::string path, std::vector> effects, c10::optional& normalize, diff --git a/torchaudio/csrc/sox/effects_chain.cpp b/torchaudio/csrc/sox/effects_chain.cpp index 80885b296c..cbe78684f7 100644 --- a/torchaudio/csrc/sox/effects_chain.cpp +++ b/torchaudio/csrc/sox/effects_chain.cpp @@ -36,12 +36,14 @@ struct SoxEffect { /// helper classes for passing the location of input tensor and output buffer /// /// drain/flow callback functions require plaing C style function signature and -/// the way to pass extra data is to attach data to sox_fffect_t::priv pointer. -/// The following structs will be assigned to sox_fffect_t::priv pointer which +/// the way to pass extra data is to attach data to sox_effect_t::priv pointer. +/// The following structs will be assigned to sox_effect_t::priv pointer which /// gives sox_effect_t an access to input Tensor and output buffer object. struct TensorInputPriv { size_t index; - TensorSignal* signal; + torch::Tensor* waveform; + int64_t sample_rate; + bool channels_first; }; struct TensorOutputPriv { std::vector* buffer; @@ -55,8 +57,7 @@ int tensor_input_drain(sox_effect_t* effp, sox_sample_t* obuf, size_t* osamp) { // Retrieve the input Tensor and current index auto priv = static_cast(effp->priv); auto index = priv->index; - auto signal = priv->signal; - auto tensor = signal->getTensor(); + auto tensor = *(priv->waveform); auto num_channels = effp->out_signal.channels; // Adjust the number of samples to read @@ -71,7 +72,7 @@ int tensor_input_drain(sox_effect_t* effp, sox_sample_t* obuf, size_t* osamp) { const auto tensor_ = [&]() { auto i_frame = index / num_channels; auto num_frames = *osamp / num_channels; - auto t = (signal->getChannelsFirst()) + auto t = (priv->channels_first) ? tensor.index({Slice(), Slice(i_frame, i_frame + num_frames)}).t() : tensor.index({Slice(i_frame, i_frame + num_frames), Slice()}); return unnormalize_wav(t.reshape({-1})).contiguous(); @@ -193,13 +194,18 @@ void SoxEffectsChain::run() { sox_flow_effects(sec_, NULL, NULL); } -void SoxEffectsChain::addInputTensor(TensorSignal* signal) { - in_sig_ = get_signalinfo(signal, "wav"); +void SoxEffectsChain::addInputTensor( + torch::Tensor* waveform, + int64_t sample_rate, + bool channels_first) { + in_sig_ = get_signalinfo(waveform, sample_rate, "wav", channels_first); interm_sig_ = in_sig_; SoxEffect e(sox_create_effect(get_tensor_input_handler())); auto priv = static_cast(e->priv); - priv->signal = signal; priv->index = 0; + priv->waveform = waveform; + priv->sample_rate = sample_rate; + priv->channels_first = channels_first; if (sox_add_effect(sec_, e, &interm_sig_, &in_sig_) != SOX_SUCCESS) { throw std::runtime_error( "Internal Error: Failed to add effect: input_tensor"); @@ -252,7 +258,13 @@ void SoxEffectsChain::addEffect(const std::vector effect) { throw std::runtime_error(stream.str()); } - SoxEffect e(sox_create_effect(sox_find_effect(name.c_str()))); + auto returned_effect = sox_find_effect(name.c_str()); + if (!returned_effect) { + std::ostringstream stream; + stream << "Unsupported effect: " << name; + throw std::runtime_error(stream.str()); + } + SoxEffect e(sox_create_effect(returned_effect)); const auto num_options = num_args - 1; std::vector opts; diff --git a/torchaudio/csrc/sox/effects_chain.h b/torchaudio/csrc/sox/effects_chain.h index a4797b3486..62e9b8685c 100644 --- a/torchaudio/csrc/sox/effects_chain.h +++ b/torchaudio/csrc/sox/effects_chain.h @@ -30,7 +30,10 @@ class SoxEffectsChain { SoxEffectsChain& operator=(SoxEffectsChain&& other) = delete; ~SoxEffectsChain(); void run(); - void addInputTensor(torchaudio::sox_utils::TensorSignal* signal); + void addInputTensor( + torch::Tensor* waveform, + int64_t sample_rate, + bool channels_first); void addInputFile(sox_format_t* sf); void addOutputBuffer(std::vector* output_buffer); void addOutputFile(sox_format_t* sf); diff --git a/torchaudio/csrc/sox/io.cpp b/torchaudio/csrc/sox/io.cpp index 4594fa4875..ac10911507 100644 --- a/torchaudio/csrc/sox/io.cpp +++ b/torchaudio/csrc/sox/io.cpp @@ -10,38 +10,6 @@ using namespace torchaudio::sox_utils; namespace torchaudio { namespace sox_io { -SignalInfo::SignalInfo( - const int64_t sample_rate_, - const int64_t num_channels_, - const int64_t num_frames_, - const int64_t bits_per_sample_, - const std::string encoding_) - : sample_rate(sample_rate_), - num_channels(num_channels_), - num_frames(num_frames_), - bits_per_sample(bits_per_sample_), - encoding(encoding_){}; - -int64_t SignalInfo::getSampleRate() const { - return sample_rate; -} - -int64_t SignalInfo::getNumChannels() const { - return num_channels; -} - -int64_t SignalInfo::getNumFrames() const { - return num_frames; -} - -int64_t SignalInfo::getBitsPerSample() const { - return bits_per_sample; -} - -std::string SignalInfo::getEncoding() const { - return encoding; -} - namespace { std::string get_encoding(sox_encoding_t encoding) { @@ -77,7 +45,7 @@ std::string get_encoding(sox_encoding_t encoding) { } // namespace -c10::intrusive_ptr get_info_file( +std::tuple get_info_file( const std::string& path, c10::optional& format) { SoxFormat sf(sox_open_read( @@ -90,10 +58,10 @@ c10::intrusive_ptr get_info_file( throw std::runtime_error("Error opening audio file"); } - return c10::make_intrusive( + return std::make_tuple( static_cast(sf->signal.rate), - static_cast(sf->signal.channels), static_cast(sf->signal.length / sf->signal.channels), + static_cast(sf->signal.channels), static_cast(sf->encoding.bits_per_sample), get_encoding(sf->encoding.encoding)); } @@ -131,7 +99,7 @@ std::vector> get_effects( } // namespace -c10::intrusive_ptr load_audio_file( +std::tuple load_audio_file( const std::string& path, c10::optional& frame_offset, c10::optional& num_frames, @@ -153,7 +121,6 @@ void save_audio_file( c10::optional dtype) { validate_input_tensor(tensor); - auto signal = TensorSignal(tensor, sample_rate, channels_first); if (tensor.dtype() != torch::kFloat32 && dtype.has_value()) { throw std::runtime_error( "dtype conversion only supported for float32 tensors"); @@ -174,8 +141,10 @@ void save_audio_file( num_channels == 1, "amr-nb format only supports single channel audio."); tensor = (unnormalize_wav(tensor) / 65536).to(torch::kInt16); } - const auto signal_info = get_signalinfo(&signal, filetype); - const auto encoding_info = get_encodinginfo(filetype, tgt_dtype, compression); + const auto signal_info = + get_signalinfo(&tensor, sample_rate, filetype, channels_first); + const auto encoding_info = + get_encodinginfo_for_save(filetype, tgt_dtype, compression); SoxFormat sf(sox_open_write( path.c_str(), @@ -190,9 +159,9 @@ void save_audio_file( } torchaudio::sox_effects_chain::SoxEffectsChain chain( - /*input_encoding=*/get_encodinginfo("wav", tensor.dtype()), + /*input_encoding=*/get_tensor_encodinginfo(tensor.dtype()), /*output_encoding=*/sf->encoding); - chain.addInputTensor(&signal); + chain.addInputTensor(&tensor, sample_rate, channels_first); chain.addOutputFile(sf); chain.run(); } @@ -294,7 +263,6 @@ void save_audio_fileobj( c10::optional dtype) { validate_input_tensor(tensor); - auto signal = TensorSignal(tensor, sample_rate, channels_first); if (tensor.dtype() != torch::kFloat32 && dtype.has_value()) { throw std::runtime_error( "dtype conversion only supported for float32 tensors"); @@ -312,8 +280,10 @@ void save_audio_fileobj( } tensor = (unnormalize_wav(tensor) / 65536).to(torch::kInt16); } - const auto signal_info = get_signalinfo(&signal, filetype); - const auto encoding_info = get_encodinginfo(filetype, tgt_dtype, compression); + const auto signal_info = + get_signalinfo(&tensor, sample_rate, filetype, channels_first); + const auto encoding_info = + get_encodinginfo_for_save(filetype, tgt_dtype, compression); AutoReleaseBuffer buffer; @@ -331,9 +301,9 @@ void save_audio_fileobj( } torchaudio::sox_effects_chain::SoxEffectsChain chain( - /*input_encoding=*/get_encodinginfo("wav", tensor.dtype()), + /*input_encoding=*/get_tensor_encodinginfo(tensor.dtype()), /*output_encoding=*/sf->encoding); - chain.addInputTensor(&signal); + chain.addInputTensor(&tensor, sample_rate, channels_first); chain.addOutputFileObj(sf, &buffer.ptr, &buffer.size, &fileobj); chain.run(); @@ -346,5 +316,15 @@ void save_audio_fileobj( #endif // TORCH_API_INCLUDE_EXTENSION_H +TORCH_LIBRARY_FRAGMENT(torchaudio, m) { + m.def("torchaudio::sox_io_get_info", &torchaudio::sox_io::get_info_file); + m.def( + "torchaudio::sox_io_load_audio_file", + &torchaudio::sox_io::load_audio_file); + m.def( + "torchaudio::sox_io_save_audio_file", + &torchaudio::sox_io::save_audio_file); +} + } // namespace sox_io } // namespace torchaudio diff --git a/torchaudio/csrc/sox/io.h b/torchaudio/csrc/sox/io.h index fa1f3d61f9..6129fac1b7 100644 --- a/torchaudio/csrc/sox/io.h +++ b/torchaudio/csrc/sox/io.h @@ -11,31 +11,11 @@ namespace torchaudio { namespace sox_io { -struct SignalInfo : torch::CustomClassHolder { - int64_t sample_rate; - int64_t num_channels; - int64_t num_frames; - int64_t bits_per_sample; - std::string encoding; - - SignalInfo( - const int64_t sample_rate_, - const int64_t num_channels_, - const int64_t num_frames_, - const int64_t bits_per_sample_, - const std::string encoding_); - int64_t getSampleRate() const; - int64_t getNumChannels() const; - int64_t getNumFrames() const; - int64_t getBitsPerSample() const; - std::string getEncoding() const; -}; - -c10::intrusive_ptr get_info_file( +std::tuple get_info_file( const std::string& path, c10::optional& format); -c10::intrusive_ptr load_audio_file( +std::tuple load_audio_file( const std::string& path, c10::optional& frame_offset, c10::optional& num_frames, diff --git a/torchaudio/csrc/sox/register.cpp b/torchaudio/csrc/sox/register.cpp deleted file mode 100644 index d90a3b6df1..0000000000 --- a/torchaudio/csrc/sox/register.cpp +++ /dev/null @@ -1,81 +0,0 @@ -#include -#include -#include - -TORCH_LIBRARY_FRAGMENT(torchaudio, m) { - ////////////////////////////////////////////////////////////////////////////// - // sox_utils.h - ////////////////////////////////////////////////////////////////////////////// - m.class_("TensorSignal") - .def(torch::init()) - .def("get_tensor", &torchaudio::sox_utils::TensorSignal::getTensor) - .def( - "get_sample_rate", - &torchaudio::sox_utils::TensorSignal::getSampleRate) - .def( - "get_channels_first", - &torchaudio::sox_utils::TensorSignal::getChannelsFirst); - - m.def("torchaudio::sox_utils_set_seed", &torchaudio::sox_utils::set_seed); - m.def( - "torchaudio::sox_utils_set_verbosity", - &torchaudio::sox_utils::set_verbosity); - m.def( - "torchaudio::sox_utils_set_use_threads", - &torchaudio::sox_utils::set_use_threads); - m.def( - "torchaudio::sox_utils_set_buffer_size", - &torchaudio::sox_utils::set_buffer_size); - m.def( - "torchaudio::sox_utils_list_effects", - &torchaudio::sox_utils::list_effects); - m.def( - "torchaudio::sox_utils_list_read_formats", - &torchaudio::sox_utils::list_read_formats); - m.def( - "torchaudio::sox_utils_list_write_formats", - &torchaudio::sox_utils::list_write_formats); - - ////////////////////////////////////////////////////////////////////////////// - // sox_io.h - ////////////////////////////////////////////////////////////////////////////// - m.class_("SignalInfo") - .def("get_sample_rate", &torchaudio::sox_io::SignalInfo::getSampleRate) - .def("get_num_channels", &torchaudio::sox_io::SignalInfo::getNumChannels) - .def("get_num_frames", &torchaudio::sox_io::SignalInfo::getNumFrames) - .def( - "get_bits_per_sample", - &torchaudio::sox_io::SignalInfo::getBitsPerSample) - .def("get_encoding", &torchaudio::sox_io::SignalInfo::getEncoding); - - m.def("torchaudio::sox_io_get_info", &torchaudio::sox_io::get_info_file); - m.def( - "torchaudio::sox_io_load_audio_file(" - "str path," - "int? frame_offset=None," - "int? num_frames=None," - "bool? normalize=True," - "bool? channels_first=False," - "str? format=None" - ") -> __torch__.torch.classes.torchaudio.TensorSignal", - &torchaudio::sox_io::load_audio_file); - m.def( - "torchaudio::sox_io_save_audio_file", - &torchaudio::sox_io::save_audio_file); - - ////////////////////////////////////////////////////////////////////////////// - // sox_effects.h - ////////////////////////////////////////////////////////////////////////////// - m.def( - "torchaudio::sox_effects_initialize_sox_effects", - &torchaudio::sox_effects::initialize_sox_effects); - m.def( - "torchaudio::sox_effects_shutdown_sox_effects", - &torchaudio::sox_effects::shutdown_sox_effects); - m.def( - "torchaudio::sox_effects_apply_effects_tensor", - &torchaudio::sox_effects::apply_effects_tensor); - m.def( - "torchaudio::sox_effects_apply_effects_file", - &torchaudio::sox_effects::apply_effects_file); -} diff --git a/torchaudio/csrc/sox/utils.cpp b/torchaudio/csrc/sox/utils.cpp index f6bd3c8137..983b7829fe 100644 --- a/torchaudio/csrc/sox/utils.cpp +++ b/torchaudio/csrc/sox/utils.cpp @@ -61,24 +61,6 @@ std::vector list_read_formats() { return formats; } -TensorSignal::TensorSignal( - torch::Tensor tensor_, - int64_t sample_rate_, - bool channels_first_) - : tensor(tensor_), - sample_rate(sample_rate_), - channels_first(channels_first_){}; - -torch::Tensor TensorSignal::getTensor() const { - return tensor; -} -int64_t TensorSignal::getSampleRate() const { - return sample_rate; -} -bool TensorSignal::getChannelsFirst() const { - return channels_first; -} - SoxFormat::SoxFormat(sox_format_t* fd) noexcept : fd_(fd) {} SoxFormat::~SoxFormat() { close(); @@ -297,23 +279,44 @@ unsigned get_precision( } sox_signalinfo_t get_signalinfo( - const TensorSignal* signal, - const std::string filetype) { - auto tensor = signal->getTensor(); + const torch::Tensor* waveform, + const int64_t sample_rate, + const std::string filetype, + const bool channels_first) { return sox_signalinfo_t{ - /*rate=*/static_cast(signal->getSampleRate()), + /*rate=*/static_cast(sample_rate), /*channels=*/ - static_cast(tensor.size(signal->getChannelsFirst() ? 0 : 1)), - /*precision=*/get_precision(filetype, tensor.dtype()), - /*length=*/static_cast(tensor.numel())}; + static_cast(waveform->size(channels_first ? 0 : 1)), + /*precision=*/get_precision(filetype, waveform->dtype()), + /*length=*/static_cast(waveform->numel())}; } -sox_encodinginfo_t get_encodinginfo( - const std::string filetype, - const caffe2::TypeMeta dtype) { +sox_encodinginfo_t get_tensor_encodinginfo(const caffe2::TypeMeta dtype) { + sox_encoding_t encoding = [&]() { + if (dtype == torch::kUInt8) + return SOX_ENCODING_UNSIGNED; + if (dtype == torch::kInt16) + return SOX_ENCODING_SIGN2; + if (dtype == torch::kInt32) + return SOX_ENCODING_SIGN2; + if (dtype == torch::kFloat32) + return SOX_ENCODING_FLOAT; + throw std::runtime_error("Unsupported dtype."); + }(); + unsigned bits_per_sample = [&]() { + if (dtype == torch::kUInt8) + return 8; + if (dtype == torch::kInt16) + return 16; + if (dtype == torch::kInt32) + return 32; + if (dtype == torch::kFloat32) + return 32; + throw std::runtime_error("Unsupported dtype."); + }(); return sox_encodinginfo_t{ - /*encoding=*/get_encoding(filetype, dtype), - /*bits_per_sample=*/get_precision(filetype, dtype), + /*encoding=*/encoding, + /*bits_per_sample=*/bits_per_sample, /*compression=*/HUGE_VAL, /*reverse_bytes=*/sox_option_default, /*reverse_nibbles=*/sox_option_default, @@ -321,7 +324,7 @@ sox_encodinginfo_t get_encodinginfo( /*opposite_endian=*/sox_false}; } -sox_encodinginfo_t get_encodinginfo( +sox_encodinginfo_t get_encodinginfo_for_save( const std::string filetype, const caffe2::TypeMeta dtype, c10::optional& compression) { @@ -364,5 +367,27 @@ uint64_t read_fileobj(py::object* fileobj, const uint64_t size, char* buffer) { #endif // TORCH_API_INCLUDE_EXTENSION_H +TORCH_LIBRARY_FRAGMENT(torchaudio, m) { + m.def("torchaudio::sox_utils_set_seed", &torchaudio::sox_utils::set_seed); + m.def( + "torchaudio::sox_utils_set_verbosity", + &torchaudio::sox_utils::set_verbosity); + m.def( + "torchaudio::sox_utils_set_use_threads", + &torchaudio::sox_utils::set_use_threads); + m.def( + "torchaudio::sox_utils_set_buffer_size", + &torchaudio::sox_utils::set_buffer_size); + m.def( + "torchaudio::sox_utils_list_effects", + &torchaudio::sox_utils::list_effects); + m.def( + "torchaudio::sox_utils_list_read_formats", + &torchaudio::sox_utils::list_read_formats); + m.def( + "torchaudio::sox_utils_list_write_formats", + &torchaudio::sox_utils::list_write_formats); +} + } // namespace sox_utils } // namespace torchaudio diff --git a/torchaudio/csrc/sox/utils.h b/torchaudio/csrc/sox/utils.h index 1d99158378..ea2a6a2953 100644 --- a/torchaudio/csrc/sox/utils.h +++ b/torchaudio/csrc/sox/utils.h @@ -30,23 +30,6 @@ std::vector list_read_formats(); std::vector list_write_formats(); -/// Class for exchanging signal infomation (tensor + meta data) between -/// C++ and Python for read/write operation. -struct TensorSignal : torch::CustomClassHolder { - torch::Tensor tensor; - int64_t sample_rate; - bool channels_first; - - TensorSignal( - torch::Tensor tensor_, - int64_t sample_rate_, - bool channels_first_); - - torch::Tensor getTensor() const; - int64_t getSampleRate() const; - bool getChannelsFirst() const; -}; - //////////////////////////////////////////////////////////////////////////////// // Utilities for sox_io / sox_effects implementations //////////////////////////////////////////////////////////////////////////////// @@ -120,15 +103,16 @@ const std::string get_filetype(const std::string path); /// Get sox_signalinfo_t for passing a torch::Tensor object. sox_signalinfo_t get_signalinfo( - const TensorSignal* signal, - const std::string filetype); - -/// Get sox_encofinginfo_t for saving audoi file -sox_encodinginfo_t get_encodinginfo( + const torch::Tensor* waveform, + const int64_t sample_rate, const std::string filetype, - const caffe2::TypeMeta dtype); + const bool channels_first); + +/// Get sox_encodinginfo_t for Tensor I/O +sox_encodinginfo_t get_tensor_encodinginfo(const caffe2::TypeMeta dtype); -sox_encodinginfo_t get_encodinginfo( +/// Get sox_encodinginfo_t for saving to file/file object +sox_encodinginfo_t get_encodinginfo_for_save( const std::string filetype, const caffe2::TypeMeta dtype, c10::optional& compression); diff --git a/torchaudio/sox_effects/sox_effects.py b/torchaudio/sox_effects/sox_effects.py index d94a776cd6..4d1d0234d9 100644 --- a/torchaudio/sox_effects/sox_effects.py +++ b/torchaudio/sox_effects/sox_effects.py @@ -63,7 +63,7 @@ def apply_effects_tensor( Note: This function works in the way very similar to ``sox`` command, however there are slight - differences. For example, ``sox`` commnad adds certain effects automatically (such as + differences. For example, ``sox`` command adds certain effects automatically (such as ``rate`` effect after ``speed`` and ``pitch`` and other effects), but this function does only applies the given effects. (Therefore, to actually apply ``speed`` effect, you also need to give ``rate`` effect with desired sampling rate.) @@ -149,9 +149,8 @@ def apply_effects_tensor( >>> waveform, sample_rate = transform(waveform, input_sample_rate) >>> assert sample_rate == 8000 """ - in_signal = torch.classes.torchaudio.TensorSignal(tensor, sample_rate, channels_first) - out_signal = torch.ops.torchaudio.sox_effects_apply_effects_tensor(in_signal, effects) - return out_signal.get_tensor(), out_signal.get_sample_rate() + return torch.ops.torchaudio.sox_effects_apply_effects_tensor( + tensor, sample_rate, effects, channels_first) @_mod_utils.requires_module('torchaudio._torchaudio') @@ -268,6 +267,5 @@ def apply_effects_file( return torchaudio._torchaudio.apply_effects_fileobj( path, effects, normalize, channels_first, format) path = os.fspath(path) - signal = torch.ops.torchaudio.sox_effects_apply_effects_file( + return torch.ops.torchaudio.sox_effects_apply_effects_file( path, effects, normalize, channels_first, format) - return signal.get_tensor(), signal.get_sample_rate() diff --git a/torchaudio/transforms.py b/torchaudio/transforms.py index dc7e2ddfe1..7d7903b752 100644 --- a/torchaudio/transforms.py +++ b/torchaudio/transforms.py @@ -248,6 +248,8 @@ class MelScale(torch.nn.Module): f_max (float or None, optional): Maximum frequency. (Default: ``sample_rate // 2``) n_stft (int, optional): Number of bins in STFT. Calculated from first input if None is given. See ``n_fft`` in :class:`Spectrogram`. (Default: ``None``) + norm (Optional[str]): If 'slaney', divide the triangular mel weights by the width of the mel band + (area normalization). (Default: ``None``) """ __constants__ = ['n_mels', 'sample_rate', 'f_min', 'f_max'] @@ -256,17 +258,19 @@ def __init__(self, sample_rate: int = 16000, f_min: float = 0., f_max: Optional[float] = None, - n_stft: Optional[int] = None) -> None: + n_stft: Optional[int] = None, + norm: Optional[str] = None) -> None: super(MelScale, self).__init__() self.n_mels = n_mels self.sample_rate = sample_rate self.f_max = f_max if f_max is not None else float(sample_rate // 2) self.f_min = f_min + self.norm = norm assert f_min <= self.f_max, 'Require f_min: {} < f_max: {}'.format(f_min, self.f_max) fb = torch.empty(0) if n_stft is None else F.create_fb_matrix( - n_stft, self.f_min, self.f_max, self.n_mels, self.sample_rate) + n_stft, self.f_min, self.f_max, self.n_mels, self.sample_rate, self.norm) self.register_buffer('fb', fb) def forward(self, specgram: Tensor) -> Tensor: @@ -283,7 +287,8 @@ def forward(self, specgram: Tensor) -> Tensor: specgram = specgram.reshape(-1, shape[-2], shape[-1]) if self.fb.numel() == 0: - tmp_fb = F.create_fb_matrix(specgram.size(1), self.f_min, self.f_max, self.n_mels, self.sample_rate) + tmp_fb = F.create_fb_matrix(specgram.size(1), self.f_min, self.f_max, + self.n_mels, self.sample_rate, self.norm) # Attributes cannot be reassigned outside __init__ so workaround self.fb.resize_(tmp_fb.size()) self.fb.copy_(tmp_fb) @@ -315,6 +320,8 @@ class InverseMelScale(torch.nn.Module): tolerance_loss (float, optional): Value of loss to stop optimization at. (Default: ``1e-5``) tolerance_change (float, optional): Difference in losses to stop optimization at. (Default: ``1e-8``) sgdargs (dict or None, optional): Arguments for the SGD optimizer. (Default: ``None``) + norm (Optional[str]): If 'slaney', divide the triangular mel weights by the width of the mel band + (area normalization). (Default: ``None``) """ __constants__ = ['n_stft', 'n_mels', 'sample_rate', 'f_min', 'f_max', 'max_iter', 'tolerance_loss', 'tolerance_change', 'sgdargs'] @@ -328,7 +335,8 @@ def __init__(self, max_iter: int = 100000, tolerance_loss: float = 1e-5, tolerance_change: float = 1e-8, - sgdargs: Optional[dict] = None) -> None: + sgdargs: Optional[dict] = None, + norm: Optional[str] = None) -> None: super(InverseMelScale, self).__init__() self.n_mels = n_mels self.sample_rate = sample_rate @@ -341,7 +349,7 @@ def __init__(self, assert f_min <= self.f_max, 'Require f_min: {} < f_max: {}'.format(f_min, self.f_max) - fb = F.create_fb_matrix(n_stft, self.f_min, self.f_max, self.n_mels, self.sample_rate) + fb = F.create_fb_matrix(n_stft, self.f_min, self.f_max, self.n_mels, self.sample_rate, norm) self.register_buffer('fb', fb) def forward(self, melspec: Tensor) -> Tensor: @@ -418,6 +426,8 @@ class MelSpectrogram(torch.nn.Module): :attr:`center` is ``True``. Default: ``"reflect"`` onesided (bool, optional): controls whether to return half of results to avoid redundancy. Default: ``True`` + norm (Optional[str]): If 'slaney', divide the triangular mel weights by the width of the mel band + (area normalization). (Default: ``None``) Example >>> waveform, sample_rate = torchaudio.load('test.wav', normalization=True) @@ -440,7 +450,8 @@ def __init__(self, wkwargs: Optional[dict] = None, center: bool = True, pad_mode: str = "reflect", - onesided: bool = True) -> None: + onesided: bool = True, + norm: Optional[str] = None) -> None: super(MelSpectrogram, self).__init__() self.sample_rate = sample_rate self.n_fft = n_fft @@ -457,7 +468,7 @@ def __init__(self, pad=self.pad, window_fn=window_fn, power=self.power, normalized=self.normalized, wkwargs=wkwargs, center=center, pad_mode=pad_mode, onesided=onesided) - self.mel_scale = MelScale(self.n_mels, self.sample_rate, self.f_min, self.f_max, self.n_fft // 2 + 1) + self.mel_scale = MelScale(self.n_mels, self.sample_rate, self.f_min, self.f_max, self.n_fft // 2 + 1, norm) def forward(self, waveform: Tensor) -> Tensor: r""" From ac3369cd7b7020ed56c7a32fd756eb261b4f61ea Mon Sep 17 00:00:00 2001 From: Vasilis Vryniotis Date: Wed, 10 Feb 2021 01:15:54 -0800 Subject: [PATCH 29/73] Import torchaudio #1250 5a69911 Summary: Imported from Github Reviewed By: mthrok Differential Revision: D26344055 fbshipit-source-id: 163f308e43f514c0b885f4ed0ed87efc0ad26982 --- .circleci/config.yml | 4 +- .circleci/config.yml.in | 4 +- .circleci/torchscript_bc_test/environment.yml | 4 +- .circleci/unittest/linux/scripts/install.sh | 1 + .circleci/unittest/linux/scripts/setup_env.sh | 11 +- .flake8 | 2 +- CMakeLists.txt | 60 ++ CONTRIBUTING.md | 117 ++++ README.md | 10 +- build_tools/setup_helpers/extension.py | 202 +++---- packaging/build_wheel.sh | 2 +- packaging/torchaudio/meta.yaml | 3 +- setup.py | 2 +- test/torchaudio_unittest/README.md | 25 +- .../__init__.py | 0 test/torchaudio_unittest/backend/common.py | 25 + .../{io_test.py => backend/legacy_test.py} | 0 .../soundfile}/__init__.py | 0 .../soundfile}/common.py | 0 .../soundfile}/info_test.py | 6 +- .../soundfile}/load_test.py | 0 .../soundfile}/save_test.py | 1 - .../backend/sox_io/__init__.py | 0 .../sox_io}/common.py | 0 .../sox_io}/info_test.py | 32 +- .../sox_io}/load_test.py | 0 .../sox_io}/roundtrip_test.py | 0 .../sox_io}/save_test.py | 0 .../sox_io}/smoke_test.py | 0 .../sox_io}/torchscript_test.py | 0 .../utils_test.py} | 0 .../batch_consistency_test.py | 77 ++- .../common_utils/__init__.py | 6 +- .../compliance_kaldi_test.py | 1 - .../datasets/datasets_test.py | 2 - .../functional/functional_cpu_test.py | 94 ++- .../torchscript_consistency_cpu_test.py | 14 + .../torchscript_consistency_cuda_test.py | 16 + .../torchscript_consistency_impl.py | 549 ++++++++++++++++++ test/torchaudio_unittest/kaldi_io_test.py | 2 - .../sox_compatibility_test.py | 2 - .../sox_effect/smoke_test.py | 1 - .../torchscript_consistency_cpu_test.py | 18 +- .../torchscript_consistency_cuda_test.py | 24 +- .../torchscript_consistency_impl.py | 544 ----------------- test/torchaudio_unittest/transforms_test.py | 1 - third_party/CMakeLists.txt | 28 +- third_party/sox/CMakeLists.txt | 6 +- third_party/transducer/CMakeLists.txt | 28 +- torchaudio/__init__.py | 25 +- torchaudio/backend/__init__.py | 1 + torchaudio/compliance/__init__.py | 4 + torchaudio/csrc/CMakeLists.txt | 91 +++ torchaudio/csrc/sox/effects_chain.cpp | 8 +- torchaudio/datasets/__init__.py | 4 +- torchaudio/datasets/gtzan.py | 3 +- torchaudio/datasets/ljspeech.py | 2 +- torchaudio/extension/extension.py | 1 - torchaudio/functional/__init__.py | 42 ++ torchaudio/functional/functional.py | 22 +- torchaudio/models/__init__.py | 6 + torchaudio/models/wav2letter.py | 4 +- torchaudio/models/wavernn.py | 8 +- torchaudio/prototype/transducer.py | 5 +- torchaudio/sox_effects/__init__.py | 8 + torchaudio/sox_effects/sox_effects.py | 1 - torchaudio/transforms.py | 15 +- 67 files changed, 1297 insertions(+), 877 deletions(-) create mode 100644 CMakeLists.txt create mode 100644 CONTRIBUTING.md rename test/torchaudio_unittest/{soundfile_backend => backend}/__init__.py (100%) create mode 100644 test/torchaudio_unittest/backend/common.py rename test/torchaudio_unittest/{io_test.py => backend/legacy_test.py} (100%) rename test/torchaudio_unittest/{sox_io_backend => backend/soundfile}/__init__.py (100%) rename test/torchaudio_unittest/{soundfile_backend => backend/soundfile}/common.py (100%) rename test/torchaudio_unittest/{soundfile_backend => backend/soundfile}/info_test.py (98%) rename test/torchaudio_unittest/{soundfile_backend => backend/soundfile}/load_test.py (100%) rename test/torchaudio_unittest/{soundfile_backend => backend/soundfile}/save_test.py (99%) create mode 100644 test/torchaudio_unittest/backend/sox_io/__init__.py rename test/torchaudio_unittest/{sox_io_backend => backend/sox_io}/common.py (100%) rename test/torchaudio_unittest/{sox_io_backend => backend/sox_io}/info_test.py (96%) rename test/torchaudio_unittest/{sox_io_backend => backend/sox_io}/load_test.py (100%) rename test/torchaudio_unittest/{sox_io_backend => backend/sox_io}/roundtrip_test.py (100%) rename test/torchaudio_unittest/{sox_io_backend => backend/sox_io}/save_test.py (100%) rename test/torchaudio_unittest/{sox_io_backend => backend/sox_io}/smoke_test.py (100%) rename test/torchaudio_unittest/{sox_io_backend => backend/sox_io}/torchscript_test.py (100%) rename test/torchaudio_unittest/{backend_test.py => backend/utils_test.py} (100%) create mode 100644 test/torchaudio_unittest/functional/torchscript_consistency_cpu_test.py create mode 100644 test/torchaudio_unittest/functional/torchscript_consistency_cuda_test.py create mode 100644 test/torchaudio_unittest/functional/torchscript_consistency_impl.py create mode 100644 torchaudio/csrc/CMakeLists.txt diff --git a/.circleci/config.yml b/.circleci/config.yml index ef2a4ff76c..1cae2f6c78 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -42,8 +42,8 @@ commands: description: "installs tools required to build torchaudio" steps: - run: - name: Install cmake and pkg-config - command: HOMEBREW_NO_AUTO_UPDATE=1 brew install cmake pkg-config wget + name: Install pkg-config + command: HOMEBREW_NO_AUTO_UPDATE=1 brew install pkg-config wget # Disable brew auto update which is very slow binary_common: &binary_common diff --git a/.circleci/config.yml.in b/.circleci/config.yml.in index 84e25911a3..fa1e202cb9 100644 --- a/.circleci/config.yml.in +++ b/.circleci/config.yml.in @@ -42,8 +42,8 @@ commands: description: "installs tools required to build torchaudio" steps: - run: - name: Install cmake and pkg-config - command: HOMEBREW_NO_AUTO_UPDATE=1 brew install cmake pkg-config wget + name: Install pkg-config + command: HOMEBREW_NO_AUTO_UPDATE=1 brew install pkg-config wget # Disable brew auto update which is very slow binary_common: &binary_common diff --git a/.circleci/torchscript_bc_test/environment.yml b/.circleci/torchscript_bc_test/environment.yml index 108d97d193..f528ce99f4 100644 --- a/.circleci/torchscript_bc_test/environment.yml +++ b/.circleci/torchscript_bc_test/environment.yml @@ -7,10 +7,12 @@ dependencies: - pytest - pytest-cov - codecov - - librosa + - librosa>=0.8.0 - llvmlite==0.31 # See https://github.com/pytorch/audio/pull/766 - pip - pip: + - cmake + - ninja - kaldi-io - scipy - parameterized diff --git a/.circleci/unittest/linux/scripts/install.sh b/.circleci/unittest/linux/scripts/install.sh index fd43260194..209c86be71 100755 --- a/.circleci/unittest/linux/scripts/install.sh +++ b/.circleci/unittest/linux/scripts/install.sh @@ -38,6 +38,7 @@ conda install -y -c "pytorch-${UPLOAD_CHANNEL}" pytorch ${cudatoolkit} # 2. Install torchaudio printf "* Installing torchaudio\n" +git submodule update --init --recursive BUILD_TRANSDUCER=1 BUILD_SOX=1 python setup.py install # 3. Install Test tools diff --git a/.circleci/unittest/linux/scripts/setup_env.sh b/.circleci/unittest/linux/scripts/setup_env.sh index f56b211ac9..085dc61a5b 100755 --- a/.circleci/unittest/linux/scripts/setup_env.sh +++ b/.circleci/unittest/linux/scripts/setup_env.sh @@ -5,7 +5,7 @@ # # Do not install PyTorch and torchaudio here, otherwise they also get cached. -set -e +set -ex root_dir="$(git rev-parse --show-toplevel)" conda_dir="${root_dir}/conda" @@ -41,12 +41,3 @@ conda activate "${env_dir}" # 3. Install minimal build tools pip --quiet install cmake ninja - -# 4. Buld codecs -git submodule update --init --recursive -mkdir -p third_party/build -( - cd third_party/build - cmake -GNinja .. - cmake --build . -) diff --git a/.flake8 b/.flake8 index b4a5069f16..f344aec879 100644 --- a/.flake8 +++ b/.flake8 @@ -1,4 +1,4 @@ [flake8] max-line-length = 120 -ignore = E305,E402,E721,E741,F401,F403,F405,W503,W504,F999 +ignore = E305,E402,E721,E741,F405,W503,W504,F999 exclude = build,docs/source,_ext,third_party diff --git a/CMakeLists.txt b/CMakeLists.txt new file mode 100644 index 0000000000..d72639a71e --- /dev/null +++ b/CMakeLists.txt @@ -0,0 +1,60 @@ +cmake_minimum_required(VERSION 3.5 FATAL_ERROR) + +# Most of the configurations are taken from PyTorch +# https://github.com/pytorch/pytorch/blob/0c9fb4aff0d60eaadb04e4d5d099fb1e1d5701a9/CMakeLists.txt + +# Use compiler ID "AppleClang" instead of "Clang" for XCode. +# Not setting this sometimes makes XCode C compiler gets detected as "Clang", +# even when the C++ one is detected as "AppleClang". +cmake_policy(SET CMP0010 NEW) +cmake_policy(SET CMP0025 NEW) + +# Suppress warning flags in default MSVC configuration. It's not +# mandatory that we do this (and we don't if cmake is old), but it's +# nice when it's possible, and it's possible on our Windows configs. +if(NOT CMAKE_VERSION VERSION_LESS 3.15.0) + cmake_policy(SET CMP0092 NEW) +endif() + +project(torchaudio) + +# check and set CMAKE_CXX_STANDARD +string(FIND "${CMAKE_CXX_FLAGS}" "-std=c++" env_cxx_standard) +if(env_cxx_standard GREATER -1) + message( + WARNING "C++ standard version definition detected in environment variable." + "PyTorch requires -std=c++14. Please remove -std=c++ settings in your environment.") +endif() +set(CMAKE_CXX_STANDARD 14) +set(CMAKE_C_STANDARD 11) + +set(CMAKE_EXPORT_COMPILE_COMMANDS ON) +set(CMAKE_POSITION_INDEPENDENT_CODE ON) + +# Apple specific +if(APPLE) + # Get clang version on macOS + execute_process( COMMAND ${CMAKE_CXX_COMPILER} --version OUTPUT_VARIABLE clang_full_version_string ) + string(REGEX REPLACE "Apple LLVM version ([0-9]+\\.[0-9]+).*" "\\1" CLANG_VERSION_STRING ${clang_full_version_string}) + message( STATUS "CLANG_VERSION_STRING: " ${CLANG_VERSION_STRING} ) + + # RPATH stuff + set(CMAKE_MACOSX_RPATH ON) + + set(CMAKE_SHARED_LIBRARY_SUFFIX ".so") +endif() + + +# Options +option(BUILD_SOX "Build libsox statically" OFF) +option(BUILD_TRANSDUCER "Enable transducer" OFF) +option(BUILD_LIBTORCHAUDIO "Build C++ Library" ON) +option(BUILD_TORCHAUDIO_PYTHON_EXTENSION "Build Python extension" OFF) + +find_package(Torch REQUIRED) + +# TORCH_CXX_FLAGS contains the same -D_GLIBCXX_USE_CXX11_ABI value as PyTorch +set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall ${TORCH_CXX_FLAGS}") + +add_subdirectory(third_party) +add_subdirectory(torchaudio/csrc) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md new file mode 100644 index 0000000000..73674b42c2 --- /dev/null +++ b/CONTRIBUTING.md @@ -0,0 +1,117 @@ +# Contributing to Torchaudio +We want to make contributing to this project as easy and transparent as possible. + +## TL;DR + +Please let us know if you encounter a bug by filing an [issue](https://github.com/pytorch/audio/issues). + +We appreciate all contributions. If you are planning to contribute back +bug-fixes, please do so without any further discussion. + +If you plan to contribute new features, utility functions or extensions to the +core, please first open an issue and discuss the feature with us. Sending a PR +without discussion might end up resulting in a rejected PR, because we might be +taking the core in a different direction than you might be aware of. + +Fixing bugs and implementing new features are not the only way you can +contribute. It also helps the project when you report problems you're facing, +and when you give a :+1: on issues that others reported and that are relevant +to you. + +You can also help by improving the documentation. This is no less important +than improving the library itself! If you find a typo in the documentation, +do not hesitate to submit a pull request. + +If you're not sure what you want to work on, you can pick an issue from the +[list of open issues labelled as "help +wanted"](https://github.com/pytorch/audio/issues?q=is%3Aopen+is%3Aissue+label%3A%22help+wanted%22). +Comment on the issue that you want to work on it and send a PR with your fix +(see below). + +## Development installation + +We recommend using a `conda` environment to contribute efficiently to +torchaudio. + +### Install PyTorch Nightly + +```bash +conda install pytorch -c pytorch-nightly +``` + +### Install Torchaudio + +```bash +pip install cmake ninja +``` + +```bash +git clone https://github.com/pytorch/audio.git +cd audio +git submodule update --init --recursive +BUILD_SOX=1 python setup.py develop +# or, for OSX +# BUILD_SOX=1 MACOSX_DEPLOYMENT_TARGET=10.9 CC=clang CXX=clang++ python setup.py develop +# for C++ debugging, please use DEBUG=1 +# DEBUG=1 python setup.py install +``` + +Note: you don't need to use `BUILD_SOX=1` if you have `libsox-dev` installed +already. If you built sox however, set the `PATH` variable so that the tests +properly use the newly built `sox` binary: + +```bash +export PATH="/third_party/install/bin:${PATH}" +``` + +The following dependencies are also needed for testing: + +```bash +pip install typing pytest scipy numpy parametrized +``` + +## Development Process + +If you plan to modify the code or documentation, please follow the steps below: + +1. Fork the repository and create your branch from `master`: `$ git checkout master && git checkout -b my_cool_feature` +2. If you have modified the code (new feature or bug-fix), [please add tests](.test/torchaudio_unittest/). +3. If you have changed APIs, [update the documentation](#Documentation). + +For more details about pull requests, +please read [GitHub's guides](https://docs.github.com/en/github/collaborating-with-issues-and-pull-requests/creating-a-pull-request). + +If you would like to contribute a new model, please see [here](#New-model). + +If you would like to contribute a new dataset, please see [here](#New-dataset). + +## Testing + +Please refer to our [testing guidelines](.test/torchaudio_unittest/) for more +details. + +## Documentation + +Torchaudio uses [Google style](http://sphinxcontrib-napoleon.readthedocs.io/en/latest/example_google.html) +for formatting docstrings. Length of line inside docstrings block must be limited to 120 characters. + +To build the docs, first install the requirements: + +```bash +cd docs +pip install -r requirements.txt +``` + +Then: + +```bash +cd docs +make html +``` + +The built docs should now be available in `docs/build/html` + +## License + +By contributing to Torchaudio, you agree that your contributions will be licensed +under the LICENSE file in the root directory of this source tree. diff --git a/README.md b/README.md index b3664de5f6..527b1a22da 100644 --- a/README.md +++ b/README.md @@ -232,15 +232,7 @@ Complex numbers are supported via tensors of dimension (..., 2), and torchaudio Contributing Guidelines ----------------------- -Please let us know if you encounter a bug by filing an [issue](https://github.com/pytorch/audio/issues). - -We appreciate all contributions. If you are planning to contribute back -bug-fixes, please do so without any further discussion. - -If you plan to contribute new features, utility functions or extensions to the -core, please first open an issue and discuss the feature with us. Sending a PR -without discussion might end up resulting in a rejected PR, because we might be -taking the core in a different direction than you might be aware of. +Please refer to [CONTRIBUTING.md](./CONTRIBUTING.md) Disclaimer on Datasets ---------------------- diff --git a/build_tools/setup_helpers/extension.py b/build_tools/setup_helpers/extension.py index 7f0ba7a14f..d34464ed37 100644 --- a/build_tools/setup_helpers/extension.py +++ b/build_tools/setup_helpers/extension.py @@ -2,23 +2,20 @@ import platform import subprocess from pathlib import Path +import distutils.sysconfig +from setuptools import Extension +from setuptools.command.build_ext import build_ext import torch -from torch.utils.cpp_extension import ( - CppExtension, - BuildExtension as TorchBuildExtension -) __all__ = [ 'get_ext_modules', - 'BuildExtension', + 'CMakeBuild', ] _THIS_DIR = Path(__file__).parent.resolve() _ROOT_DIR = _THIS_DIR.parent.parent.resolve() -_CSRC_DIR = _ROOT_DIR / 'torchaudio' / 'csrc' -_TP_BASE_DIR = _ROOT_DIR / 'third_party' -_TP_INSTALL_DIR = _TP_BASE_DIR / 'install' +_TORCHAUDIO_DIR = _ROOT_DIR / 'torchaudio' def _get_build(var): @@ -38,132 +35,71 @@ def _get_build(var): _BUILD_TRANSDUCER = _get_build("BUILD_TRANSDUCER") -def _get_eca(debug): - eca = [] - if debug: - eca += ["-O0", "-g"] - else: - eca += ["-O3"] - if _BUILD_TRANSDUCER: - eca += ['-DBUILD_TRANSDUCER'] - return eca - - -def _get_ela(debug): - ela = [] - if debug: - if platform.system() == "Windows": - ela += ["/DEBUG:FULL"] - else: - ela += ["-O0", "-g"] - else: - ela += ["-O3"] - return ela - - -def _get_srcs(): - srcs = [_CSRC_DIR / 'pybind.cpp'] - srcs += list(_CSRC_DIR.glob('sox/**/*.cpp')) - if _BUILD_TRANSDUCER: - srcs += [_CSRC_DIR / 'transducer.cpp'] - return [str(path) for path in srcs] - - -def _get_include_dirs(): - dirs = [ - str(_ROOT_DIR), - ] - if _BUILD_SOX or _BUILD_TRANSDUCER: - dirs.append(str(_TP_INSTALL_DIR / 'include')) - return dirs - - -def _get_extra_objects(): - libs = [] - if _BUILD_SOX: - # NOTE: The order of the library listed bellow matters. - # - # (the most important thing is that dependencies come after a library - # e.g., sox comes first, flac/vorbis comes before ogg, and - # vorbisenc/vorbisfile comes before vorbis - libs += [ - 'libsox.a', - 'libmad.a', - 'libFLAC.a', - 'libmp3lame.a', - 'libopusfile.a', - 'libopus.a', - 'libvorbisenc.a', - 'libvorbisfile.a', - 'libvorbis.a', - 'libogg.a', - 'libopencore-amrnb.a', - 'libopencore-amrwb.a', - ] - if _BUILD_TRANSDUCER: - libs += ['libwarprnnt.a'] - - return [str(_TP_INSTALL_DIR / 'lib' / lib) for lib in libs] - - -def _get_libraries(): - return [] if _BUILD_SOX else ['sox'] - - -def _get_cxx11_abi(): - try: - value = int(torch._C._GLIBCXX_USE_CXX11_ABI) - except ImportError: - value = 0 - return f'-D_GLIBCXX_USE_CXX11_ABI={value}' - - -def _build_third_party(base_build_dir): - build_dir = os.path.join(base_build_dir, 'third_party') - os.makedirs(build_dir, exist_ok=True) - subprocess.run( - args=[ - 'cmake', - f"-DCMAKE_CXX_FLAGS='{_get_cxx11_abi()}'", - '-DCMAKE_VERBOSE_MAKEFILE:BOOL=ON', - f'-DCMAKE_INSTALL_PREFIX={_TP_INSTALL_DIR}', - f'-DBUILD_SOX={"ON" if _BUILD_SOX else "OFF"}', - f'-DBUILD_TRANSDUCER={"ON" if _BUILD_TRANSDUCER else "OFF"}', - f'{_TP_BASE_DIR}'], - cwd=build_dir, - check=True, - ) - command = ['cmake', '--build', '.'] - if _BUILD_TRANSDUCER: - command += ['--target', 'install'] - subprocess.run( - args=command, - cwd=build_dir, - check=True, - ) - +def get_ext_modules(): + if platform.system() == 'Windows': + return None + return [Extension(name='torchaudio._torchaudio', sources=[])] -_EXT_NAME = 'torchaudio._torchaudio' +# Based off of +# https://github.com/pybind/cmake_example/blob/580c5fd29d4651db99d8874714b07c0c49a53f8a/setup.py +class CMakeBuild(build_ext): + def run(self): + try: + subprocess.check_output(['cmake', '--version']) + except OSError: + raise RuntimeError("CMake is not available.") + super().run() -def get_ext_modules(debug=False): - if platform.system() == 'Windows': - return None - return [ - CppExtension( - _EXT_NAME, - _get_srcs(), - libraries=_get_libraries(), - include_dirs=_get_include_dirs(), - extra_compile_args=_get_eca(debug), - extra_objects=_get_extra_objects(), - extra_link_args=_get_ela(debug), - ), - ] - - -class BuildExtension(TorchBuildExtension): def build_extension(self, ext): - if ext.name == _EXT_NAME and _BUILD_SOX: - _build_third_party(self.build_temp) - super().build_extension(ext) + extdir = os.path.abspath( + os.path.dirname(self.get_ext_fullpath(ext.name))) + + # required for auto-detection of auxiliary "native" libs + if not extdir.endswith(os.path.sep): + extdir += os.path.sep + + cfg = "Debug" if self.debug else "Release" + + cmake_args = [ + f"-DCMAKE_BUILD_TYPE={cfg}", + f"-DCMAKE_PREFIX_PATH={torch.utils.cmake_prefix_path}", + f"-DCMAKE_INSTALL_PREFIX={extdir}", + '-DCMAKE_VERBOSE_MAKEFILE=ON', + f"-DPython_INCLUDE_DIR={distutils.sysconfig.get_python_inc()}", + f"-DBUILD_SOX:BOOL={'ON' if _BUILD_SOX else 'OFF'}", + f"-DBUILD_TRANSDUCER:BOOL={'ON' if _BUILD_TRANSDUCER else 'OFF'}", + "-DBUILD_TORCHAUDIO_PYTHON_EXTENSION:BOOL=ON", + "-DBUILD_LIBTORCHAUDIO:BOOL=OFF", + ] + build_args = [ + '--target', 'install' + ] + + # Default to Ninja + if 'CMAKE_GENERATOR' not in os.environ: + cmake_args += ["-GNinja"] + + # Set CMAKE_BUILD_PARALLEL_LEVEL to control the parallel build level + # across all generators. + if "CMAKE_BUILD_PARALLEL_LEVEL" not in os.environ: + # self.parallel is a Python 3 only way to set parallel jobs by hand + # using -j in the build_ext call, not supported by pip or PyPA-build. + if hasattr(self, "parallel") and self.parallel: + # CMake 3.12+ only. + build_args += ["-j{}".format(self.parallel)] + + if not os.path.exists(self.build_temp): + os.makedirs(self.build_temp) + + subprocess.check_call( + ["cmake", str(_ROOT_DIR)] + cmake_args, cwd=self.build_temp) + subprocess.check_call( + ["cmake", "--build", "."] + build_args, cwd=self.build_temp) + + def get_ext_filename(self, fullname): + ext_filename = super().get_ext_filename(fullname) + ext_filename_parts = ext_filename.split('.') + without_abi = ext_filename_parts[:-2] + ext_filename_parts[-1:] + ext_filename = '.'.join(without_abi) + return ext_filename diff --git a/packaging/build_wheel.sh b/packaging/build_wheel.sh index 957b41e048..11e8f07bfd 100755 --- a/packaging/build_wheel.sh +++ b/packaging/build_wheel.sh @@ -8,7 +8,7 @@ export BUILD_TYPE="wheel" export NO_CUDA_PACKAGE=1 setup_env 0.8.0 setup_wheel_python -pip_install numpy future +pip_install numpy future cmake ninja setup_pip_pytorch_version python setup.py clean if [[ "$OSTYPE" == "msys" ]]; then diff --git a/packaging/torchaudio/meta.yaml b/packaging/torchaudio/meta.yaml index bd4f004a1b..ad12821d0e 100644 --- a/packaging/torchaudio/meta.yaml +++ b/packaging/torchaudio/meta.yaml @@ -14,11 +14,12 @@ requirements: - python - setuptools - cpuonly + - cmake + - ninja {{ environ.get('CONDA_PYTORCH_BUILD_CONSTRAINT') }} run: - python - - typing # [py2k] {{ environ.get('CONDA_PYTORCH_CONSTRAINT') }} build: diff --git a/setup.py b/setup.py index 8ecc41c1cc..1ee56dfcb7 100644 --- a/setup.py +++ b/setup.py @@ -83,7 +83,7 @@ def run(self): packages=find_packages(exclude=["build*", "test*", "torchaudio.csrc*", "third_party*", "build_tools*"]), ext_modules=setup_helpers.get_ext_modules(), cmdclass={ - 'build_ext': setup_helpers.BuildExtension.with_options(no_python_abi_suffix=True), + 'build_ext': setup_helpers.CMakeBuild, 'clean': clean, }, install_requires=[pytorch_package_dep], diff --git a/test/torchaudio_unittest/README.md b/test/torchaudio_unittest/README.md index 50d17d9948..d61c64b015 100644 --- a/test/torchaudio_unittest/README.md +++ b/test/torchaudio_unittest/README.md @@ -2,9 +2,25 @@ ## How to run test -You can use `pytest` to run `torchaudio`'s test suites. See https://docs.pytest.org/ for the detail of how to use `pytest` command. The `parametrized` package is also needed; it can be installed via `pip` or with ` conda install -c conda-forge parameterized`. +You can use `pytest` to run `torchaudio`'s test suites. See +https://docs.pytest.org/ for the detail of how to use `pytest` command. +For testing, the following packages are needed: + +```bash +pip install typing pytest scipy numpy parametrized +``` + +Make sure to follow the installation instruction in the [contributing +guide](../../CONTRIBUTING.md) first. For running `kaldi`-related tests: + +```bash +export PATH="${PATH}:/src/featbin/" ``` + +Some useful pytest commands: + +```bash # List up all the tests pytest test --collect-only # Run all the test suites @@ -21,6 +37,11 @@ pytest test/torchaudio_unittest/sox_io_backend -k load # only runs tests where **Note** We use PyTorch's test utilities instead of `pytest` frameworks when writing tests to avoid reinventing the wheel for Tensor comparison. +Also, while we recommend using `pytest` for *running* the tests, we cannot +make `pytest` a testing dependency of `torchaudio`. As a result, you should +not import `pytest` or its submodules in the test files; Use the Python +`unittest` builtin module instead, or the `parametrized` package to +parametrize tests. ## Structure of tests @@ -28,7 +49,7 @@ The following is an overview of the tests and related modules for `torchaudio`. ### Purpose specific test suites -#### Numerical compatibility agains existing software +#### Numerical compatibility against existing software - [Librosa compatibility test](./librosa_compatibility_test.py) Test suite for numerical compatibility against librosa. - [SoX compatibility test](./sox_compatibility_test.py) diff --git a/test/torchaudio_unittest/soundfile_backend/__init__.py b/test/torchaudio_unittest/backend/__init__.py similarity index 100% rename from test/torchaudio_unittest/soundfile_backend/__init__.py rename to test/torchaudio_unittest/backend/__init__.py diff --git a/test/torchaudio_unittest/backend/common.py b/test/torchaudio_unittest/backend/common.py new file mode 100644 index 0000000000..dc8e90bf77 --- /dev/null +++ b/test/torchaudio_unittest/backend/common.py @@ -0,0 +1,25 @@ +from torchaudio_unittest.common_utils import sox_utils + + +def get_encoding(ext, dtype): + exts = { + 'mp3', + 'flac', + 'vorbis', + } + encodings = { + 'float32': 'PCM_F', + 'int32': 'PCM_S', + 'int16': 'PCM_S', + 'uint8': 'PCM_U', + } + return ext.upper() if ext in exts else encodings[dtype] + + +def get_bits_per_sample(ext, dtype): + bits_per_samples = { + 'flac': 24, + 'mp3': 0, + 'vorbis': 0, + } + return bits_per_samples.get(ext, sox_utils.get_bit_depth(dtype)) diff --git a/test/torchaudio_unittest/io_test.py b/test/torchaudio_unittest/backend/legacy_test.py similarity index 100% rename from test/torchaudio_unittest/io_test.py rename to test/torchaudio_unittest/backend/legacy_test.py diff --git a/test/torchaudio_unittest/sox_io_backend/__init__.py b/test/torchaudio_unittest/backend/soundfile/__init__.py similarity index 100% rename from test/torchaudio_unittest/sox_io_backend/__init__.py rename to test/torchaudio_unittest/backend/soundfile/__init__.py diff --git a/test/torchaudio_unittest/soundfile_backend/common.py b/test/torchaudio_unittest/backend/soundfile/common.py similarity index 100% rename from test/torchaudio_unittest/soundfile_backend/common.py rename to test/torchaudio_unittest/backend/soundfile/common.py diff --git a/test/torchaudio_unittest/soundfile_backend/info_test.py b/test/torchaudio_unittest/backend/soundfile/info_test.py similarity index 98% rename from test/torchaudio_unittest/soundfile_backend/info_test.py rename to test/torchaudio_unittest/backend/soundfile/info_test.py index d4aa2b2b2e..3b3f792281 100644 --- a/test/torchaudio_unittest/soundfile_backend/info_test.py +++ b/test/torchaudio_unittest/backend/soundfile/info_test.py @@ -13,8 +13,10 @@ get_wav_data, save_wav, ) -# TODO refactor and move these to common location -from torchaudio_unittest.sox_io_backend.info_test import get_encoding, get_bits_per_sample +from torchaudio_unittest.backend.common import ( + get_bits_per_sample, + get_encoding, +) from .common import skipIfFormatNotSupported, parameterize if _mod_utils.is_module_available("soundfile"): diff --git a/test/torchaudio_unittest/soundfile_backend/load_test.py b/test/torchaudio_unittest/backend/soundfile/load_test.py similarity index 100% rename from test/torchaudio_unittest/soundfile_backend/load_test.py rename to test/torchaudio_unittest/backend/soundfile/load_test.py diff --git a/test/torchaudio_unittest/soundfile_backend/save_test.py b/test/torchaudio_unittest/backend/soundfile/save_test.py similarity index 99% rename from test/torchaudio_unittest/soundfile_backend/save_test.py rename to test/torchaudio_unittest/backend/soundfile/save_test.py index 5c36e0d126..2f2741c303 100644 --- a/test/torchaudio_unittest/soundfile_backend/save_test.py +++ b/test/torchaudio_unittest/backend/soundfile/save_test.py @@ -1,5 +1,4 @@ import io -import itertools from unittest.mock import patch from torchaudio._internal import module_utils as _mod_utils diff --git a/test/torchaudio_unittest/backend/sox_io/__init__.py b/test/torchaudio_unittest/backend/sox_io/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/test/torchaudio_unittest/sox_io_backend/common.py b/test/torchaudio_unittest/backend/sox_io/common.py similarity index 100% rename from test/torchaudio_unittest/sox_io_backend/common.py rename to test/torchaudio_unittest/backend/sox_io/common.py diff --git a/test/torchaudio_unittest/sox_io_backend/info_test.py b/test/torchaudio_unittest/backend/sox_io/info_test.py similarity index 96% rename from test/torchaudio_unittest/sox_io_backend/info_test.py rename to test/torchaudio_unittest/backend/sox_io/info_test.py index 9a26b0d2ea..a2a93648a1 100644 --- a/test/torchaudio_unittest/sox_io_backend/info_test.py +++ b/test/torchaudio_unittest/backend/sox_io/info_test.py @@ -7,6 +7,10 @@ from torchaudio.backend import sox_io_backend from torchaudio._internal import module_utils as _mod_utils +from torchaudio_unittest.backend.common import ( + get_bits_per_sample, + get_encoding, +) from torchaudio_unittest.common_utils import ( TempDirMixin, HttpServerMixin, @@ -28,30 +32,6 @@ import requests -def get_encoding(ext, dtype): - exts = { - 'mp3', - 'flac', - 'vorbis', - } - encodings = { - 'float32': 'PCM_F', - 'int32': 'PCM_S', - 'int16': 'PCM_S', - 'uint8': 'PCM_U', - } - return ext.upper() if ext in exts else encodings[dtype] - - -def get_bits_per_sample(ext, dtype): - bits_per_samples = { - 'flac': 24, - 'mp3': 0, - 'vorbis': 0, - } - return bits_per_samples.get(ext, sox_utils.get_bit_depth(dtype)) - - @skipIfNoExec('sox') @skipIfNoExtension class TestInfo(TempDirMixin, PytorchTestCase): @@ -161,7 +141,9 @@ def test_sphere(self, sample_rate, num_channels, bits_per_sample): """`sox_io_backend.info` can check sph file correctly""" duration = 1 path = self.get_temp_path('data.sph') - sox_utils.gen_audio_file(path, sample_rate, num_channels, duration=duration, bit_depth=bits_per_sample) + sox_utils.gen_audio_file( + path, sample_rate, num_channels, duration=duration, + bit_depth=bits_per_sample) info = sox_io_backend.info(path) assert info.sample_rate == sample_rate assert info.num_frames == sample_rate * duration diff --git a/test/torchaudio_unittest/sox_io_backend/load_test.py b/test/torchaudio_unittest/backend/sox_io/load_test.py similarity index 100% rename from test/torchaudio_unittest/sox_io_backend/load_test.py rename to test/torchaudio_unittest/backend/sox_io/load_test.py diff --git a/test/torchaudio_unittest/sox_io_backend/roundtrip_test.py b/test/torchaudio_unittest/backend/sox_io/roundtrip_test.py similarity index 100% rename from test/torchaudio_unittest/sox_io_backend/roundtrip_test.py rename to test/torchaudio_unittest/backend/sox_io/roundtrip_test.py diff --git a/test/torchaudio_unittest/sox_io_backend/save_test.py b/test/torchaudio_unittest/backend/sox_io/save_test.py similarity index 100% rename from test/torchaudio_unittest/sox_io_backend/save_test.py rename to test/torchaudio_unittest/backend/sox_io/save_test.py diff --git a/test/torchaudio_unittest/sox_io_backend/smoke_test.py b/test/torchaudio_unittest/backend/sox_io/smoke_test.py similarity index 100% rename from test/torchaudio_unittest/sox_io_backend/smoke_test.py rename to test/torchaudio_unittest/backend/sox_io/smoke_test.py diff --git a/test/torchaudio_unittest/sox_io_backend/torchscript_test.py b/test/torchaudio_unittest/backend/sox_io/torchscript_test.py similarity index 100% rename from test/torchaudio_unittest/sox_io_backend/torchscript_test.py rename to test/torchaudio_unittest/backend/sox_io/torchscript_test.py diff --git a/test/torchaudio_unittest/backend_test.py b/test/torchaudio_unittest/backend/utils_test.py similarity index 100% rename from test/torchaudio_unittest/backend_test.py rename to test/torchaudio_unittest/backend/utils_test.py diff --git a/test/torchaudio_unittest/batch_consistency_test.py b/test/torchaudio_unittest/batch_consistency_test.py index 78e3cd62f9..4644fe7dd3 100644 --- a/test/torchaudio_unittest/batch_consistency_test.py +++ b/test/torchaudio_unittest/batch_consistency_test.py @@ -1,8 +1,9 @@ """Test numerical consistency among single input and batched input.""" -import unittest import itertools from parameterized import parameterized +import math + import torch import torchaudio import torchaudio.functional as F @@ -59,6 +60,78 @@ def test_detect_pitch_frequency(self, frequency, sample_rate, n_channels): n_channels=n_channels, duration=5) self.assert_batch_consistencies(F.detect_pitch_frequency, waveform, sample_rate) + def test_amplitude_to_DB(self): + torch.manual_seed(0) + spec = torch.rand(2, 100, 100) * 200 + + amplitude_mult = 20. + amin = 1e-10 + ref = 1.0 + db_mult = math.log10(max(amin, ref)) + + # Test with & without a `top_db` clamp + self.assert_batch_consistencies(F.amplitude_to_DB, spec, amplitude_mult, + amin, db_mult, top_db=None) + self.assert_batch_consistencies(F.amplitude_to_DB, spec, amplitude_mult, + amin, db_mult, top_db=40.) + + def test_amplitude_to_DB_itemwise_clamps(self): + """Ensure that the clamps are separate for each spectrogram in a batch. + + The clamp was determined per-batch in a prior implementation, which + meant it was determined by the loudest item, thus items weren't + independent. See: + + https://github.com/pytorch/audio/issues/994 + + """ + amplitude_mult = 20. + amin = 1e-10 + ref = 1.0 + db_mult = math.log10(max(amin, ref)) + top_db = 20. + + # Make a batch of noise + torch.manual_seed(0) + spec = torch.rand([2, 2, 100, 100]) * 200 + # Make one item blow out the other + spec[0] += 50 + + batchwise_dbs = F.amplitude_to_DB(spec, amplitude_mult, amin, + db_mult, top_db=top_db) + itemwise_dbs = torch.stack([ + F.amplitude_to_DB(item, amplitude_mult, amin, + db_mult, top_db=top_db) + for item in spec + ]) + + self.assertEqual(batchwise_dbs, itemwise_dbs) + + def test_amplitude_to_DB_not_channelwise_clamps(self): + """Check that clamps are applied per-item, not per channel.""" + amplitude_mult = 20. + amin = 1e-10 + ref = 1.0 + db_mult = math.log10(max(amin, ref)) + top_db = 40. + + torch.manual_seed(0) + spec = torch.rand([1, 2, 100, 100]) * 200 + # Make one channel blow out the other + spec[:, 0] += 50 + + specwise_dbs = F.amplitude_to_DB(spec, amplitude_mult, amin, + db_mult, top_db=top_db) + channelwise_dbs = torch.stack([ + F.amplitude_to_DB(spec[:, i], amplitude_mult, amin, + db_mult, top_db=top_db) + for i in range(spec.size(-3)) + ]) + + # Just check channelwise gives a different answer. + difference = (specwise_dbs - channelwise_dbs).abs() + assert (difference >= 1e-5).any() + def test_contrast(self): waveform = torch.rand(2, 100) - 0.5 self.assert_batch_consistencies(F.contrast, waveform, enhancement_amount=80.) @@ -103,7 +176,7 @@ class TestTransforms(common_utils.TorchaudioTestCase): """Test suite for classes defined in `transforms` module""" def test_batch_AmplitudeToDB(self): - spec = torch.rand((6, 201)) + spec = torch.rand((2, 6, 201)) # Single then transform then batch expected = torchaudio.transforms.AmplitudeToDB()(spec).repeat(3, 1, 1) diff --git a/test/torchaudio_unittest/common_utils/__init__.py b/test/torchaudio_unittest/common_utils/__init__.py index cf3e717116..8cc44c3529 100644 --- a/test/torchaudio_unittest/common_utils/__init__.py +++ b/test/torchaudio_unittest/common_utils/__init__.py @@ -27,4 +27,8 @@ from .parameterized_utils import ( load_params, ) -from . import sox_utils + +__all__ = ['get_asset_path', 'get_whitenoise', 'get_sinusoid', 'set_audio_backend', + 'TempDirMixin', 'HttpServerMixin', 'TestBaseMixin', 'PytorchTestCase', 'TorchaudioTestCase', + 'skipIfNoCuda', 'skipIfNoExec', 'skipIfNoModule', 'skipIfNoExtension', 'skipIfNoSoxBackend', + 'get_wav_data', 'normalize_wav', 'load_wav', 'save_wav', 'load_params'] diff --git a/test/torchaudio_unittest/compliance_kaldi_test.py b/test/torchaudio_unittest/compliance_kaldi_test.py index 43e9865e2f..c7b4149819 100644 --- a/test/torchaudio_unittest/compliance_kaldi_test.py +++ b/test/torchaudio_unittest/compliance_kaldi_test.py @@ -1,6 +1,5 @@ import os import math -import unittest import torch import torchaudio diff --git a/test/torchaudio_unittest/datasets/datasets_test.py b/test/torchaudio_unittest/datasets/datasets_test.py index cd04c4d447..fda0804ea6 100644 --- a/test/torchaudio_unittest/datasets/datasets_test.py +++ b/test/torchaudio_unittest/datasets/datasets_test.py @@ -1,5 +1,3 @@ -from torchaudio.datasets.librispeech import LIBRISPEECH -from torchaudio.datasets.speechcommands import SPEECHCOMMANDS from torchaudio.datasets.vctk import VCTK from torchaudio_unittest.common_utils import ( diff --git a/test/torchaudio_unittest/functional/functional_cpu_test.py b/test/torchaudio_unittest/functional/functional_cpu_test.py index c4ba42391d..21e5a3e1b7 100644 --- a/test/torchaudio_unittest/functional/functional_cpu_test.py +++ b/test/torchaudio_unittest/functional/functional_cpu_test.py @@ -83,46 +83,78 @@ def test_pitch(self, frequency): self.assertFalse(s) -class TestDB_to_amplitude(common_utils.TorchaudioTestCase): - def test_DB_to_amplitude(self): - # Make some noise - x = torch.rand(1000) - spectrogram = torchaudio.transforms.Spectrogram() - spec = spectrogram(x) - +class Testamplitude_to_DB(common_utils.TorchaudioTestCase): + @parameterized.expand([ + ([100, 100],), + ([2, 100, 100],), + ([2, 2, 100, 100],), + ]) + def test_reversible(self, shape): + """Round trip between amplitude and db should return the original for various shape + + This implicitly also tests `DB_to_amplitude`. + + """ + amplitude_mult = 20. + power_mult = 10. amin = 1e-10 ref = 1.0 - db_multiplier = math.log10(max(amin, ref)) - - # Waveform amplitude -> DB -> amplitude - multiplier = 20. - power = 0.5 - - db = F.amplitude_to_DB(torch.abs(x), multiplier, amin, db_multiplier, top_db=None) - x2 = F.DB_to_amplitude(db, ref, power) + db_mult = math.log10(max(amin, ref)) - self.assertEqual(x2, torch.abs(x), atol=5e-5, rtol=1e-5) + torch.manual_seed(0) + spec = torch.rand(*shape) * 200 # Spectrogram amplitude -> DB -> amplitude - db = F.amplitude_to_DB(spec, multiplier, amin, db_multiplier, top_db=None) - x2 = F.DB_to_amplitude(db, ref, power) + db = F.amplitude_to_DB(spec, amplitude_mult, amin, db_mult, top_db=None) + x2 = F.DB_to_amplitude(db, ref, 0.5) self.assertEqual(x2, spec, atol=5e-5, rtol=1e-5) - # Waveform power -> DB -> power - multiplier = 10. - power = 1. - - db = F.amplitude_to_DB(x, multiplier, amin, db_multiplier, top_db=None) - x2 = F.DB_to_amplitude(db, ref, power) - - self.assertEqual(x2, torch.abs(x), atol=5e-5, rtol=1e-5) - # Spectrogram power -> DB -> power - db = F.amplitude_to_DB(spec, multiplier, amin, db_multiplier, top_db=None) - x2 = F.DB_to_amplitude(db, ref, power) - - self.assertEqual(x2, spec, atol=5e-5, rtol=1e-5) + db = F.amplitude_to_DB(spec, power_mult, amin, db_mult, top_db=None) + x2 = F.DB_to_amplitude(db, ref, 1.) + + self.assertEqual(x2, spec) + + @parameterized.expand([ + ([100, 100],), + ([2, 100, 100],), + ([2, 2, 100, 100],), + ]) + def test_top_db_clamp(self, shape): + """Ensure values are properly clamped when `top_db` is supplied.""" + amplitude_mult = 20. + amin = 1e-10 + ref = 1.0 + db_mult = math.log10(max(amin, ref)) + top_db = 40. + + torch.manual_seed(0) + # A random tensor is used for increased entropy, but the max and min for + # each spectrogram still need to be predictable. The max determines the + # decibel cutoff, and the distance from the min must be large enough + # that it triggers a clamp. + spec = torch.rand(*shape) + # Ensure each spectrogram has a min of 0 and a max of 1. + spec -= spec.amin([-2, -1])[..., None, None] + spec /= spec.amax([-2, -1])[..., None, None] + # Expand the range to (0, 200) - wide enough to properly test clamping. + spec *= 200 + + decibels = F.amplitude_to_DB(spec, amplitude_mult, amin, + db_mult, top_db=top_db) + # Ensure the clamp was applied + below_limit = decibels < 6.0205 + assert not below_limit.any(), ( + "{} decibel values were below the expected cutoff:\n{}".format( + below_limit.sum().item(), decibels + ) + ) + # Ensure it didn't over-clamp + close_to_limit = decibels < 6.0207 + assert close_to_limit.any(), ( + f"No values were close to the limit. Did it over-clamp?\n{decibels}" + ) class TestComplexNorm(common_utils.TorchaudioTestCase): diff --git a/test/torchaudio_unittest/functional/torchscript_consistency_cpu_test.py b/test/torchaudio_unittest/functional/torchscript_consistency_cpu_test.py new file mode 100644 index 0000000000..06871f9bde --- /dev/null +++ b/test/torchaudio_unittest/functional/torchscript_consistency_cpu_test.py @@ -0,0 +1,14 @@ +import torch + +from torchaudio_unittest.common_utils import PytorchTestCase +from .torchscript_consistency_impl import Functional + + +class TestFunctionalFloat32(Functional, PytorchTestCase): + dtype = torch.float32 + device = torch.device('cpu') + + +class TestFunctionalFloat64(Functional, PytorchTestCase): + dtype = torch.float64 + device = torch.device('cpu') diff --git a/test/torchaudio_unittest/functional/torchscript_consistency_cuda_test.py b/test/torchaudio_unittest/functional/torchscript_consistency_cuda_test.py new file mode 100644 index 0000000000..53ccbad3c9 --- /dev/null +++ b/test/torchaudio_unittest/functional/torchscript_consistency_cuda_test.py @@ -0,0 +1,16 @@ +import torch + +from torchaudio_unittest.common_utils import skipIfNoCuda, PytorchTestCase +from .torchscript_consistency_impl import Functional + + +@skipIfNoCuda +class TestFunctionalFloat32(Functional, PytorchTestCase): + dtype = torch.float32 + device = torch.device('cuda') + + +@skipIfNoCuda +class TestFunctionalFloat64(Functional, PytorchTestCase): + dtype = torch.float64 + device = torch.device('cuda') diff --git a/test/torchaudio_unittest/functional/torchscript_consistency_impl.py b/test/torchaudio_unittest/functional/torchscript_consistency_impl.py new file mode 100644 index 0000000000..83f7e8e95d --- /dev/null +++ b/test/torchaudio_unittest/functional/torchscript_consistency_impl.py @@ -0,0 +1,549 @@ +"""Test suites for jit-ability and its numerical compatibility""" +import unittest + +import torch +import torchaudio.functional as F + +from torchaudio_unittest import common_utils + + +class Functional(common_utils.TestBaseMixin): + """Implements test for `functinoal` modul that are performed for different devices""" + def _assert_consistency(self, func, tensor, shape_only=False): + tensor = tensor.to(device=self.device, dtype=self.dtype) + + ts_func = torch.jit.script(func) + output = func(tensor) + ts_output = ts_func(tensor) + if shape_only: + ts_output = ts_output.shape + output = output.shape + self.assertEqual(ts_output, output) + + def test_spectrogram(self): + def func(tensor): + n_fft = 400 + ws = 400 + hop = 200 + pad = 0 + window = torch.hann_window(ws, device=tensor.device, dtype=tensor.dtype) + power = 2. + normalize = False + return F.spectrogram(tensor, pad, window, n_fft, hop, ws, power, normalize) + + tensor = common_utils.get_whitenoise() + self._assert_consistency(func, tensor) + + def test_griffinlim(self): + def func(tensor): + n_fft = 400 + ws = 400 + hop = 200 + window = torch.hann_window(ws, device=tensor.device, dtype=tensor.dtype) + power = 2. + normalize = False + momentum = 0.99 + n_iter = 32 + length = 1000 + rand_int = False + return F.griffinlim(tensor, window, n_fft, hop, ws, power, normalize, n_iter, momentum, length, rand_int) + + tensor = torch.rand((1, 201, 6)) + self._assert_consistency(func, tensor) + + def test_compute_deltas(self): + def func(tensor): + win_length = 2 * 7 + 1 + return F.compute_deltas(tensor, win_length=win_length) + + channel = 13 + n_mfcc = channel * 3 + time = 1021 + tensor = torch.randn(channel, n_mfcc, time) + self._assert_consistency(func, tensor) + + def test_detect_pitch_frequency(self): + waveform = common_utils.get_sinusoid(sample_rate=44100) + + def func(tensor): + sample_rate = 44100 + return F.detect_pitch_frequency(tensor, sample_rate) + + self._assert_consistency(func, waveform) + + def test_create_fb_matrix(self): + if self.device != torch.device('cpu'): + raise unittest.SkipTest('No need to perform test on device other than CPU') + + def func(_): + n_stft = 100 + f_min = 0.0 + f_max = 20.0 + n_mels = 10 + sample_rate = 16000 + norm = "slaney" + return F.create_fb_matrix(n_stft, f_min, f_max, n_mels, sample_rate, norm) + + dummy = torch.zeros(1, 1) + self._assert_consistency(func, dummy) + + def test_amplitude_to_DB(self): + def func(tensor): + multiplier = 10.0 + amin = 1e-10 + db_multiplier = 0.0 + top_db = 80.0 + return F.amplitude_to_DB(tensor, multiplier, amin, db_multiplier, top_db) + + tensor = torch.rand((6, 201)) + self._assert_consistency(func, tensor) + + def test_DB_to_amplitude(self): + def func(tensor): + ref = 1. + power = 1. + return F.DB_to_amplitude(tensor, ref, power) + + tensor = torch.rand((1, 100)) + self._assert_consistency(func, tensor) + + def test_create_dct(self): + if self.device != torch.device('cpu'): + raise unittest.SkipTest('No need to perform test on device other than CPU') + + def func(_): + n_mfcc = 40 + n_mels = 128 + norm = "ortho" + return F.create_dct(n_mfcc, n_mels, norm) + + dummy = torch.zeros(1, 1) + self._assert_consistency(func, dummy) + + def test_mu_law_encoding(self): + def func(tensor): + qc = 256 + return F.mu_law_encoding(tensor, qc) + + waveform = common_utils.get_whitenoise() + self._assert_consistency(func, waveform) + + def test_mu_law_decoding(self): + def func(tensor): + qc = 256 + return F.mu_law_decoding(tensor, qc) + + tensor = torch.rand((1, 10)) + self._assert_consistency(func, tensor) + + def test_complex_norm(self): + def func(tensor): + power = 2. + return F.complex_norm(tensor, power) + + tensor = torch.randn(1, 2, 1025, 400, 2) + self._assert_consistency(func, tensor) + + def test_mask_along_axis(self): + def func(tensor): + mask_param = 100 + mask_value = 30. + axis = 2 + return F.mask_along_axis(tensor, mask_param, mask_value, axis) + + tensor = torch.randn(2, 1025, 400) + self._assert_consistency(func, tensor) + + def test_mask_along_axis_iid(self): + def func(tensor): + mask_param = 100 + mask_value = 30. + axis = 2 + return F.mask_along_axis_iid(tensor, mask_param, mask_value, axis) + + tensor = torch.randn(4, 2, 1025, 400) + self._assert_consistency(func, tensor) + + def test_gain(self): + def func(tensor): + gainDB = 2.0 + return F.gain(tensor, gainDB) + + tensor = torch.rand((1, 1000)) + self._assert_consistency(func, tensor) + + def test_dither_TPDF(self): + def func(tensor): + return F.dither(tensor, 'TPDF') + + tensor = common_utils.get_whitenoise(n_channels=2) + self._assert_consistency(func, tensor, shape_only=True) + + def test_dither_RPDF(self): + def func(tensor): + return F.dither(tensor, 'RPDF') + + tensor = common_utils.get_whitenoise(n_channels=2) + self._assert_consistency(func, tensor, shape_only=True) + + def test_dither_GPDF(self): + def func(tensor): + return F.dither(tensor, 'GPDF') + + tensor = common_utils.get_whitenoise(n_channels=2) + self._assert_consistency(func, tensor, shape_only=True) + + def test_dither_noise_shaping(self): + def func(tensor): + return F.dither(tensor, noise_shaping=True) + + tensor = common_utils.get_whitenoise(n_channels=2) + self._assert_consistency(func, tensor) + + def test_lfilter(self): + if self.dtype == torch.float64: + raise unittest.SkipTest("This test is known to fail for float64") + + waveform = common_utils.get_whitenoise() + + def func(tensor): + # Design an IIR lowpass filter using scipy.signal filter design + # https://docs.scipy.org/doc/scipy/reference/generated/scipy.signal.iirdesign.html#scipy.signal.iirdesign + # + # Example + # >>> from scipy.signal import iirdesign + # >>> b, a = iirdesign(0.2, 0.3, 1, 60) + b_coeffs = torch.tensor( + [ + 0.00299893, + -0.0051152, + 0.00841964, + -0.00747802, + 0.00841964, + -0.0051152, + 0.00299893, + ], + device=tensor.device, + dtype=tensor.dtype, + ) + a_coeffs = torch.tensor( + [ + 1.0, + -4.8155751, + 10.2217618, + -12.14481273, + 8.49018171, + -3.3066882, + 0.56088705, + ], + device=tensor.device, + dtype=tensor.dtype, + ) + return F.lfilter(tensor, a_coeffs, b_coeffs) + + self._assert_consistency(func, waveform) + + def test_lowpass(self): + if self.dtype == torch.float64: + raise unittest.SkipTest("This test is known to fail for float64") + + waveform = common_utils.get_whitenoise(sample_rate=44100) + + def func(tensor): + sample_rate = 44100 + cutoff_freq = 3000. + return F.lowpass_biquad(tensor, sample_rate, cutoff_freq) + + self._assert_consistency(func, waveform) + + def test_highpass(self): + if self.dtype == torch.float64: + raise unittest.SkipTest("This test is known to fail for float64") + + waveform = common_utils.get_whitenoise(sample_rate=44100) + + def func(tensor): + sample_rate = 44100 + cutoff_freq = 2000. + return F.highpass_biquad(tensor, sample_rate, cutoff_freq) + + self._assert_consistency(func, waveform) + + def test_allpass(self): + if self.dtype == torch.float64: + raise unittest.SkipTest("This test is known to fail for float64") + + waveform = common_utils.get_whitenoise(sample_rate=44100) + + def func(tensor): + sample_rate = 44100 + central_freq = 1000. + q = 0.707 + return F.allpass_biquad(tensor, sample_rate, central_freq, q) + + self._assert_consistency(func, waveform) + + def test_bandpass_with_csg(self): + if self.dtype == torch.float64: + raise unittest.SkipTest("This test is known to fail for float64") + + waveform = common_utils.get_whitenoise(sample_rate=44100) + + def func(tensor): + sample_rate = 44100 + central_freq = 1000. + q = 0.707 + const_skirt_gain = True + return F.bandpass_biquad(tensor, sample_rate, central_freq, q, const_skirt_gain) + + self._assert_consistency(func, waveform) + + def test_bandpass_without_csg(self): + if self.dtype == torch.float64: + raise unittest.SkipTest("This test is known to fail for float64") + + waveform = common_utils.get_whitenoise(sample_rate=44100) + + def func(tensor): + sample_rate = 44100 + central_freq = 1000. + q = 0.707 + const_skirt_gain = True + return F.bandpass_biquad(tensor, sample_rate, central_freq, q, const_skirt_gain) + + self._assert_consistency(func, waveform) + + def test_bandreject(self): + if self.dtype == torch.float64: + raise unittest.SkipTest("This test is known to fail for float64") + + waveform = common_utils.get_whitenoise(sample_rate=44100) + + def func(tensor): + sample_rate = 44100 + central_freq = 1000. + q = 0.707 + return F.bandreject_biquad(tensor, sample_rate, central_freq, q) + + self._assert_consistency(func, waveform) + + def test_band_with_noise(self): + if self.dtype == torch.float64: + raise unittest.SkipTest("This test is known to fail for float64") + + waveform = common_utils.get_whitenoise(sample_rate=44100) + + def func(tensor): + sample_rate = 44100 + central_freq = 1000. + q = 0.707 + noise = True + return F.band_biquad(tensor, sample_rate, central_freq, q, noise) + + self._assert_consistency(func, waveform) + + def test_band_without_noise(self): + if self.dtype == torch.float64: + raise unittest.SkipTest("This test is known to fail for float64") + + waveform = common_utils.get_whitenoise(sample_rate=44100) + + def func(tensor): + sample_rate = 44100 + central_freq = 1000. + q = 0.707 + noise = False + return F.band_biquad(tensor, sample_rate, central_freq, q, noise) + + self._assert_consistency(func, waveform) + + def test_treble(self): + if self.dtype == torch.float64: + raise unittest.SkipTest("This test is known to fail for float64") + + waveform = common_utils.get_whitenoise(sample_rate=44100) + + def func(tensor): + sample_rate = 44100 + gain = 40. + central_freq = 1000. + q = 0.707 + return F.treble_biquad(tensor, sample_rate, gain, central_freq, q) + + self._assert_consistency(func, waveform) + + def test_bass(self): + if self.dtype == torch.float64: + raise unittest.SkipTest("This test is known to fail for float64") + + waveform = common_utils.get_whitenoise(sample_rate=44100) + + def func(tensor): + sample_rate = 44100 + gain = 40. + central_freq = 1000. + q = 0.707 + return F.bass_biquad(tensor, sample_rate, gain, central_freq, q) + + self._assert_consistency(func, waveform) + + def test_deemph(self): + if self.dtype == torch.float64: + raise unittest.SkipTest("This test is known to fail for float64") + + waveform = common_utils.get_whitenoise(sample_rate=44100) + + def func(tensor): + sample_rate = 44100 + return F.deemph_biquad(tensor, sample_rate) + + self._assert_consistency(func, waveform) + + def test_riaa(self): + if self.dtype == torch.float64: + raise unittest.SkipTest("This test is known to fail for float64") + + waveform = common_utils.get_whitenoise(sample_rate=44100) + + def func(tensor): + sample_rate = 44100 + return F.riaa_biquad(tensor, sample_rate) + + self._assert_consistency(func, waveform) + + def test_equalizer(self): + if self.dtype == torch.float64: + raise unittest.SkipTest("This test is known to fail for float64") + + waveform = common_utils.get_whitenoise(sample_rate=44100) + + def func(tensor): + sample_rate = 44100 + center_freq = 300. + gain = 1. + q = 0.707 + return F.equalizer_biquad(tensor, sample_rate, center_freq, gain, q) + + self._assert_consistency(func, waveform) + + def test_perf_biquad_filtering(self): + if self.dtype == torch.float64: + raise unittest.SkipTest("This test is known to fail for float64") + + waveform = common_utils.get_whitenoise() + + def func(tensor): + a = torch.tensor([0.7, 0.2, 0.6], device=tensor.device, dtype=tensor.dtype) + b = torch.tensor([0.4, 0.2, 0.9], device=tensor.device, dtype=tensor.dtype) + return F.lfilter(tensor, a, b) + + self._assert_consistency(func, waveform) + + def test_sliding_window_cmn(self): + def func(tensor): + cmn_window = 600 + min_cmn_window = 100 + center = False + norm_vars = False + a = torch.tensor( + [ + [ + -1.915875792503357, + 1.147700309753418 + ], + [ + 1.8242558240890503, + 1.3869990110397339 + ] + ], + device=tensor.device, + dtype=tensor.dtype + ) + return F.sliding_window_cmn(a, cmn_window, min_cmn_window, center, norm_vars) + b = torch.tensor( + [ + [ + -1.8701, + -0.1196 + ], + [ + 1.8701, + 0.1196 + ] + ] + ) + self._assert_consistency(func, b) + + def test_contrast(self): + waveform = common_utils.get_whitenoise() + + def func(tensor): + enhancement_amount = 80. + return F.contrast(tensor, enhancement_amount) + + self._assert_consistency(func, waveform) + + def test_dcshift(self): + waveform = common_utils.get_whitenoise() + + def func(tensor): + shift = 0.5 + limiter_gain = 0.05 + return F.dcshift(tensor, shift, limiter_gain) + + self._assert_consistency(func, waveform) + + def test_overdrive(self): + waveform = common_utils.get_whitenoise() + + def func(tensor): + gain = 30. + colour = 50. + return F.overdrive(tensor, gain, colour) + + self._assert_consistency(func, waveform) + + def test_phaser(self): + waveform = common_utils.get_whitenoise(sample_rate=44100) + + def func(tensor): + gain_in = 0.5 + gain_out = 0.8 + delay_ms = 2.0 + decay = 0.4 + speed = 0.5 + sample_rate = 44100 + return F.phaser(tensor, sample_rate, gain_in, gain_out, delay_ms, decay, speed, sinusoidal=True) + + self._assert_consistency(func, waveform) + + def test_flanger(self): + torch.random.manual_seed(40) + waveform = torch.rand(2, 100) - 0.5 + + def func(tensor): + delay = 0.8 + depth = 0.88 + regen = 3.0 + width = 0.23 + speed = 1.3 + phase = 60. + sample_rate = 44100 + return F.flanger(tensor, sample_rate, delay, depth, regen, width, speed, + phase, modulation='sinusoidal', interpolation='linear') + + self._assert_consistency(func, waveform) + + def test_spectral_centroid(self): + + def func(tensor): + sample_rate = 44100 + n_fft = 400 + ws = 400 + hop = 200 + pad = 0 + window = torch.hann_window(ws, device=tensor.device, dtype=tensor.dtype) + return F.spectral_centroid(tensor, sample_rate, pad, window, n_fft, hop, ws) + + tensor = common_utils.get_whitenoise(sample_rate=44100) + self._assert_consistency(func, tensor) diff --git a/test/torchaudio_unittest/kaldi_io_test.py b/test/torchaudio_unittest/kaldi_io_test.py index 2153b4cc02..4ceeeebbc5 100644 --- a/test/torchaudio_unittest/kaldi_io_test.py +++ b/test/torchaudio_unittest/kaldi_io_test.py @@ -1,5 +1,3 @@ -import unittest - import torch import torchaudio.kaldi_io as kio diff --git a/test/torchaudio_unittest/sox_compatibility_test.py b/test/torchaudio_unittest/sox_compatibility_test.py index ade98b2aeb..c68e529427 100644 --- a/test/torchaudio_unittest/sox_compatibility_test.py +++ b/test/torchaudio_unittest/sox_compatibility_test.py @@ -1,5 +1,3 @@ -import unittest - import torch import torchaudio.functional as F import torchaudio.transforms as T diff --git a/test/torchaudio_unittest/sox_effect/smoke_test.py b/test/torchaudio_unittest/sox_effect/smoke_test.py index 2a8d9e7ff9..3b2b34d3ec 100644 --- a/test/torchaudio_unittest/sox_effect/smoke_test.py +++ b/test/torchaudio_unittest/sox_effect/smoke_test.py @@ -10,7 +10,6 @@ save_wav, ) from .common import ( - name_func, load_params, ) diff --git a/test/torchaudio_unittest/torchscript_consistency_cpu_test.py b/test/torchaudio_unittest/torchscript_consistency_cpu_test.py index fcc9cb8389..9092f3a64b 100644 --- a/test/torchaudio_unittest/torchscript_consistency_cpu_test.py +++ b/test/torchaudio_unittest/torchscript_consistency_cpu_test.py @@ -1,24 +1,14 @@ import torch -from torchaudio_unittest import common_utils -from .torchscript_consistency_impl import Functional, Transforms +from torchaudio_unittest.common_utils import PytorchTestCase +from .torchscript_consistency_impl import Transforms -class TestFunctionalFloat32(Functional, common_utils.PytorchTestCase): +class TestTransformsFloat32(Transforms, PytorchTestCase): dtype = torch.float32 device = torch.device('cpu') -class TestFunctionalFloat64(Functional, common_utils.PytorchTestCase): - dtype = torch.float64 - device = torch.device('cpu') - - -class TestTransformsFloat32(Transforms, common_utils.PytorchTestCase): - dtype = torch.float32 - device = torch.device('cpu') - - -class TestTransformsFloat64(Transforms, common_utils.PytorchTestCase): +class TestTransformsFloat64(Transforms, PytorchTestCase): dtype = torch.float64 device = torch.device('cpu') diff --git a/test/torchaudio_unittest/torchscript_consistency_cuda_test.py b/test/torchaudio_unittest/torchscript_consistency_cuda_test.py index c205e192ed..7425647bab 100644 --- a/test/torchaudio_unittest/torchscript_consistency_cuda_test.py +++ b/test/torchaudio_unittest/torchscript_consistency_cuda_test.py @@ -1,28 +1,16 @@ import torch -from torchaudio_unittest import common_utils -from .torchscript_consistency_impl import Functional, Transforms +from torchaudio_unittest.common_utils import skipIfNoCuda, PytorchTestCase +from .torchscript_consistency_impl import Transforms -@common_utils.skipIfNoCuda -class TestFunctionalFloat32(Functional, common_utils.PytorchTestCase): +@skipIfNoCuda +class TestTransformsFloat32(Transforms, PytorchTestCase): dtype = torch.float32 device = torch.device('cuda') -@common_utils.skipIfNoCuda -class TestFunctionalFloat64(Functional, common_utils.PytorchTestCase): - dtype = torch.float64 - device = torch.device('cuda') - - -@common_utils.skipIfNoCuda -class TestTransformsFloat32(Transforms, common_utils.PytorchTestCase): - dtype = torch.float32 - device = torch.device('cuda') - - -@common_utils.skipIfNoCuda -class TestTransformsFloat64(Transforms, common_utils.PytorchTestCase): +@skipIfNoCuda +class TestTransformsFloat64(Transforms, PytorchTestCase): dtype = torch.float64 device = torch.device('cuda') diff --git a/test/torchaudio_unittest/torchscript_consistency_impl.py b/test/torchaudio_unittest/torchscript_consistency_impl.py index ab681b999b..492e1e4a92 100644 --- a/test/torchaudio_unittest/torchscript_consistency_impl.py +++ b/test/torchaudio_unittest/torchscript_consistency_impl.py @@ -1,555 +1,11 @@ """Test suites for jit-ability and its numerical compatibility""" -import unittest import torch -import torchaudio.functional as F import torchaudio.transforms as T from torchaudio_unittest import common_utils -class Functional(common_utils.TestBaseMixin): - """Implements test for `functinoal` modul that are performed for different devices""" - def _assert_consistency(self, func, tensor, shape_only=False): - tensor = tensor.to(device=self.device, dtype=self.dtype) - - ts_func = torch.jit.script(func) - output = func(tensor) - ts_output = ts_func(tensor) - if shape_only: - ts_output = ts_output.shape - output = output.shape - self.assertEqual(ts_output, output) - - def test_spectrogram(self): - def func(tensor): - n_fft = 400 - ws = 400 - hop = 200 - pad = 0 - window = torch.hann_window(ws, device=tensor.device, dtype=tensor.dtype) - power = 2. - normalize = False - return F.spectrogram(tensor, pad, window, n_fft, hop, ws, power, normalize) - - tensor = common_utils.get_whitenoise() - self._assert_consistency(func, tensor) - - def test_griffinlim(self): - def func(tensor): - n_fft = 400 - ws = 400 - hop = 200 - window = torch.hann_window(ws, device=tensor.device, dtype=tensor.dtype) - power = 2. - normalize = False - momentum = 0.99 - n_iter = 32 - length = 1000 - rand_int = False - return F.griffinlim(tensor, window, n_fft, hop, ws, power, normalize, n_iter, momentum, length, rand_int) - - tensor = torch.rand((1, 201, 6)) - self._assert_consistency(func, tensor) - - def test_compute_deltas(self): - def func(tensor): - win_length = 2 * 7 + 1 - return F.compute_deltas(tensor, win_length=win_length) - - channel = 13 - n_mfcc = channel * 3 - time = 1021 - tensor = torch.randn(channel, n_mfcc, time) - self._assert_consistency(func, tensor) - - def test_detect_pitch_frequency(self): - waveform = common_utils.get_sinusoid(sample_rate=44100) - - def func(tensor): - sample_rate = 44100 - return F.detect_pitch_frequency(tensor, sample_rate) - - self._assert_consistency(func, waveform) - - def test_create_fb_matrix(self): - if self.device != torch.device('cpu'): - raise unittest.SkipTest('No need to perform test on device other than CPU') - - def func(_): - n_stft = 100 - f_min = 0.0 - f_max = 20.0 - n_mels = 10 - sample_rate = 16000 - norm = "slaney" - return F.create_fb_matrix(n_stft, f_min, f_max, n_mels, sample_rate, norm) - - dummy = torch.zeros(1, 1) - self._assert_consistency(func, dummy) - - def test_amplitude_to_DB(self): - def func(tensor): - multiplier = 10.0 - amin = 1e-10 - db_multiplier = 0.0 - top_db = 80.0 - return F.amplitude_to_DB(tensor, multiplier, amin, db_multiplier, top_db) - - tensor = torch.rand((6, 201)) - self._assert_consistency(func, tensor) - - def test_DB_to_amplitude(self): - def func(tensor): - ref = 1. - power = 1. - return F.DB_to_amplitude(tensor, ref, power) - - tensor = torch.rand((1, 100)) - self._assert_consistency(func, tensor) - - def test_create_dct(self): - if self.device != torch.device('cpu'): - raise unittest.SkipTest('No need to perform test on device other than CPU') - - def func(_): - n_mfcc = 40 - n_mels = 128 - norm = "ortho" - return F.create_dct(n_mfcc, n_mels, norm) - - dummy = torch.zeros(1, 1) - self._assert_consistency(func, dummy) - - def test_mu_law_encoding(self): - def func(tensor): - qc = 256 - return F.mu_law_encoding(tensor, qc) - - waveform = common_utils.get_whitenoise() - self._assert_consistency(func, waveform) - - def test_mu_law_decoding(self): - def func(tensor): - qc = 256 - return F.mu_law_decoding(tensor, qc) - - tensor = torch.rand((1, 10)) - self._assert_consistency(func, tensor) - - def test_complex_norm(self): - def func(tensor): - power = 2. - return F.complex_norm(tensor, power) - - tensor = torch.randn(1, 2, 1025, 400, 2) - self._assert_consistency(func, tensor) - - def test_mask_along_axis(self): - def func(tensor): - mask_param = 100 - mask_value = 30. - axis = 2 - return F.mask_along_axis(tensor, mask_param, mask_value, axis) - - tensor = torch.randn(2, 1025, 400) - self._assert_consistency(func, tensor) - - def test_mask_along_axis_iid(self): - def func(tensor): - mask_param = 100 - mask_value = 30. - axis = 2 - return F.mask_along_axis_iid(tensor, mask_param, mask_value, axis) - - tensor = torch.randn(4, 2, 1025, 400) - self._assert_consistency(func, tensor) - - def test_gain(self): - def func(tensor): - gainDB = 2.0 - return F.gain(tensor, gainDB) - - tensor = torch.rand((1, 1000)) - self._assert_consistency(func, tensor) - - def test_dither_TPDF(self): - def func(tensor): - return F.dither(tensor, 'TPDF') - - tensor = common_utils.get_whitenoise(n_channels=2) - self._assert_consistency(func, tensor, shape_only=True) - - def test_dither_RPDF(self): - def func(tensor): - return F.dither(tensor, 'RPDF') - - tensor = common_utils.get_whitenoise(n_channels=2) - self._assert_consistency(func, tensor, shape_only=True) - - def test_dither_GPDF(self): - def func(tensor): - return F.dither(tensor, 'GPDF') - - tensor = common_utils.get_whitenoise(n_channels=2) - self._assert_consistency(func, tensor, shape_only=True) - - def test_dither_noise_shaping(self): - def func(tensor): - return F.dither(tensor, noise_shaping=True) - - tensor = common_utils.get_whitenoise(n_channels=2) - self._assert_consistency(func, tensor) - - def test_lfilter(self): - if self.dtype == torch.float64: - raise unittest.SkipTest("This test is known to fail for float64") - - waveform = common_utils.get_whitenoise() - - def func(tensor): - # Design an IIR lowpass filter using scipy.signal filter design - # https://docs.scipy.org/doc/scipy/reference/generated/scipy.signal.iirdesign.html#scipy.signal.iirdesign - # - # Example - # >>> from scipy.signal import iirdesign - # >>> b, a = iirdesign(0.2, 0.3, 1, 60) - b_coeffs = torch.tensor( - [ - 0.00299893, - -0.0051152, - 0.00841964, - -0.00747802, - 0.00841964, - -0.0051152, - 0.00299893, - ], - device=tensor.device, - dtype=tensor.dtype, - ) - a_coeffs = torch.tensor( - [ - 1.0, - -4.8155751, - 10.2217618, - -12.14481273, - 8.49018171, - -3.3066882, - 0.56088705, - ], - device=tensor.device, - dtype=tensor.dtype, - ) - return F.lfilter(tensor, a_coeffs, b_coeffs) - - self._assert_consistency(func, waveform) - - def test_lowpass(self): - if self.dtype == torch.float64: - raise unittest.SkipTest("This test is known to fail for float64") - - waveform = common_utils.get_whitenoise(sample_rate=44100) - - def func(tensor): - sample_rate = 44100 - cutoff_freq = 3000. - return F.lowpass_biquad(tensor, sample_rate, cutoff_freq) - - self._assert_consistency(func, waveform) - - def test_highpass(self): - if self.dtype == torch.float64: - raise unittest.SkipTest("This test is known to fail for float64") - - waveform = common_utils.get_whitenoise(sample_rate=44100) - - def func(tensor): - sample_rate = 44100 - cutoff_freq = 2000. - return F.highpass_biquad(tensor, sample_rate, cutoff_freq) - - self._assert_consistency(func, waveform) - - def test_allpass(self): - if self.dtype == torch.float64: - raise unittest.SkipTest("This test is known to fail for float64") - - waveform = common_utils.get_whitenoise(sample_rate=44100) - - def func(tensor): - sample_rate = 44100 - central_freq = 1000. - q = 0.707 - return F.allpass_biquad(tensor, sample_rate, central_freq, q) - - self._assert_consistency(func, waveform) - - def test_bandpass_with_csg(self): - if self.dtype == torch.float64: - raise unittest.SkipTest("This test is known to fail for float64") - - waveform = common_utils.get_whitenoise(sample_rate=44100) - - def func(tensor): - sample_rate = 44100 - central_freq = 1000. - q = 0.707 - const_skirt_gain = True - return F.bandpass_biquad(tensor, sample_rate, central_freq, q, const_skirt_gain) - - self._assert_consistency(func, waveform) - - def test_bandpass_without_csg(self): - if self.dtype == torch.float64: - raise unittest.SkipTest("This test is known to fail for float64") - - waveform = common_utils.get_whitenoise(sample_rate=44100) - - def func(tensor): - sample_rate = 44100 - central_freq = 1000. - q = 0.707 - const_skirt_gain = True - return F.bandpass_biquad(tensor, sample_rate, central_freq, q, const_skirt_gain) - - self._assert_consistency(func, waveform) - - def test_bandreject(self): - if self.dtype == torch.float64: - raise unittest.SkipTest("This test is known to fail for float64") - - waveform = common_utils.get_whitenoise(sample_rate=44100) - - def func(tensor): - sample_rate = 44100 - central_freq = 1000. - q = 0.707 - return F.bandreject_biquad(tensor, sample_rate, central_freq, q) - - self._assert_consistency(func, waveform) - - def test_band_with_noise(self): - if self.dtype == torch.float64: - raise unittest.SkipTest("This test is known to fail for float64") - - waveform = common_utils.get_whitenoise(sample_rate=44100) - - def func(tensor): - sample_rate = 44100 - central_freq = 1000. - q = 0.707 - noise = True - return F.band_biquad(tensor, sample_rate, central_freq, q, noise) - - self._assert_consistency(func, waveform) - - def test_band_without_noise(self): - if self.dtype == torch.float64: - raise unittest.SkipTest("This test is known to fail for float64") - - waveform = common_utils.get_whitenoise(sample_rate=44100) - - def func(tensor): - sample_rate = 44100 - central_freq = 1000. - q = 0.707 - noise = False - return F.band_biquad(tensor, sample_rate, central_freq, q, noise) - - self._assert_consistency(func, waveform) - - def test_treble(self): - if self.dtype == torch.float64: - raise unittest.SkipTest("This test is known to fail for float64") - - waveform = common_utils.get_whitenoise(sample_rate=44100) - - def func(tensor): - sample_rate = 44100 - gain = 40. - central_freq = 1000. - q = 0.707 - return F.treble_biquad(tensor, sample_rate, gain, central_freq, q) - - self._assert_consistency(func, waveform) - - def test_bass(self): - if self.dtype == torch.float64: - raise unittest.SkipTest("This test is known to fail for float64") - - waveform = common_utils.get_whitenoise(sample_rate=44100) - - def func(tensor): - sample_rate = 44100 - gain = 40. - central_freq = 1000. - q = 0.707 - return F.bass_biquad(tensor, sample_rate, gain, central_freq, q) - - self._assert_consistency(func, waveform) - - def test_deemph(self): - if self.dtype == torch.float64: - raise unittest.SkipTest("This test is known to fail for float64") - - waveform = common_utils.get_whitenoise(sample_rate=44100) - - def func(tensor): - sample_rate = 44100 - return F.deemph_biquad(tensor, sample_rate) - - self._assert_consistency(func, waveform) - - def test_riaa(self): - if self.dtype == torch.float64: - raise unittest.SkipTest("This test is known to fail for float64") - - waveform = common_utils.get_whitenoise(sample_rate=44100) - - def func(tensor): - sample_rate = 44100 - return F.riaa_biquad(tensor, sample_rate) - - self._assert_consistency(func, waveform) - - def test_equalizer(self): - if self.dtype == torch.float64: - raise unittest.SkipTest("This test is known to fail for float64") - - waveform = common_utils.get_whitenoise(sample_rate=44100) - - def func(tensor): - sample_rate = 44100 - center_freq = 300. - gain = 1. - q = 0.707 - return F.equalizer_biquad(tensor, sample_rate, center_freq, gain, q) - - self._assert_consistency(func, waveform) - - def test_perf_biquad_filtering(self): - if self.dtype == torch.float64: - raise unittest.SkipTest("This test is known to fail for float64") - - waveform = common_utils.get_whitenoise() - - def func(tensor): - a = torch.tensor([0.7, 0.2, 0.6], device=tensor.device, dtype=tensor.dtype) - b = torch.tensor([0.4, 0.2, 0.9], device=tensor.device, dtype=tensor.dtype) - return F.lfilter(tensor, a, b) - - self._assert_consistency(func, waveform) - - def test_sliding_window_cmn(self): - def func(tensor): - cmn_window = 600 - min_cmn_window = 100 - center = False - norm_vars = False - a = torch.tensor( - [ - [ - -1.915875792503357, - 1.147700309753418 - ], - [ - 1.8242558240890503, - 1.3869990110397339 - ] - ], - device=tensor.device, - dtype=tensor.dtype - ) - return F.sliding_window_cmn(a, cmn_window, min_cmn_window, center, norm_vars) - b = torch.tensor( - [ - [ - -1.8701, - -0.1196 - ], - [ - 1.8701, - 0.1196 - ] - ] - ) - self._assert_consistency(func, b) - - def test_contrast(self): - waveform = common_utils.get_whitenoise() - - def func(tensor): - enhancement_amount = 80. - return F.contrast(tensor, enhancement_amount) - - self._assert_consistency(func, waveform) - - def test_dcshift(self): - waveform = common_utils.get_whitenoise() - - def func(tensor): - shift = 0.5 - limiter_gain = 0.05 - return F.dcshift(tensor, shift, limiter_gain) - - self._assert_consistency(func, waveform) - - def test_overdrive(self): - waveform = common_utils.get_whitenoise() - - def func(tensor): - gain = 30. - colour = 50. - return F.overdrive(tensor, gain, colour) - - self._assert_consistency(func, waveform) - - def test_phaser(self): - waveform = common_utils.get_whitenoise(sample_rate=44100) - - def func(tensor): - gain_in = 0.5 - gain_out = 0.8 - delay_ms = 2.0 - decay = 0.4 - speed = 0.5 - sample_rate = 44100 - return F.phaser(tensor, sample_rate, gain_in, gain_out, delay_ms, decay, speed, sinusoidal=True) - - self._assert_consistency(func, waveform) - - def test_flanger(self): - torch.random.manual_seed(40) - waveform = torch.rand(2, 100) - 0.5 - - def func(tensor): - delay = 0.8 - depth = 0.88 - regen = 3.0 - width = 0.23 - speed = 1.3 - phase = 60. - sample_rate = 44100 - return F.flanger(tensor, sample_rate, delay, depth, regen, width, speed, - phase, modulation='sinusoidal', interpolation='linear') - - self._assert_consistency(func, waveform) - - def test_spectral_centroid(self): - - def func(tensor): - sample_rate = 44100 - n_fft = 400 - ws = 400 - hop = 200 - pad = 0 - window = torch.hann_window(ws, device=tensor.device, dtype=tensor.dtype) - return F.spectral_centroid(tensor, sample_rate, pad, window, n_fft, hop, ws) - - tensor = common_utils.get_whitenoise(sample_rate=44100) - self._assert_consistency(func, tensor) - - class Transforms(common_utils.TestBaseMixin): """Implements test for Transforms that are performed for different devices""" def _assert_consistency(self, transform, tensor): diff --git a/test/torchaudio_unittest/transforms_test.py b/test/torchaudio_unittest/transforms_test.py index 76628b1315..ab7b2ed981 100644 --- a/test/torchaudio_unittest/transforms_test.py +++ b/test/torchaudio_unittest/transforms_test.py @@ -1,5 +1,4 @@ import math -import unittest import torch import torchaudio diff --git a/third_party/CMakeLists.txt b/third_party/CMakeLists.txt index 1284affa88..3e1ab962fe 100644 --- a/third_party/CMakeLists.txt +++ b/third_party/CMakeLists.txt @@ -1,16 +1,28 @@ -cmake_minimum_required(VERSION 3.5) +set(TORCHAUDIO_THIRD_PARTIES "") -project(torchaudio_third_parties) - -option(BUILD_SOX "Build libsox statically") -option(BUILD_TRANSDUCER "Build transducer statically") - -set(CMAKE_POSITION_INDEPENDENT_CODE ON) +set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fvisibility=hidden") +################################################################################ +# sox +################################################################################ +add_library(libsox INTERFACE) if (BUILD_SOX) add_subdirectory(sox) + target_include_directories(libsox INTERFACE ${SOX_INCLUDE_DIR}) + target_link_libraries(libsox INTERFACE ${SOX_LIBRARIES}) +else() + # If not building and linking libsox statically, then we expect that + # sox library and header are found in search path + target_link_libraries(libsox INTERFACE -lsox) endif() +list(APPEND TORCHAUDIO_THIRD_PARTIES libsox) -if(BUILD_TRANSDUCER) +################################################################################ +# transducer +################################################################################ +if (BUILD_TRANSDUCER) add_subdirectory(transducer) + list(APPEND TORCHAUDIO_THIRD_PARTIES warprnnt) endif() + +set_property(GLOBAL PROPERTY TORCHAUDIO_THIRD_PARTIES "${TORCHAUDIO_THIRD_PARTIES}") diff --git a/third_party/sox/CMakeLists.txt b/third_party/sox/CMakeLists.txt index 930b84496a..840130f055 100644 --- a/third_party/sox/CMakeLists.txt +++ b/third_party/sox/CMakeLists.txt @@ -11,7 +11,7 @@ set(COMMON_ARGS --quiet --disable-shared --enable-static --prefix=${INSTALL_DIR} set(envs "PKG_CONFIG_PATH=${INSTALL_DIR}/lib/pkgconfig" "LDFLAGS=-L${INSTALL_DIR}/lib $ENV{LDFLAGS}" - "CPPFLAGS=-I${INSTALL_DIR}/include $ENV{CPPFLAGS}" + "CFLAGS=-I${INSTALL_DIR}/include -fvisibility=hidden $ENV{CFLAGS}" ) ExternalProject_Add(mad @@ -207,3 +207,7 @@ ExternalProject_Add(sox LOG_MERGED_STDOUTERR ON LOG_OUTPUT_ON_FAILURE ON ) + +add_dependencies(libsox sox) +set(SOX_INCLUDE_DIR ${INSTALL_DIR}/include PARENT_SCOPE) +set(SOX_LIBRARIES ${SOX_LIBRARIES} PARENT_SCOPE) diff --git a/third_party/transducer/CMakeLists.txt b/third_party/transducer/CMakeLists.txt index c35f0c8552..359af3e3e3 100755 --- a/third_party/transducer/CMakeLists.txt +++ b/third_party/transducer/CMakeLists.txt @@ -1,27 +1,3 @@ -ADD_DEFINITIONS(-DRNNT_DISABLE_OMP) - -IF(APPLE) - ADD_DEFINITIONS(-DAPPLE) - EXEC_PROGRAM(uname ARGS -v OUTPUT_VARIABLE DARWIN_VERSION) - STRING(REGEX MATCH "[0-9]+" DARWIN_VERSION ${DARWIN_VERSION}) - MESSAGE(STATUS "DARWIN_VERSION=${DARWIN_VERSION}") - - # for el capitain have to use rpath - IF(DARWIN_VERSION LESS 15) - SET(CMAKE_SKIP_RPATH TRUE) - ENDIF() - -ELSE() - # always skip for linux - SET(CMAKE_SKIP_RPATH TRUE) -ENDIF() - -ADD_LIBRARY(warprnnt STATIC submodule/src/rnnt_entrypoint.cpp) +add_library(warprnnt STATIC submodule/src/rnnt_entrypoint.cpp) +target_compile_definitions(warprnnt PRIVATE RNNT_DISABLE_OMP) target_include_directories(warprnnt PUBLIC submodule/include) -set_target_properties(warprnnt PROPERTIES PUBLIC_HEADER submodule/include/rnnt.h) - - -INSTALL( - TARGETS warprnnt - ARCHIVE DESTINATION "lib" - PUBLIC_HEADER DESTINATION "include") diff --git a/torchaudio/__init__.py b/torchaudio/__init__.py index cbb2ba3370..35f5fd41d5 100644 --- a/torchaudio/__init__.py +++ b/torchaudio/__init__.py @@ -1,5 +1,5 @@ -from . import extension -from torchaudio._internal import module_utils as _mod_utils +from . import extension # noqa: F401 +from torchaudio._internal import module_utils as _mod_utils # noqa: F401 from torchaudio import ( compliance, datasets, @@ -30,3 +30,24 @@ from .version import __version__, git_version # noqa: F401 except ImportError: pass + +__all__ = [ + 'compliance', + 'datasets', + 'functional', + 'kaldi_io', + 'utils', + 'sox_effects', + 'transforms', + 'list_audio_backends', + 'get_audio_backend', + 'set_audio_backend', + 'save_encinfo', + 'sox_signalinfo_t', + 'sox_encodinginfo_t', + 'get_sox_option_t', + 'get_sox_encoding_t', + 'get_sox_bool', + 'SignalInfo', + 'EncodingInfo', +] diff --git a/torchaudio/backend/__init__.py b/torchaudio/backend/__init__.py index 0812c09cf4..361935229f 100644 --- a/torchaudio/backend/__init__.py +++ b/torchaudio/backend/__init__.py @@ -1,3 +1,4 @@ +# flake8: noqa from . import utils from .utils import ( list_audio_backends, diff --git a/torchaudio/compliance/__init__.py b/torchaudio/compliance/__init__.py index ba354c371e..795065dc8d 100644 --- a/torchaudio/compliance/__init__.py +++ b/torchaudio/compliance/__init__.py @@ -1 +1,5 @@ from . import kaldi + +__all__ = [ + 'kaldi', +] diff --git a/torchaudio/csrc/CMakeLists.txt b/torchaudio/csrc/CMakeLists.txt new file mode 100644 index 0000000000..f9c3a4d08f --- /dev/null +++ b/torchaudio/csrc/CMakeLists.txt @@ -0,0 +1,91 @@ +get_property(TORCHAUDIO_THIRD_PARTIES GLOBAL PROPERTY TORCHAUDIO_THIRD_PARTIES) + +################################################################################ +# Stuff common to libtorchaudio and _torchaudio.so +################################################################################ +set( + LIBTORCHAUDIO_SOURCES + sox/io.cpp + sox/utils.cpp + sox/effects.cpp + sox/effects_chain.cpp + ) + +if(BUILD_TRANSDUCER) + list(APPEND LIBTORCHAUDIO_SOURCES transducer.cpp) +endif() + +################################################################################ +# libtorchaudio.so +################################################################################ +if(BUILD_LIBTORCHAUDIO) + add_library( + libtorchaudio + SHARED + ${LIBTORCHAUDIO_SOURCES} + ) + set_target_properties(libtorchaudio PROPERTIES PREFIX "") + + target_include_directories( + libtorchaudio + PUBLIC + ${PROJECT_SOURCE_DIR} + ) + + target_link_libraries( + libtorchaudio + ${TORCHAUDIO_THIRD_PARTIES} + ) + + install( + TARGETS + libtorchaudio + LIBRARY DESTINATION lib + ) + + set(TORCHAUDIO_LIBRARY -Wl,--no-as-needed libtorchaudio -Wl,--as-needed CACHE INTERNAL "") +endif() + +################################################################################ +# _torchaudio.so +################################################################################ +if (BUILD_TORCHAUDIO_PYTHON_EXTENSION) + add_library( + _torchaudio + SHARED + pybind.cpp + sox/legacy.cpp + ${LIBTORCHAUDIO_SOURCES} + ) + + set_target_properties(_torchaudio PROPERTIES PREFIX "") + + if (APPLE) + # https://github.com/facebookarchive/caffe2/issues/854#issuecomment-364538485 + # https://github.com/pytorch/pytorch/commit/73f6715f4725a0723d8171d3131e09ac7abf0666 + set_target_properties(_torchaudio PROPERTIES LINK_FLAGS "-undefined dynamic_lookup") + endif() + + target_compile_definitions( + _torchaudio PRIVATE TORCH_API_INCLUDE_EXTENSION_H + ) + + target_include_directories( + _torchaudio + PRIVATE + ${PROJECT_SOURCE_DIR} + ${Python_INCLUDE_DIR} + ) + + # See https://github.com/pytorch/pytorch/issues/38122 + find_library(TORCH_PYTHON_LIBRARY torch_python PATHS "${TORCH_INSTALL_PREFIX}/lib") + + target_link_libraries( + _torchaudio + ${TORCH_LIBRARIES} + ${TORCH_PYTHON_LIBRARY} + ${TORCHAUDIO_THIRD_PARTIES} + ) + + install(TARGETS _torchaudio LIBRARY DESTINATION ${CMAKE_INSTALL_PREFIX}) +endif() diff --git a/torchaudio/csrc/sox/effects_chain.cpp b/torchaudio/csrc/sox/effects_chain.cpp index cbe78684f7..b98010f67b 100644 --- a/torchaudio/csrc/sox/effects_chain.cpp +++ b/torchaudio/csrc/sox/effects_chain.cpp @@ -353,7 +353,11 @@ int fileobj_input_drain(sox_effect_t* effp, sox_sample_t* obuf, size_t* osamp) { // in sync and `tell_off` has seemingly uninitialized value, which // leads num_remain to be negative and cause segmentation fault // in `memmove`. - const auto num_consumed = ftell((FILE*)sf->fp); + const auto tell = ftell((FILE*)sf->fp); + if (tell < 0) { + throw std::runtime_error("Internal Error: ftell failed."); + } + const auto num_consumed = static_cast(tell); if (num_consumed > priv->buffer_size) { throw std::runtime_error("Internal Error: buffer overrun."); } @@ -361,7 +365,7 @@ int fileobj_input_drain(sox_effect_t* effp, sox_sample_t* obuf, size_t* osamp) { const auto num_remain = priv->buffer_size - num_consumed; // 1.1. Fetch the data to see if there is data to fill the buffer - uint64_t num_refill = 0; + size_t num_refill = 0; std::string chunk(num_consumed, '\0'); if (num_consumed && !priv->eof_reached) { num_refill = read_fileobj( diff --git a/torchaudio/datasets/__init__.py b/torchaudio/datasets/__init__.py index 5e5b9c1118..a83bf33c82 100644 --- a/torchaudio/datasets/__init__.py +++ b/torchaudio/datasets/__init__.py @@ -10,7 +10,7 @@ from .libritts import LIBRITTS from .tedlium import TEDLIUM -__all__ = ( +__all__ = [ "COMMONVOICE", "LIBRISPEECH", "SPEECHCOMMANDS", @@ -24,4 +24,4 @@ "diskcache_iterator", "bg_iterator", "TEDLIUM", -) +] diff --git a/torchaudio/datasets/gtzan.py b/torchaudio/datasets/gtzan.py index 4c91894be1..6c0b6246f3 100644 --- a/torchaudio/datasets/gtzan.py +++ b/torchaudio/datasets/gtzan.py @@ -1,7 +1,6 @@ import os -import warnings from pathlib import Path -from typing import Any, Tuple, Optional, Union +from typing import Tuple, Optional, Union import torchaudio from torch import Tensor diff --git a/torchaudio/datasets/ljspeech.py b/torchaudio/datasets/ljspeech.py index 99058dd83e..1a519242c3 100644 --- a/torchaudio/datasets/ljspeech.py +++ b/torchaudio/datasets/ljspeech.py @@ -1,6 +1,6 @@ import os import csv -from typing import List, Tuple, Union +from typing import Tuple, Union from pathlib import Path import torchaudio diff --git a/torchaudio/extension/extension.py b/torchaudio/extension/extension.py index b01ba13e39..5875f41023 100644 --- a/torchaudio/extension/extension.py +++ b/torchaudio/extension/extension.py @@ -1,6 +1,5 @@ import warnings import importlib -from collections import namedtuple import torch from torchaudio._internal import module_utils as _mod_utils diff --git a/torchaudio/functional/__init__.py b/torchaudio/functional/__init__.py index 688708296b..d59400e82e 100644 --- a/torchaudio/functional/__init__.py +++ b/torchaudio/functional/__init__.py @@ -41,3 +41,45 @@ treble_biquad, vad, ) + +__all__ = [ + 'amplitude_to_DB', + 'angle', + 'complex_norm', + 'compute_deltas', + 'create_dct', + 'create_fb_matrix', + 'DB_to_amplitude', + 'detect_pitch_frequency', + 'griffinlim', + 'magphase', + 'mask_along_axis', + 'mask_along_axis_iid', + 'mu_law_encoding', + 'mu_law_decoding', + 'phase_vocoder', + 'sliding_window_cmn', + 'spectrogram', + 'spectral_centroid', + 'allpass_biquad', + 'band_biquad', + 'bandpass_biquad', + 'bandreject_biquad', + 'bass_biquad', + 'biquad', + 'contrast', + 'dither', + 'dcshift', + 'deemph_biquad', + 'equalizer_biquad', + 'flanger', + 'gain', + 'highpass_biquad', + 'lfilter', + 'lowpass_biquad', + 'overdrive', + 'phaser', + 'riaa_biquad', + 'treble_biquad', + 'vad', +] diff --git a/torchaudio/functional/functional.py b/torchaudio/functional/functional.py index 73941946ec..4dde324a31 100644 --- a/torchaudio/functional/functional.py +++ b/torchaudio/functional/functional.py @@ -237,14 +237,16 @@ def amplitude_to_DB( db_multiplier: float, top_db: Optional[float] = None ) -> Tensor: - r"""Turn a tensor from the power/amplitude scale to the decibel scale. + r"""Turn a spectrogram from the power/amplitude scale to the decibel scale. - This output depends on the maximum value in the input tensor, and so - may return different values for an audio clip split into snippets vs. a - full clip. + The output of each tensor in a batch depends on the maximum value of that tensor, + and so may return different values for an audio clip split into snippets vs. a full clip. Args: - x (Tensor): Input tensor before being converted to decibel scale + + x (Tensor): Input spectrogram(s) before being converted to decibel scale. Input should take + the form `(..., freq, time)`. Batched inputs should include a channel dimension and + have the form `(batch, channel, freq, time)`. multiplier (float): Use 10. for power and 20. for amplitude amin (float): Number to clamp ``x`` db_multiplier (float): Log10(max(reference value and amin)) @@ -258,7 +260,15 @@ def amplitude_to_DB( x_db -= multiplier * db_multiplier if top_db is not None: - x_db = x_db.clamp(min=x_db.max().item() - top_db) + # Expand batch + shape = x_db.size() + packed_channels = shape[-3] if x_db.dim() > 2 else 1 + x_db = x_db.reshape(-1, packed_channels, shape[-2], shape[-1]) + + x_db = torch.max(x_db, (x_db.amax(dim=(-3, -2, -1)) - top_db).view(-1, 1, 1, 1)) + + # Repack batch + x_db = x_db.reshape(shape) return x_db diff --git a/torchaudio/models/__init__.py b/torchaudio/models/__init__.py index 55498fd7f6..5b134345af 100644 --- a/torchaudio/models/__init__.py +++ b/torchaudio/models/__init__.py @@ -1,3 +1,9 @@ from .wav2letter import Wav2Letter from .wavernn import WaveRNN from .conv_tasnet import ConvTasNet + +__all__ = [ + 'Wav2Letter', + 'WaveRNN', + 'ConvTasNet', +] diff --git a/torchaudio/models/wav2letter.py b/torchaudio/models/wav2letter.py index acd4dfe4b3..20a665a784 100644 --- a/torchaudio/models/wav2letter.py +++ b/torchaudio/models/wav2letter.py @@ -1,7 +1,9 @@ from torch import Tensor from torch import nn -__all__ = ["Wav2Letter"] +__all__ = [ + "Wav2Letter", +] class Wav2Letter(nn.Module): diff --git a/torchaudio/models/wavernn.py b/torchaudio/models/wavernn.py index 8fbd111a72..eedbd3c589 100644 --- a/torchaudio/models/wavernn.py +++ b/torchaudio/models/wavernn.py @@ -4,7 +4,13 @@ from torch import Tensor from torch import nn -__all__ = ["ResBlock", "MelResNet", "Stretch2d", "UpsampleNetwork", "WaveRNN"] +__all__ = [ + "ResBlock", + "MelResNet", + "Stretch2d", + "UpsampleNetwork", + "WaveRNN", +] class ResBlock(nn.Module): diff --git a/torchaudio/prototype/transducer.py b/torchaudio/prototype/transducer.py index d08ab6ea17..843cf5f9a4 100644 --- a/torchaudio/prototype/transducer.py +++ b/torchaudio/prototype/transducer.py @@ -5,7 +5,10 @@ module_utils as _mod_utils, ) -__all__ = ["rnnt_loss", "RNNTLoss"] +__all__ = [ + "rnnt_loss", + "RNNTLoss", +] class _RNNT(Function): diff --git a/torchaudio/sox_effects/__init__.py b/torchaudio/sox_effects/__init__.py index 5baf406b10..b3e2708ad1 100644 --- a/torchaudio/sox_effects/__init__.py +++ b/torchaudio/sox_effects/__init__.py @@ -12,3 +12,11 @@ import atexit init_sox_effects() atexit.register(shutdown_sox_effects) + +__all__ = [ + 'init_sox_effects', + 'shutdown_sox_effects', + 'effect_names', + 'apply_effects_tensor', + 'apply_effects_file', +] diff --git a/torchaudio/sox_effects/sox_effects.py b/torchaudio/sox_effects/sox_effects.py index 4d1d0234d9..e183932788 100644 --- a/torchaudio/sox_effects/sox_effects.py +++ b/torchaudio/sox_effects/sox_effects.py @@ -1,5 +1,4 @@ import os -from pathlib import Path from typing import List, Tuple, Optional import torch diff --git a/torchaudio/transforms.py b/torchaudio/transforms.py index 7d7903b752..af89d5b250 100644 --- a/torchaudio/transforms.py +++ b/torchaudio/transforms.py @@ -2,7 +2,6 @@ import math from typing import Callable, Optional -from warnings import warn import torch from torch import Tensor @@ -541,24 +540,16 @@ def forward(self, waveform: Tensor) -> Tensor: Returns: Tensor: specgram_mel_db of size (..., ``n_mfcc``, time). """ - - # pack batch - shape = waveform.size() - waveform = waveform.reshape(-1, shape[-1]) - mel_specgram = self.MelSpectrogram(waveform) if self.log_mels: log_offset = 1e-6 mel_specgram = torch.log(mel_specgram + log_offset) else: mel_specgram = self.amplitude_to_DB(mel_specgram) - # (channel, n_mels, time).tranpose(...) dot (n_mels, n_mfcc) - # -> (channel, time, n_mfcc).tranpose(...) - mfcc = torch.matmul(mel_specgram.transpose(1, 2), self.dct_mat).transpose(1, 2) - - # unpack batch - mfcc = mfcc.reshape(shape[:-1] + mfcc.shape[-2:]) + # (..., channel, n_mels, time).tranpose(...) dot (n_mels, n_mfcc) + # -> (..., channel, time, n_mfcc).tranpose(...) + mfcc = torch.matmul(mel_specgram.transpose(-2, -1), self.dct_mat).transpose(-2, -1) return mfcc From a0446251ef7c2806fe36c601631fcae54667318d Mon Sep 17 00:00:00 2001 From: Scott Wolchok Date: Wed, 17 Feb 2021 10:33:13 -0800 Subject: [PATCH 30/73] Remove reference_cast in make_boxed_from_unboxed_functor (#51319) Summary: Pull Request resolved: https://github.com/pytorch/pytorch/pull/51319 We were going out of our way to accommodate `IValue::to` returning a copy of the inner Tensor. `IValue::toTensor` is capable of returning a reference without copying, so if we use it directly, we can allow kernels that want to take `Tensor &` to do so! As a bonus, we get reduced build times. ghstack-source-id: 121378961 Reviewed By: bhosmer Differential Revision: D26138549 fbshipit-source-id: b0f830527da360c542c815bef2f7e1692615b32a --- torchaudio/csrc/sox/effects.cpp | 6 +++--- torchaudio/csrc/sox/effects.h | 6 +++--- torchaudio/csrc/sox/io.cpp | 16 ++++++++-------- torchaudio/csrc/sox/io.h | 12 ++++++------ 4 files changed, 20 insertions(+), 20 deletions(-) diff --git a/torchaudio/csrc/sox/effects.cpp b/torchaudio/csrc/sox/effects.cpp index eb4bf24549..d2d2a0f5ad 100644 --- a/torchaudio/csrc/sox/effects.cpp +++ b/torchaudio/csrc/sox/effects.cpp @@ -91,9 +91,9 @@ std::tuple apply_effects_tensor( std::tuple apply_effects_file( const std::string path, std::vector> effects, - c10::optional& normalize, - c10::optional& channels_first, - c10::optional& format) { + c10::optional normalize, + c10::optional channels_first, + const c10::optional& format) { // Open input file SoxFormat sf(sox_open_read( path.c_str(), diff --git a/torchaudio/csrc/sox/effects.h b/torchaudio/csrc/sox/effects.h index 8ce9757824..efec06971c 100644 --- a/torchaudio/csrc/sox/effects.h +++ b/torchaudio/csrc/sox/effects.h @@ -24,9 +24,9 @@ std::tuple apply_effects_tensor( std::tuple apply_effects_file( const std::string path, std::vector> effects, - c10::optional& normalize, - c10::optional& channels_first, - c10::optional& format); + c10::optional normalize, + c10::optional channels_first, + const c10::optional& format); #ifdef TORCH_API_INCLUDE_EXTENSION_H diff --git a/torchaudio/csrc/sox/io.cpp b/torchaudio/csrc/sox/io.cpp index ac10911507..90532dd3ad 100644 --- a/torchaudio/csrc/sox/io.cpp +++ b/torchaudio/csrc/sox/io.cpp @@ -47,7 +47,7 @@ std::string get_encoding(sox_encoding_t encoding) { std::tuple get_info_file( const std::string& path, - c10::optional& format) { + const c10::optional& format) { SoxFormat sf(sox_open_read( path.c_str(), /*signal=*/nullptr, @@ -69,8 +69,8 @@ std::tuple get_info_file( namespace { std::vector> get_effects( - c10::optional& frame_offset, - c10::optional& num_frames) { + const c10::optional& frame_offset, + const c10::optional& num_frames) { const auto offset = frame_offset.value_or(0); if (offset < 0) { throw std::runtime_error( @@ -101,11 +101,11 @@ std::vector> get_effects( std::tuple load_audio_file( const std::string& path, - c10::optional& frame_offset, - c10::optional& num_frames, - c10::optional& normalize, - c10::optional& channels_first, - c10::optional& format) { + const c10::optional& frame_offset, + const c10::optional& num_frames, + c10::optional normalize, + c10::optional channels_first, + const c10::optional& format) { auto effects = get_effects(frame_offset, num_frames); return torchaudio::sox_effects::apply_effects_file( path, effects, normalize, channels_first, format); diff --git a/torchaudio/csrc/sox/io.h b/torchaudio/csrc/sox/io.h index 6129fac1b7..cd203e9c5c 100644 --- a/torchaudio/csrc/sox/io.h +++ b/torchaudio/csrc/sox/io.h @@ -13,15 +13,15 @@ namespace sox_io { std::tuple get_info_file( const std::string& path, - c10::optional& format); + const c10::optional& format); std::tuple load_audio_file( const std::string& path, - c10::optional& frame_offset, - c10::optional& num_frames, - c10::optional& normalize, - c10::optional& channels_first, - c10::optional& format); + const c10::optional& frame_offset, + const c10::optional& num_frames, + c10::optional normalize, + c10::optional channels_first, + const c10::optional& format); void save_audio_file( const std::string& path, From d6321ae070da4155712a156e232c7e9443c1e570 Mon Sep 17 00:00:00 2001 From: cpuhrsch Date: Fri, 2 Apr 2021 13:34:42 -0400 Subject: [PATCH 31/73] Add missing file to faciliate fixup patch (#1417) --- .circleci/unittest/windows/scripts/environment.yml | 0 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 .circleci/unittest/windows/scripts/environment.yml diff --git a/.circleci/unittest/windows/scripts/environment.yml b/.circleci/unittest/windows/scripts/environment.yml new file mode 100644 index 0000000000..e69de29bb2 From ece130122fb7e2a34d79bb59addb301aef53e324 Mon Sep 17 00:00:00 2001 From: cpuhrsch Date: Fri, 2 Apr 2021 13:44:12 -0400 Subject: [PATCH 32/73] Sync environment.yml such that patch applies (#1418) --- .../unittest/windows/scripts/environment.yml | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/.circleci/unittest/windows/scripts/environment.yml b/.circleci/unittest/windows/scripts/environment.yml index e69de29bb2..4a0b71d653 100644 --- a/.circleci/unittest/windows/scripts/environment.yml +++ b/.circleci/unittest/windows/scripts/environment.yml @@ -0,0 +1,18 @@ +channels: + - conda-forge + - defaults +dependencies: + - flake8 + - numpy + - pytest + - pytest-cov + - codecov + - pip + - pip: + - scipy == 1.4.1 + - kaldi-io + - PySoundFile + - librosa >= 0.8.0 + - future + - parameterized + - dataclasses From 76167470d0eee470020908cc42549c5faf7cd1ee Mon Sep 17 00:00:00 2001 From: Moto Hira Date: Thu, 18 Mar 2021 11:38:04 -0700 Subject: [PATCH 33/73] Import #1396 dd76e9d Summary: Import #1396 dd76e9d Reviewed By: vincentqb Differential Revision: D26772272 fbshipit-source-id: 5fb10b8e4bfe955372eaf588d33ab96e1a83ef8d --- .circleci/config.yml | 269 ++++++- .circleci/config.yml.in | 45 +- .circleci/regenerate.py | 16 +- .circleci/unittest/linux/scripts/install.sh | 23 +- .../linux/scripts/run_style_checks.sh | 4 +- .../unittest/windows/scripts/environment.yml | 4 +- .circleci/unittest/windows/scripts/install.sh | 19 +- .../unittest/windows/scripts/setup_env.sh | 3 + .gitmodules | 4 + CMakeLists.txt | 1 + CONTRIBUTING.md | 30 +- README.md | 75 +- build_tools/setup_helpers/extension.py | 21 +- docs/Makefile | 2 +- docs/source/_templates/layout.html | 8 + docs/source/backend.rst | 127 +-- docs/source/conf.py | 10 +- docs/source/functional.rst | 149 ++-- docs/source/torchaudio.rst | 4 - docs/source/transforms.rst | 7 + examples/interactive_asr/vad.py | 4 +- examples/libtorchaudio/.gitignore | 3 + examples/libtorchaudio/CMakeLists.txt | 20 + examples/libtorchaudio/README.md | 11 + .../libtorchaudio/create_jittable_pipeline.py | 83 ++ examples/libtorchaudio/data/README.md | 5 + examples/libtorchaudio/data/input.wav | Bin 0 -> 108844 bytes examples/libtorchaudio/data/rir.wav | Bin 0 -> 9338 bytes examples/libtorchaudio/main.cpp | 21 + examples/libtorchaudio/run.sh | 24 + .../pipeline_wav2letter/languagemodels.py | 2 +- .../utils/dataset/wsj0mix.py | 2 +- packaging/build_conda.sh | 3 +- packaging/build_wheel.sh | 4 +- packaging/pkg_helpers.bash | 20 +- packaging/torchaudio/meta.yaml | 2 + packaging/vc_env_helper.bat | 39 + packaging/vs2019/activate.bat | 44 + packaging/vs2019/conda_build_config.yaml | 24 + packaging/vs2019/install_activate.bat | 30 + packaging/vs2019/install_runtime.bat | 49 ++ packaging/vs2019/meta.yaml | 24 + setup.cfg | 2 + setup.py | 3 +- test/torchaudio_unittest/README.md | 18 +- ..._args.json => kaldi_test_fbank_args.jsonl} | 0 ...c_args.json => kaldi_test_mfcc_args.jsonl} | 0 .../assets/kaldi_test_pitch_args.jsonl | 5 + ...json => kaldi_test_spectrogram_args.jsonl} | 0 ...t_args.json => sox_effect_test_args.jsonl} | 0 .../backend/legacy_test.py | 290 ------- .../backend/soundfile/common.py | 23 + .../backend/soundfile/info_test.py | 12 +- .../backend/soundfile/load_test.py | 2 +- .../backend/soundfile/save_test.py | 81 +- .../backend/sox_io/common.py | 12 + .../backend/sox_io/info_test.py | 45 +- .../backend/sox_io/load_test.py | 226 ++---- .../backend/sox_io/roundtrip_test.py | 8 +- .../backend/sox_io/save_test.py | 755 ++++++++---------- .../backend/sox_io/smoke_test.py | 10 +- .../backend/sox_io/torchscript_test.py | 26 +- .../torchaudio_unittest/backend/utils_test.py | 23 +- .../common_utils/__init__.py | 9 +- .../common_utils/backend_utils.py | 4 +- .../common_utils/case_utils.py | 16 +- .../common_utils/data_utils.py | 4 +- .../common_utils/kaldi_utils.py | 38 + .../common_utils/parameterized_utils.py | 19 +- .../common_utils/sox_utils.py | 12 +- .../compliance/generate_fbank_data.py | 3 +- .../compliance_kaldi_test.py | 20 +- .../datasets/tedlium_test.py | 9 +- .../functional/autograd_cpu_test.py | 8 + .../functional/autograd_cuda_test.py | 9 + .../functional/autograd_impl.py | 40 + .../functional/batch_consistency_test.py | 224 ++++++ .../functional/functional_cpu_test.py | 53 ++ .../functional/functional_cuda_test.py | 5 + .../functional/functional_impl.py | 37 + .../kaldi_compatibility_cpu_test.py | 19 + .../kaldi_compatibility_cuda_test.py | 16 + .../kaldi_compatibility_test_impl.py | 60 ++ .../functional/librosa_compatibility_test.py | 155 ++++ .../sox_compatibility_test.py | 30 - .../torchscript_consistency_impl.py | 30 +- .../kaldi_compatibility_impl.py | 103 --- .../librosa_compatibility_test.py | 366 --------- .../sox_effect/dataset_test.py | 6 +- .../sox_effect/smoke_test.py | 10 +- .../sox_effect/sox_effect_test.py | 20 +- .../sox_effect/torchscript_test.py | 8 +- test/torchaudio_unittest/transducer_test.py | 15 +- .../transforms/__init__.py | 0 .../batch_consistency_test.py | 166 ---- .../kaldi_compatibility_cpu_test.py | 0 .../kaldi_compatibility_cuda_test.py | 0 .../transforms/kaldi_compatibility_impl.py | 55 ++ .../transforms/librosa_compatibility_test.py | 245 ++++++ .../transforms/sox_compatibility_test.py | 53 ++ .../torchscript_consistency_cpu_test.py | 0 .../torchscript_consistency_cuda_test.py | 0 .../torchscript_consistency_impl.py | 0 .../{ => transforms}/transforms_test.py | 0 .../utils/sox_utils_test.py | 4 +- third_party/CMakeLists.txt | 14 +- third_party/kaldi/CMakeLists.txt | 30 + third_party/kaldi/README.md | 6 + third_party/kaldi/kaldi.patch | 76 ++ third_party/kaldi/src/matrix/kaldi-matrix.cc | 39 + third_party/kaldi/src/matrix/kaldi-matrix.h | 178 +++++ third_party/kaldi/src/matrix/kaldi-vector.cc | 42 + third_party/kaldi/src/matrix/kaldi-vector.h | 313 ++++++++ third_party/sox/CMakeLists.txt | 1 + third_party/sox/patch/sox.patch | 16 + torchaudio/__init__.py | 10 - torchaudio/_internal/module_utils.py | 40 +- torchaudio/backend/__init__.py | 12 - torchaudio/backend/_soundfile_backend.py | 316 -------- torchaudio/backend/common.py | 202 +---- torchaudio/backend/no_backend.py | 17 +- torchaudio/backend/soundfile_backend.py | 495 +++++++++--- torchaudio/backend/sox_backend.py | 294 ------- torchaudio/backend/sox_io_backend.py | 256 +++--- torchaudio/backend/utils.py | 40 +- torchaudio/compliance/kaldi.py | 2 +- torchaudio/csrc/CMakeLists.txt | 48 +- torchaudio/csrc/kaldi.cpp | 93 +++ torchaudio/csrc/lfilter.cpp | 268 +++++++ torchaudio/csrc/overdrive.cpp | 52 ++ torchaudio/csrc/pybind.cpp | 103 +-- torchaudio/csrc/sox/effects.cpp | 8 +- torchaudio/csrc/sox/effects.h | 6 +- torchaudio/csrc/sox/effects_chain.cpp | 45 +- torchaudio/csrc/sox/io.cpp | 115 ++- torchaudio/csrc/sox/io.h | 20 +- torchaudio/csrc/sox/legacy.cpp | 170 ---- torchaudio/csrc/sox/legacy.h | 40 - torchaudio/csrc/sox/types.cpp | 139 ++++ torchaudio/csrc/sox/types.h | 60 ++ torchaudio/csrc/sox/utils.cpp | 404 +++++++--- torchaudio/csrc/sox/utils.h | 15 +- torchaudio/csrc/transducer.cpp | 29 + torchaudio/csrc/utils.cpp | 30 + torchaudio/datasets/speechcommands.py | 13 +- torchaudio/datasets/tedlium.py | 6 +- torchaudio/extension/extension.py | 1 + torchaudio/functional/__init__.py | 4 + torchaudio/functional/filtering.py | 167 ++-- torchaudio/functional/functional.py | 284 ++++++- torchaudio/kaldi_io.py | 2 +- torchaudio/prototype/transducer.py | 43 - torchaudio/sox_effects/__init__.py | 2 +- torchaudio/sox_effects/sox_effects.py | 20 +- torchaudio/transforms.py | 43 +- torchaudio/utils/__init__.py | 3 +- torchaudio/utils/sox_utils.py | 19 +- 157 files changed, 5521 insertions(+), 3777 deletions(-) create mode 100644 docs/source/_templates/layout.html create mode 100644 examples/libtorchaudio/.gitignore create mode 100644 examples/libtorchaudio/CMakeLists.txt create mode 100644 examples/libtorchaudio/README.md create mode 100755 examples/libtorchaudio/create_jittable_pipeline.py create mode 100644 examples/libtorchaudio/data/README.md create mode 100644 examples/libtorchaudio/data/input.wav create mode 100644 examples/libtorchaudio/data/rir.wav create mode 100644 examples/libtorchaudio/main.cpp create mode 100755 examples/libtorchaudio/run.sh create mode 100644 packaging/vc_env_helper.bat create mode 100644 packaging/vs2019/activate.bat create mode 100644 packaging/vs2019/conda_build_config.yaml create mode 100644 packaging/vs2019/install_activate.bat create mode 100644 packaging/vs2019/install_runtime.bat create mode 100644 packaging/vs2019/meta.yaml create mode 100644 setup.cfg rename test/torchaudio_unittest/assets/{kaldi_test_fbank_args.json => kaldi_test_fbank_args.jsonl} (100%) rename test/torchaudio_unittest/assets/{kaldi_test_mfcc_args.json => kaldi_test_mfcc_args.jsonl} (100%) create mode 100644 test/torchaudio_unittest/assets/kaldi_test_pitch_args.jsonl rename test/torchaudio_unittest/assets/{kaldi_test_spectrogram_args.json => kaldi_test_spectrogram_args.jsonl} (100%) rename test/torchaudio_unittest/assets/{sox_effect_test_args.json => sox_effect_test_args.jsonl} (100%) delete mode 100644 test/torchaudio_unittest/backend/legacy_test.py create mode 100644 test/torchaudio_unittest/common_utils/kaldi_utils.py create mode 100644 test/torchaudio_unittest/functional/autograd_cpu_test.py create mode 100644 test/torchaudio_unittest/functional/autograd_cuda_test.py create mode 100644 test/torchaudio_unittest/functional/autograd_impl.py create mode 100644 test/torchaudio_unittest/functional/batch_consistency_test.py create mode 100644 test/torchaudio_unittest/functional/kaldi_compatibility_cpu_test.py create mode 100644 test/torchaudio_unittest/functional/kaldi_compatibility_cuda_test.py create mode 100644 test/torchaudio_unittest/functional/kaldi_compatibility_test_impl.py create mode 100644 test/torchaudio_unittest/functional/librosa_compatibility_test.py rename test/torchaudio_unittest/{ => functional}/sox_compatibility_test.py (90%) delete mode 100644 test/torchaudio_unittest/kaldi_compatibility_impl.py delete mode 100644 test/torchaudio_unittest/librosa_compatibility_test.py create mode 100644 test/torchaudio_unittest/transforms/__init__.py rename test/torchaudio_unittest/{ => transforms}/batch_consistency_test.py (54%) rename test/torchaudio_unittest/{ => transforms}/kaldi_compatibility_cpu_test.py (100%) rename test/torchaudio_unittest/{ => transforms}/kaldi_compatibility_cuda_test.py (100%) create mode 100644 test/torchaudio_unittest/transforms/kaldi_compatibility_impl.py create mode 100644 test/torchaudio_unittest/transforms/librosa_compatibility_test.py create mode 100644 test/torchaudio_unittest/transforms/sox_compatibility_test.py rename test/torchaudio_unittest/{ => transforms}/torchscript_consistency_cpu_test.py (100%) rename test/torchaudio_unittest/{ => transforms}/torchscript_consistency_cuda_test.py (100%) rename test/torchaudio_unittest/{ => transforms}/torchscript_consistency_impl.py (100%) rename test/torchaudio_unittest/{ => transforms}/transforms_test.py (100%) create mode 100644 third_party/kaldi/CMakeLists.txt create mode 100644 third_party/kaldi/README.md create mode 100644 third_party/kaldi/kaldi.patch create mode 100644 third_party/kaldi/src/matrix/kaldi-matrix.cc create mode 100644 third_party/kaldi/src/matrix/kaldi-matrix.h create mode 100644 third_party/kaldi/src/matrix/kaldi-vector.cc create mode 100644 third_party/kaldi/src/matrix/kaldi-vector.h create mode 100644 third_party/sox/patch/sox.patch delete mode 100644 torchaudio/backend/_soundfile_backend.py delete mode 100644 torchaudio/backend/sox_backend.py create mode 100644 torchaudio/csrc/kaldi.cpp create mode 100644 torchaudio/csrc/lfilter.cpp create mode 100644 torchaudio/csrc/overdrive.cpp delete mode 100644 torchaudio/csrc/sox/legacy.cpp delete mode 100644 torchaudio/csrc/sox/legacy.h create mode 100644 torchaudio/csrc/sox/types.cpp create mode 100644 torchaudio/csrc/sox/types.h create mode 100644 torchaudio/csrc/utils.cpp diff --git a/.circleci/config.yml b/.circleci/config.yml index 1cae2f6c78..3bf72c3a6d 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -45,6 +45,16 @@ commands: name: Install pkg-config command: HOMEBREW_NO_AUTO_UPDATE=1 brew install pkg-config wget # Disable brew auto update which is very slow + load_conda_channel_flags: + description: "Determines whether we need extra conda channels" + steps: + - run: + name: Adding CONDA_CHANNEL_FLAGS to BASH_ENV + command: | + CONDA_CHANNEL_FLAGS="" + if [[ "${PYTHON_VERSION}" = *3.9* ]]; then + echo "export CONDA_CHANNEL_FLAGS=-c=conda-forge" >> ${BASH_ENV} + fi binary_common: &binary_common parameters: @@ -117,7 +127,7 @@ jobs: binary_linux_wheel: <<: *binary_common docker: - - image: "pytorch/manylinux-cuda100" + - image: "pytorch/manylinux-cuda102" resource_class: 2xlarge+ steps: - checkout @@ -138,6 +148,7 @@ jobs: resource_class: 2xlarge+ steps: - checkout + - load_conda_channel_flags - attach_workspace: at: third_party - run: packaging/build_conda.sh @@ -155,6 +166,7 @@ jobs: steps: - checkout - install_build_tools_macos + - load_conda_channel_flags - attach_workspace: at: third_party - run: @@ -180,6 +192,7 @@ jobs: steps: - checkout - install_build_tools_macos + - load_conda_channel_flags - attach_workspace: at: third_party - run: @@ -202,6 +215,7 @@ jobs: name: windows-cpu steps: - checkout + - load_conda_channel_flags - run: name: build command: | @@ -221,6 +235,7 @@ jobs: name: windows-cpu steps: - checkout + - load_conda_channel_flags - run: name: build command: | @@ -278,6 +293,7 @@ jobs: - attach_workspace: at: ~/workspace - designate_upload_channel + - load_conda_channel_flags - run: name: install binaries command: | @@ -297,6 +313,7 @@ jobs: - attach_workspace: at: ~/workspace - designate_upload_channel + - load_conda_channel_flags - run: name: install binaries command: | @@ -317,6 +334,7 @@ jobs: - attach_workspace: at: ~/workspace - designate_upload_channel + - load_conda_channel_flags - run: name: install binaries command: | @@ -342,6 +360,7 @@ jobs: - attach_workspace: at: ~/workspace - designate_upload_channel + - load_conda_channel_flags - run: name: install binaries command: | @@ -395,6 +414,7 @@ jobs: - attach_workspace: at: third_party - designate_upload_channel + - load_conda_channel_flags - run: name: Setup command: .circleci/unittest/linux/scripts/setup_env.sh @@ -423,6 +443,7 @@ jobs: - attach_workspace: at: third_party - designate_upload_channel + - load_conda_channel_flags - run: name: Pull Docker image command: docker pull --quiet "${image_name}" @@ -431,7 +452,7 @@ jobs: command: docker run -t --gpus all -e PYTHON_VERSION -v $PWD:$PWD -w $PWD "${image_name}" .circleci/unittest/linux/scripts/setup_env.sh - run: name: Install torchaudio - command: docker run -t --gpus all -e UPLOAD_CHANNEL -v $PWD:$PWD -w $PWD "${image_name}" .circleci/unittest/linux/scripts/install.sh + command: docker run -t --gpus all -e UPLOAD_CHANNEL -e CONDA_CHANNEL_FLAGS -v $PWD:$PWD -w $PWD "${image_name}" .circleci/unittest/linux/scripts/install.sh - run: name: Run tests command: docker run -t --gpus all -v $PWD:$PWD -w $PWD "${image_name}" .circleci/unittest/linux/scripts/run_test.sh @@ -448,6 +469,7 @@ jobs: steps: - checkout - designate_upload_channel + - load_conda_channel_flags - run: name: Setup command: .circleci/unittest/windows/scripts/setup_env.sh @@ -473,6 +495,7 @@ jobs: steps: - checkout - designate_upload_channel + - load_conda_channel_flags - run: name: Setup command: .circleci/unittest/windows/scripts/setup_env.sh @@ -496,6 +519,7 @@ jobs: steps: - checkout - install_build_tools_macos + - load_conda_channel_flags - attach_workspace: at: third_party - designate_upload_channel @@ -522,6 +546,7 @@ jobs: steps: - checkout - designate_upload_channel + - load_conda_channel_flags - run: name: Setup command: .circleci/unittest/linux/scripts/setup_env.sh @@ -538,6 +563,7 @@ jobs: - attach_workspace: at: ~/workspace - checkout + - load_conda_channel_flags - run: name: Install pytorch-audio command: .circleci/build_docs/install_wheels.sh @@ -548,6 +574,9 @@ jobs: root: ./ paths: - "*" + - store_artifacts: + path: ./docs/build/html + destination: docs upload_docs: <<: *binary_common @@ -577,6 +606,18 @@ jobs: target=${tag:-master} ~/workspace/.circleci/build_docs/commit_docs.sh ~/workspace $target + docstring_parameters_sync: + <<: *binary_common + docker: + - image: circleci/python:3.8 + steps: + - checkout + - run: + name: Check parameters docstring sync + command: | + pip install --user pydocstyle + pydocstyle torchaudio + workflows: build: jobs: @@ -598,6 +639,11 @@ workflows: python_version: '3.8' requires: - download_third_parties_nix + - binary_linux_wheel: + name: binary_linux_wheel_py3.9 + python_version: '3.9' + requires: + - download_third_parties_nix - binary_macos_wheel: name: binary_macos_wheel_py3.6 python_version: '3.6' @@ -613,6 +659,11 @@ workflows: python_version: '3.8' requires: - download_third_parties_nix + - binary_macos_wheel: + name: binary_macos_wheel_py3.9 + python_version: '3.9' + requires: + - download_third_parties_nix - binary_windows_wheel: name: binary_windows_wheel_py3.6 python_version: '3.6' @@ -622,6 +673,9 @@ workflows: - binary_windows_wheel: name: binary_windows_wheel_py3.8 python_version: '3.8' + - binary_windows_wheel: + name: binary_windows_wheel_py3.9 + python_version: '3.9' - binary_linux_conda: name: binary_linux_conda_py3.6 python_version: '3.6' @@ -637,6 +691,11 @@ workflows: python_version: '3.8' requires: - download_third_parties_nix + - binary_linux_conda: + name: binary_linux_conda_py3.9 + python_version: '3.9' + requires: + - download_third_parties_nix - binary_macos_conda: name: binary_macos_conda_py3.6 python_version: '3.6' @@ -652,6 +711,11 @@ workflows: python_version: '3.8' requires: - download_third_parties_nix + - binary_macos_conda: + name: binary_macos_conda_py3.9 + python_version: '3.9' + requires: + - download_third_parties_nix - binary_windows_conda: name: binary_windows_conda_py3.6 python_version: '3.6' @@ -661,6 +725,9 @@ workflows: - binary_windows_conda: name: binary_windows_conda_py3.8 python_version: '3.8' + - binary_windows_conda: + name: binary_windows_conda_py3.9 + python_version: '3.9' - build_docs: name: build_docs python_version: '3.8' @@ -678,6 +745,11 @@ workflows: python_version: '3.8' requires: - build_docs + - docstring_parameters_sync: + name: docstring_parameters_sync + python_version: '3.8' + requires: + - binary_linux_wheel_py3.8 unittest: jobs: - download_third_parties_nix: @@ -700,6 +772,11 @@ workflows: python_version: '3.8' requires: - download_third_parties_nix + - unittest_linux_cpu: + name: unittest_linux_cpu_py3.9 + python_version: '3.9' + requires: + - download_third_parties_nix - unittest_linux_gpu: name: unittest_linux_gpu_py3.6 python_version: '3.6' @@ -715,6 +792,11 @@ workflows: python_version: '3.8' requires: - download_third_parties_nix + - unittest_linux_gpu: + name: unittest_linux_gpu_py3.9 + python_version: '3.9' + requires: + - download_third_parties_nix - unittest_windows_cpu: name: unittest_windows_cpu_py3.6 python_version: '3.6' @@ -724,6 +806,9 @@ workflows: - unittest_windows_cpu: name: unittest_windows_cpu_py3.8 python_version: '3.8' + - unittest_windows_cpu: + name: unittest_windows_cpu_py3.9 + python_version: '3.9' - unittest_windows_gpu: name: unittest_windows_gpu_py3.6 python_version: '3.6' @@ -733,6 +818,9 @@ workflows: - unittest_windows_gpu: name: unittest_windows_gpu_py3.8 python_version: '3.8' + - unittest_windows_gpu: + name: unittest_windows_gpu_py3.9 + python_version: '3.9' - unittest_macos_cpu: name: unittest_macos_cpu_py3.6 python_version: '3.6' @@ -748,6 +836,11 @@ workflows: python_version: '3.8' requires: - download_third_parties_nix + - unittest_macos_cpu: + name: unittest_macos_cpu_py3.9 + python_version: '3.9' + requires: + - download_third_parties_nix nightly: jobs: - circleci_consistency: @@ -861,6 +954,39 @@ workflows: python_version: '3.8' requires: - nightly_binary_linux_wheel_py3.8_upload + - binary_linux_wheel: + filters: + branches: + only: + - nightly + tags: + only: /v[0-9]+(\.[0-9]+)*-rc[0-9]+/ + name: nightly_binary_linux_wheel_py3.9 + python_version: '3.9' + requires: + - download_third_parties_nix + - binary_wheel_upload: + context: org-member + filters: + branches: + only: + - nightly + tags: + only: /v[0-9]+(\.[0-9]+)*-rc[0-9]+/ + name: nightly_binary_linux_wheel_py3.9_upload + requires: + - nightly_binary_linux_wheel_py3.9 + - smoke_test_linux_pip: + filters: + branches: + only: + - nightly + tags: + only: /v[0-9]+(\.[0-9]+)*-rc[0-9]+/ + name: nightly_binary_linux_wheel_py3.9_smoke_test_pip + python_version: '3.9' + requires: + - nightly_binary_linux_wheel_py3.9_upload - binary_macos_wheel: filters: branches: @@ -927,6 +1053,28 @@ workflows: name: nightly_binary_macos_wheel_py3.8_upload requires: - nightly_binary_macos_wheel_py3.8 + - binary_macos_wheel: + filters: + branches: + only: + - nightly + tags: + only: /v[0-9]+(\.[0-9]+)*-rc[0-9]+/ + name: nightly_binary_macos_wheel_py3.9 + python_version: '3.9' + requires: + - download_third_parties_nix + - binary_wheel_upload: + context: org-member + filters: + branches: + only: + - nightly + tags: + only: /v[0-9]+(\.[0-9]+)*-rc[0-9]+/ + name: nightly_binary_macos_wheel_py3.9_upload + requires: + - nightly_binary_macos_wheel_py3.9 - binary_windows_wheel: filters: branches: @@ -1020,6 +1168,37 @@ workflows: python_version: '3.8' requires: - nightly_binary_windows_wheel_py3.8_upload + - binary_windows_wheel: + filters: + branches: + only: + - nightly + tags: + only: /v[0-9]+(\.[0-9]+)*-rc[0-9]+/ + name: nightly_binary_windows_wheel_py3.9 + python_version: '3.9' + - binary_wheel_upload: + context: org-member + filters: + branches: + only: + - nightly + tags: + only: /v[0-9]+(\.[0-9]+)*-rc[0-9]+/ + name: nightly_binary_windows_wheel_py3.9_upload + requires: + - nightly_binary_windows_wheel_py3.9 + - smoke_test_windows_pip: + filters: + branches: + only: + - nightly + tags: + only: /v[0-9]+(\.[0-9]+)*-rc[0-9]+/ + name: nightly_binary_windows_wheel_py3.9_smoke_test_pip + python_version: '3.9' + requires: + - nightly_binary_windows_wheel_py3.9_upload - binary_linux_conda: filters: branches: @@ -1119,6 +1298,39 @@ workflows: python_version: '3.8' requires: - nightly_binary_linux_conda_py3.8_upload + - binary_linux_conda: + filters: + branches: + only: + - nightly + tags: + only: /v[0-9]+(\.[0-9]+)*-rc[0-9]+/ + name: nightly_binary_linux_conda_py3.9 + python_version: '3.9' + requires: + - download_third_parties_nix + - binary_conda_upload: + context: org-member + filters: + branches: + only: + - nightly + tags: + only: /v[0-9]+(\.[0-9]+)*-rc[0-9]+/ + name: nightly_binary_linux_conda_py3.9_upload + requires: + - nightly_binary_linux_conda_py3.9 + - smoke_test_linux_conda: + filters: + branches: + only: + - nightly + tags: + only: /v[0-9]+(\.[0-9]+)*-rc[0-9]+/ + name: nightly_binary_linux_conda_py3.9_smoke_test_conda + python_version: '3.9' + requires: + - nightly_binary_linux_conda_py3.9_upload - binary_macos_conda: filters: branches: @@ -1185,6 +1397,28 @@ workflows: name: nightly_binary_macos_conda_py3.8_upload requires: - nightly_binary_macos_conda_py3.8 + - binary_macos_conda: + filters: + branches: + only: + - nightly + tags: + only: /v[0-9]+(\.[0-9]+)*-rc[0-9]+/ + name: nightly_binary_macos_conda_py3.9 + python_version: '3.9' + requires: + - download_third_parties_nix + - binary_conda_upload: + context: org-member + filters: + branches: + only: + - nightly + tags: + only: /v[0-9]+(\.[0-9]+)*-rc[0-9]+/ + name: nightly_binary_macos_conda_py3.9_upload + requires: + - nightly_binary_macos_conda_py3.9 - binary_windows_conda: filters: branches: @@ -1278,6 +1512,37 @@ workflows: python_version: '3.8' requires: - nightly_binary_windows_conda_py3.8_upload + - binary_windows_conda: + filters: + branches: + only: + - nightly + tags: + only: /v[0-9]+(\.[0-9]+)*-rc[0-9]+/ + name: nightly_binary_windows_conda_py3.9 + python_version: '3.9' + - binary_conda_upload: + context: org-member + filters: + branches: + only: + - nightly + tags: + only: /v[0-9]+(\.[0-9]+)*-rc[0-9]+/ + name: nightly_binary_windows_conda_py3.9_upload + requires: + - nightly_binary_windows_conda_py3.9 + - smoke_test_windows_conda: + filters: + branches: + only: + - nightly + tags: + only: /v[0-9]+(\.[0-9]+)*-rc[0-9]+/ + name: nightly_binary_windows_conda_py3.9_smoke_test_conda + python_version: '3.9' + requires: + - nightly_binary_windows_conda_py3.9_upload docker_build: triggers: - schedule: diff --git a/.circleci/config.yml.in b/.circleci/config.yml.in index fa1e202cb9..8e01b1da56 100644 --- a/.circleci/config.yml.in +++ b/.circleci/config.yml.in @@ -45,6 +45,16 @@ commands: name: Install pkg-config command: HOMEBREW_NO_AUTO_UPDATE=1 brew install pkg-config wget # Disable brew auto update which is very slow + load_conda_channel_flags: + description: "Determines whether we need extra conda channels" + steps: + - run: + name: Adding CONDA_CHANNEL_FLAGS to BASH_ENV + command: | + CONDA_CHANNEL_FLAGS="" + if [[ "${PYTHON_VERSION}" = *3.9* ]]; then + echo "export CONDA_CHANNEL_FLAGS=-c=conda-forge" >> ${BASH_ENV} + fi binary_common: &binary_common parameters: @@ -117,7 +127,7 @@ jobs: binary_linux_wheel: <<: *binary_common docker: - - image: "pytorch/manylinux-cuda100" + - image: "pytorch/manylinux-cuda102" resource_class: 2xlarge+ steps: - checkout @@ -138,6 +148,7 @@ jobs: resource_class: 2xlarge+ steps: - checkout + - load_conda_channel_flags - attach_workspace: at: third_party - run: packaging/build_conda.sh @@ -155,6 +166,7 @@ jobs: steps: - checkout - install_build_tools_macos + - load_conda_channel_flags - attach_workspace: at: third_party - run: @@ -180,6 +192,7 @@ jobs: steps: - checkout - install_build_tools_macos + - load_conda_channel_flags - attach_workspace: at: third_party - run: @@ -202,6 +215,7 @@ jobs: name: windows-cpu steps: - checkout + - load_conda_channel_flags - run: name: build command: | @@ -221,6 +235,7 @@ jobs: name: windows-cpu steps: - checkout + - load_conda_channel_flags - run: name: build command: | @@ -278,6 +293,7 @@ jobs: - attach_workspace: at: ~/workspace - designate_upload_channel + - load_conda_channel_flags - run: name: install binaries command: | @@ -297,6 +313,7 @@ jobs: - attach_workspace: at: ~/workspace - designate_upload_channel + - load_conda_channel_flags - run: name: install binaries command: | @@ -317,6 +334,7 @@ jobs: - attach_workspace: at: ~/workspace - designate_upload_channel + - load_conda_channel_flags - run: name: install binaries command: | @@ -342,6 +360,7 @@ jobs: - attach_workspace: at: ~/workspace - designate_upload_channel + - load_conda_channel_flags - run: name: install binaries command: | @@ -395,6 +414,7 @@ jobs: - attach_workspace: at: third_party - designate_upload_channel + - load_conda_channel_flags - run: name: Setup command: .circleci/unittest/linux/scripts/setup_env.sh @@ -423,6 +443,7 @@ jobs: - attach_workspace: at: third_party - designate_upload_channel + - load_conda_channel_flags - run: name: Pull Docker image command: docker pull --quiet "${image_name}" @@ -431,7 +452,7 @@ jobs: command: docker run -t --gpus all -e PYTHON_VERSION -v $PWD:$PWD -w $PWD "${image_name}" .circleci/unittest/linux/scripts/setup_env.sh - run: name: Install torchaudio - command: docker run -t --gpus all -e UPLOAD_CHANNEL -v $PWD:$PWD -w $PWD "${image_name}" .circleci/unittest/linux/scripts/install.sh + command: docker run -t --gpus all -e UPLOAD_CHANNEL -e CONDA_CHANNEL_FLAGS -v $PWD:$PWD -w $PWD "${image_name}" .circleci/unittest/linux/scripts/install.sh - run: name: Run tests command: docker run -t --gpus all -v $PWD:$PWD -w $PWD "${image_name}" .circleci/unittest/linux/scripts/run_test.sh @@ -448,6 +469,7 @@ jobs: steps: - checkout - designate_upload_channel + - load_conda_channel_flags - run: name: Setup command: .circleci/unittest/windows/scripts/setup_env.sh @@ -473,6 +495,7 @@ jobs: steps: - checkout - designate_upload_channel + - load_conda_channel_flags - run: name: Setup command: .circleci/unittest/windows/scripts/setup_env.sh @@ -496,6 +519,7 @@ jobs: steps: - checkout - install_build_tools_macos + - load_conda_channel_flags - attach_workspace: at: third_party - designate_upload_channel @@ -522,6 +546,7 @@ jobs: steps: - checkout - designate_upload_channel + - load_conda_channel_flags - run: name: Setup command: .circleci/unittest/linux/scripts/setup_env.sh @@ -538,6 +563,7 @@ jobs: - attach_workspace: at: ~/workspace - checkout + - load_conda_channel_flags - run: name: Install pytorch-audio command: .circleci/build_docs/install_wheels.sh @@ -548,6 +574,9 @@ jobs: root: ./ paths: - "*" + - store_artifacts: + path: ./docs/build/html + destination: docs upload_docs: <<: *binary_common @@ -577,6 +606,18 @@ jobs: target=${tag:-master} ~/workspace/.circleci/build_docs/commit_docs.sh ~/workspace $target + docstring_parameters_sync: + <<: *binary_common + docker: + - image: circleci/python:3.8 + steps: + - checkout + - run: + name: Check parameters docstring sync + command: | + pip install --user pydocstyle + pydocstyle torchaudio + workflows: build: jobs: diff --git a/.circleci/regenerate.py b/.circleci/regenerate.py index ea4639ad86..0985c1f9f6 100755 --- a/.circleci/regenerate.py +++ b/.circleci/regenerate.py @@ -19,7 +19,7 @@ import os.path -PYTHON_VERSIONS = ["3.6", "3.7", "3.8"] +PYTHON_VERSIONS = ["3.6", "3.7", "3.8", "3.9"] DOC_VERSION = ('linux', '3.8') @@ -36,6 +36,8 @@ def build_workflows(prefix='', upload=False, filter_branch=None, indentation=6): # Build on every pull request, but upload only on nightly and tags w += build_doc_job(None) w += upload_doc_job('nightly') + w += docstring_parameters_sync_job(None) + return indent(indentation, w) @@ -100,6 +102,18 @@ def upload_doc_job(filter_branch): return [{"upload_docs": job}] +def docstring_parameters_sync_job(filter_branch): + job = { + "name": "docstring_parameters_sync", + "python_version": "3.8", + "requires": ["binary_linux_wheel_py3.8", ], + } + + if filter_branch: + job["filters"] = gen_filter_branch_tree(filter_branch) + return [{"docstring_parameters_sync": job}] + + def generate_base_workflow(base_workflow_name, python_version, filter_branch, os_type, btype): d = { diff --git a/.circleci/unittest/linux/scripts/install.sh b/.circleci/unittest/linux/scripts/install.sh index 209c86be71..5638a28850 100755 --- a/.circleci/unittest/linux/scripts/install.sh +++ b/.circleci/unittest/linux/scripts/install.sh @@ -34,7 +34,10 @@ else cudatoolkit="cudatoolkit=${version}" fi printf "Installing PyTorch with %s\n" "${cudatoolkit}" -conda install -y -c "pytorch-${UPLOAD_CHANNEL}" pytorch ${cudatoolkit} +( + set -x + conda install ${CONDA_CHANNEL_FLAGS:-} -y -c "pytorch-${UPLOAD_CHANNEL}" "pytorch-${UPLOAD_CHANNEL}::pytorch" ${cudatoolkit} +) # 2. Install torchaudio printf "* Installing torchaudio\n" @@ -43,11 +46,15 @@ BUILD_TRANSDUCER=1 BUILD_SOX=1 python setup.py install # 3. Install Test tools printf "* Installing test tools\n" -if [ "${os}" == Linux ] ; then - conda install -y -c conda-forge codecov pytest pytest-cov - pip install kaldi-io 'librosa>=0.8.0' parameterized SoundFile scipy 'requests>=2.20' -else - # Note: installing librosa via pip fail because it will try to compile numba. - conda install -y -c conda-forge codecov pytest pytest-cov 'librosa>=0.8.0' parameterized scipy - pip install kaldi-io SoundFile 'requests>=2.20' +NUMBA_DEV_CHANNEL="" +if [[ "$(python --version)" = *3.9* ]]; then + # Numba isn't available for Python 3.9 except on the numba dev channel and building from source fails + # See https://github.com/librosa/librosa/issues/1270#issuecomment-759065048 + NUMBA_DEV_CHANNEL="-c numba/label/dev" fi +# Note: installing librosa via pip fail because it will try to compile numba. +( + set -x + conda install -y -c conda-forge ${NUMBA_DEV_CHANNEL} 'librosa>=0.8.0' parameterized 'requests>=2.20' + pip install kaldi-io SoundFile codecov pytest pytest-cov scipy +) diff --git a/.circleci/unittest/linux/scripts/run_style_checks.sh b/.circleci/unittest/linux/scripts/run_style_checks.sh index d8af8824f5..8b2d8e2548 100755 --- a/.circleci/unittest/linux/scripts/run_style_checks.sh +++ b/.circleci/unittest/linux/scripts/run_style_checks.sh @@ -29,7 +29,7 @@ set +e exit_status=0 printf "\x1b[34mRunning flake8:\x1b[0m\n" -flake8 torchaudio test build_tools/setup_helpers +flake8 torchaudio test build_tools/setup_helpers docs/source/conf.py status=$? exit_status="$((exit_status+status))" if [ "${status}" -ne 0 ]; then @@ -38,7 +38,7 @@ fi printf "\x1b[34mRunning clang-format:\x1b[0m\n" "${this_dir}"/run_clang_format.py \ - -r torchaudio/csrc \ + -r torchaudio/csrc third_party/kaldi/src \ --clang-format-executable "${clangformat_path}" \ && git diff --exit-code status=$? diff --git a/.circleci/unittest/windows/scripts/environment.yml b/.circleci/unittest/windows/scripts/environment.yml index 4a0b71d653..27322ccc01 100644 --- a/.circleci/unittest/windows/scripts/environment.yml +++ b/.circleci/unittest/windows/scripts/environment.yml @@ -3,16 +3,14 @@ channels: - defaults dependencies: - flake8 - - numpy - pytest - pytest-cov - codecov + - scipy >= 1.4.1 - pip - pip: - - scipy == 1.4.1 - kaldi-io - PySoundFile - - librosa >= 0.8.0 - future - parameterized - dataclasses diff --git a/.circleci/unittest/windows/scripts/install.sh b/.circleci/unittest/windows/scripts/install.sh index 901cb40450..be0c890614 100644 --- a/.circleci/unittest/windows/scripts/install.sh +++ b/.circleci/unittest/windows/scripts/install.sh @@ -25,13 +25,24 @@ else cudatoolkit="cudatoolkit=${version}" fi printf "Installing PyTorch with %s\n" "${cudatoolkit}" -conda install -y -c "pytorch-${UPLOAD_CHANNEL}" pytorch "${cudatoolkit}" +conda install ${CONDA_CHANNEL_FLAGS:-} -y -c "pytorch-${UPLOAD_CHANNEL}" "pytorch-${UPLOAD_CHANNEL}::pytorch" ${cudatoolkit} # 2. Install torchaudio printf "* Installing torchaudio\n" -python setup.py install +git submodule update --init --recursive +"$root_dir/packaging/vc_env_helper.bat" python setup.py install # 3. Install Test tools printf "* Installing test tools\n" -conda install -y -c conda-forge codecov pytest pytest-cov -pip install kaldi-io 'librosa>=0.8.0' parameterized PySoundFile scipy +NUMBA_DEV_CHANNEL="" +if [[ "$(python --version)" = *3.9* ]]; then + # Numba isn't available for Python 3.9 except on the numba dev channel and building from source fails + # See https://github.com/librosa/librosa/issues/1270#issuecomment-759065048 + NUMBA_DEV_CHANNEL="-c numba/label/dev" +fi +# Note: installing librosa via pip fail because it will try to compile numba. +( + set -x + conda install -y -c conda-forge ${NUMBA_DEV_CHANNEL} 'librosa>=0.8.0' parameterized 'requests>=2.20' + pip install kaldi-io SoundFile codecov pytest pytest-cov scipy +) diff --git a/.circleci/unittest/windows/scripts/setup_env.sh b/.circleci/unittest/windows/scripts/setup_env.sh index 929a98cb8f..5f092bfceb 100644 --- a/.circleci/unittest/windows/scripts/setup_env.sh +++ b/.circleci/unittest/windows/scripts/setup_env.sh @@ -37,3 +37,6 @@ if [ ! -d "${env_dir}" ]; then conda create --prefix "${env_dir}" -y python="${PYTHON_VERSION}" fi conda activate "${env_dir}" + +# 3. Install minimal build tools +pip --quiet install cmake ninja diff --git a/.gitmodules b/.gitmodules index c01f8c91ad..dd47fc1e91 100644 --- a/.gitmodules +++ b/.gitmodules @@ -2,3 +2,7 @@ path = third_party/transducer/submodule url = https://github.com/HawkAaron/warp-transducer ignore = dirty +[submodule "kaldi"] + path = third_party/kaldi/submodule + url = https://github.com/kaldi-asr/kaldi + ignore = dirty diff --git a/CMakeLists.txt b/CMakeLists.txt index d72639a71e..87abef1262 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -47,6 +47,7 @@ endif() # Options option(BUILD_SOX "Build libsox statically" OFF) +option(BUILD_KALDI "Build kaldi statically" ON) option(BUILD_TRANSDUCER "Enable transducer" OFF) option(BUILD_LIBTORCHAUDIO "Build C++ Library" ON) option(BUILD_TORCHAUDIO_PYTHON_EXTENSION "Build Python extension" OFF) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 73674b42c2..94526661e0 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -13,6 +13,10 @@ core, please first open an issue and discuss the feature with us. Sending a PR without discussion might end up resulting in a rejected PR, because we might be taking the core in a different direction than you might be aware of. +Facebook has a [bounty program](https://www.facebook.com/whitehat/) for the +safe disclosure of security bugs. In those cases, please go through the +process outlined on that page and do not file a public issue. + Fixing bugs and implementing new features are not the only way you can contribute. It also helps the project when you report problems you're facing, and when you give a :+1: on issues that others reported and that are relevant @@ -28,12 +32,18 @@ wanted"](https://github.com/pytorch/audio/issues?q=is%3Aopen+is%3Aissue+label%3A Comment on the issue that you want to work on it and send a PR with your fix (see below). +## Contributor License Agreement ("CLA") +In order to accept your pull request, we need you to submit a CLA. You only need +to do this once to work on any of Facebook's open source projects. + +Complete your CLA here: + ## Development installation We recommend using a `conda` environment to contribute efficiently to torchaudio. -### Install PyTorch Nightly +### Install PyTorch Nightly ```bash conda install pytorch -c pytorch-nightly @@ -53,12 +63,10 @@ BUILD_SOX=1 python setup.py develop # or, for OSX # BUILD_SOX=1 MACOSX_DEPLOYMENT_TARGET=10.9 CC=clang CXX=clang++ python setup.py develop # for C++ debugging, please use DEBUG=1 -# DEBUG=1 python setup.py install +# DEBUG=1 python setup.py develop ``` -Note: you don't need to use `BUILD_SOX=1` if you have `libsox-dev` installed -already. If you built sox however, set the `PATH` variable so that the tests -properly use the newly built `sox` binary: +If you built sox, set the `PATH` variable so that the tests properly use the newly built `sox` binary: ```bash export PATH="/third_party/install/bin:${PATH}" @@ -67,7 +75,7 @@ export PATH="/third_party/install/bin:${PATH}" The following dependencies are also needed for testing: ```bash -pip install typing pytest scipy numpy parametrized +pip install typing pytest scipy numpy parameterized ``` ## Development Process @@ -75,19 +83,19 @@ pip install typing pytest scipy numpy parametrized If you plan to modify the code or documentation, please follow the steps below: 1. Fork the repository and create your branch from `master`: `$ git checkout master && git checkout -b my_cool_feature` -2. If you have modified the code (new feature or bug-fix), [please add tests](.test/torchaudio_unittest/). +2. If you have modified the code (new feature or bug-fix), [please add tests](test/torchaudio_unittest/). 3. If you have changed APIs, [update the documentation](#Documentation). -For more details about pull requests, -please read [GitHub's guides](https://docs.github.com/en/github/collaborating-with-issues-and-pull-requests/creating-a-pull-request). +For more details about pull requests, +please read [GitHub's guides](https://docs.github.com/en/github/collaborating-with-issues-and-pull-requests/creating-a-pull-request). If you would like to contribute a new model, please see [here](#New-model). -If you would like to contribute a new dataset, please see [here](#New-dataset). +If you would like to contribute a new dataset, please see [here](#New-dataset). ## Testing -Please refer to our [testing guidelines](.test/torchaudio_unittest/) for more +Please refer to our [testing guidelines](test/torchaudio_unittest/) for more details. ## Documentation diff --git a/README.md b/README.md index 527b1a22da..2cff4bf076 100644 --- a/README.md +++ b/README.md @@ -29,17 +29,18 @@ to use and feel like a natural extension. Dependencies ------------ * PyTorch (See below for the compatible versions) -* libsox v14.3.2 or above (only required when building from source) * [optional] vesis84/kaldi-io-for-python commit cb46cb1f44318a5d04d4941cf39084c5b021241e or above The following are the corresponding ``torchaudio`` versions and supported Python versions. | ``torch`` | ``torchaudio`` | ``python`` | | ------------------------ | ------------------------ | ------------------------------- | -| ``master`` / ``nightly`` | ``master`` / ``nightly`` | ``>=3.6`` | -| ``1.7.0`` | ``0.7.0`` | ``>=3.6`` | -| ``1.6.0`` | ``0.6.0`` | ``>=3.6`` | -| ``1.5.0`` | ``0.5.0`` | ``>=3.5`` | +| ``master`` / ``nightly`` | ``master`` / ``nightly`` | ``>=3.6``, ``<=3.9`` | +| ``1.8.0`` | ``0.8.0`` | ``>=3.6``, ``<=3.9`` | +| ``1.7.1`` | ``0.7.2`` | ``>=3.6``, ``<=3.9`` | +| ``1.7.0`` | ``0.7.0`` | ``>=3.6``, ``<=3.8`` | +| ``1.6.0`` | ``0.6.0`` | ``>=3.6``, ``<=3.8`` | +| ``1.5.0`` | ``0.5.0`` | ``>=3.5``, ``<=3.8`` | | ``1.4.0`` | ``0.4.0`` | ``==2.7``, ``>=3.5``, ``<=3.8`` | @@ -83,39 +84,7 @@ conda install -y -c pytorch-nightly torchaudio ### From Source -If your system configuration is not among the supported configurations -above, you can build torchaudio from source. - -This will require libsox v14.3.2 or above. - -

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 literal 0 HcmV?d00001 diff --git a/examples/libtorchaudio/data/rir.wav b/examples/libtorchaudio/data/rir.wav new file mode 100644 index 0000000000000000000000000000000000000000..c9e6d836818ff5ea8cfaaadeab69316561b32465 GIT binary patch literal 9338 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 + +int main(int argc, char* argv[]) { + if (argc !=4) { + std::cerr << "Usage: " << argv[0] << " " << 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; +} diff --git a/examples/libtorchaudio/run.sh b/examples/libtorchaudio/run.sh new file mode 100755 index 0000000000..a55614e909 --- /dev/null +++ b/examples/libtorchaudio/run.sh @@ -0,0 +1,24 @@ +#!/usr/bin/env bash + +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}" diff --git a/examples/pipeline_wav2letter/languagemodels.py b/examples/pipeline_wav2letter/languagemodels.py index eee018ae69..d66858ea95 100644 --- a/examples/pipeline_wav2letter/languagemodels.py +++ b/examples/pipeline_wav2letter/languagemodels.py @@ -8,7 +8,7 @@ def __init__(self, labels, char_blank, char_space): self.char_space = char_space self.char_blank = char_blank - labels = [l for l in labels] + labels = list(labels) self.length = len(labels) enumerated = list(enumerate(labels)) flipped = [(sub[1], sub[0]) for sub in enumerated] diff --git a/examples/source_separation/utils/dataset/wsj0mix.py b/examples/source_separation/utils/dataset/wsj0mix.py index efd9268971..c67bbd8205 100644 --- a/examples/source_separation/utils/dataset/wsj0mix.py +++ b/examples/source_separation/utils/dataset/wsj0mix.py @@ -63,7 +63,7 @@ def __len__(self) -> int: def __getitem__(self, key: int) -> SampleType: """Load the n-th sample from the dataset. Args: - n (int): The index of the sample to be loaded + key (int): The index of the sample to be loaded Returns: tuple: ``(sample_rate, mix_waveform, list_of_source_waveforms)`` """ diff --git a/packaging/build_conda.sh b/packaging/build_conda.sh index 488d0fe871..161c48ad43 100755 --- a/packaging/build_conda.sh +++ b/packaging/build_conda.sh @@ -6,7 +6,8 @@ script_dir="$( cd "$( dirname "${BASH_SOURCE[0]}" )" >/dev/null 2>&1 && pwd )" export BUILD_TYPE="conda" export NO_CUDA_PACKAGE=1 -setup_env 0.8.0 +setup_env 0.9.0 export SOURCE_ROOT_DIR="$PWD" setup_conda_pytorch_constraint +setup_visual_studio_constraint conda build $CONDA_CHANNEL_FLAGS --no-anaconda-upload --python "$PYTHON_VERSION" packaging/torchaudio diff --git a/packaging/build_wheel.sh b/packaging/build_wheel.sh index 11e8f07bfd..9b4194afda 100755 --- a/packaging/build_wheel.sh +++ b/packaging/build_wheel.sh @@ -6,14 +6,14 @@ script_dir="$( cd "$( dirname "${BASH_SOURCE[0]}" )" >/dev/null 2>&1 && pwd )" export BUILD_TYPE="wheel" export NO_CUDA_PACKAGE=1 -setup_env 0.8.0 +setup_env 0.9.0 setup_wheel_python pip_install numpy future cmake ninja setup_pip_pytorch_version python setup.py clean if [[ "$OSTYPE" == "msys" ]]; then python_tag="$(echo "cp$PYTHON_VERSION" | tr -d '.')" - python setup.py bdist_wheel --plat-name win_amd64 --python-tag $python_tag + "$script_dir/vc_env_helper.bat" python setup.py bdist_wheel --plat-name win_amd64 --python-tag $python_tag else BUILD_TRANSDUCER=1 BUILD_SOX=1 python setup.py bdist_wheel fi diff --git a/packaging/pkg_helpers.bash b/packaging/pkg_helpers.bash index 36760b9484..5dc5397042 100644 --- a/packaging/pkg_helpers.bash +++ b/packaging/pkg_helpers.bash @@ -141,6 +141,7 @@ setup_wheel_python() { 3.6) python_abi=cp36-cp36m ;; 3.7) python_abi=cp37-cp37m ;; 3.8) python_abi=cp38-cp38 ;; + 3.9) python_abi=cp39-cp39 ;; *) echo "Unrecognized PYTHON_VERSION=$PYTHON_VERSION" exit 1 @@ -176,11 +177,16 @@ setup_pip_pytorch_version() { # # You MUST have populated PYTORCH_VERSION_SUFFIX before hand. setup_conda_pytorch_constraint() { + CONDA_CHANNEL_FLAGS="${CONDA_CHANNEL_FLAGS}" if [[ -z "$PYTORCH_VERSION" ]]; then - export CONDA_CHANNEL_FLAGS="-c pytorch-nightly" + export CONDA_CHANNEL_FLAGS="${CONDA_CHANNEL_FLAGS} -c pytorch-nightly" export PYTORCH_VERSION="$(conda search --json 'pytorch[channel=pytorch-nightly]' | python -c "import sys, json, re; print(re.sub(r'\\+.*$', '', json.load(sys.stdin)['pytorch'][-1]['version']))")" else - export CONDA_CHANNEL_FLAGS="-c pytorch -c pytorch-${UPLOAD_CHANNEL}" + export CONDA_CHANNEL_FLAGS="${CONDA_CHANNEL_FLAGS} -c pytorch -c pytorch-test -c pytorch-nightly" + fi + # Some dependencies for Python 3.9 are only on conda-forge + if [[ "${PYTHON_VERSION}" = "3.9" ]]; then + export CONDA_CHANNEL_FLAGS="${CONDA_CHANNEL_FLAGS} -c conda-forge" fi if [[ "$CU_VERSION" == cpu ]]; then export CONDA_PYTORCH_BUILD_CONSTRAINT="- pytorch==$PYTORCH_VERSION${PYTORCH_VERSION_SUFFIX}" @@ -215,3 +221,13 @@ setup_conda_cudatoolkit_constraint() { esac fi } + +# Build the proper compiler package before building the final package +setup_visual_studio_constraint() { + if [[ "$OSTYPE" == "msys" ]]; then + export VSTOOLCHAIN_PACKAGE=vs2019 + export VSDEVCMD_ARGS='' + conda build $CONDA_CHANNEL_FLAGS --no-anaconda-upload packaging/$VSTOOLCHAIN_PACKAGE + cp packaging/$VSTOOLCHAIN_PACKAGE/conda_build_config.yaml packaging/torchaudio/conda_build_config.yaml + fi +} diff --git a/packaging/torchaudio/meta.yaml b/packaging/torchaudio/meta.yaml index ad12821d0e..5f9e485eba 100644 --- a/packaging/torchaudio/meta.yaml +++ b/packaging/torchaudio/meta.yaml @@ -16,10 +16,12 @@ requirements: - cpuonly - cmake - ninja + - defaults::numpy >=1.11 {{ environ.get('CONDA_PYTORCH_BUILD_CONSTRAINT') }} run: - python + - defaults::numpy >=1.11 {{ environ.get('CONDA_PYTORCH_CONSTRAINT') }} build: diff --git a/packaging/vc_env_helper.bat b/packaging/vc_env_helper.bat new file mode 100644 index 0000000000..9410135677 --- /dev/null +++ b/packaging/vc_env_helper.bat @@ -0,0 +1,39 @@ +@echo on + +set VC_VERSION_LOWER=16 +set VC_VERSION_UPPER=17 + +for /f "usebackq tokens=*" %%i in (`"%ProgramFiles(x86)%\Microsoft Visual Studio\Installer\vswhere.exe" -legacy -products * -version [%VC_VERSION_LOWER%^,%VC_VERSION_UPPER%^) -property installationPath`) do ( + if exist "%%i" if exist "%%i\VC\Auxiliary\Build\vcvarsall.bat" ( + set "VS15INSTALLDIR=%%i" + set "VS15VCVARSALL=%%i\VC\Auxiliary\Build\vcvarsall.bat" + goto vswhere + ) +) + +:vswhere +if "%VSDEVCMD_ARGS%" == "" ( + call "%VS15VCVARSALL%" x64 || exit /b 1 +) else ( + call "%VS15VCVARSALL%" x64 %VSDEVCMD_ARGS% || exit /b 1 +) + +@echo on + +set DISTUTILS_USE_SDK=1 + +set args=%1 +shift +:start +if [%1] == [] goto done +set args=%args% %1 +shift +goto start + +:done +if "%args%" == "" ( + echo Usage: vc_env_helper.bat [command] [args] + echo e.g. vc_env_helper.bat cl /c test.cpp +) + +%args% || exit /b 1 diff --git a/packaging/vs2019/activate.bat b/packaging/vs2019/activate.bat new file mode 100644 index 0000000000..6f607ba751 --- /dev/null +++ b/packaging/vs2019/activate.bat @@ -0,0 +1,44 @@ +:: Set env vars that tell distutils to use the compiler that we put on path +SET DISTUTILS_USE_SDK=1 +SET MSSdk=1 + +SET "VS_VERSION=16.0" +SET "VS_MAJOR=16" +SET "VS_YEAR=2019" + +set "MSYS2_ARG_CONV_EXCL=/AI;/AL;/OUT;/out" +set "MSYS2_ENV_CONV_EXCL=CL" + +:: For Python 3.5+, ensure that we link with the dynamic runtime. See +:: http://stevedower.id.au/blog/building-for-python-3-5-part-two/ for more info +set "PY_VCRUNTIME_REDIST=%PREFIX%\\bin\\vcruntime140.dll" + +for /f "usebackq tokens=*" %%i in (`"%ProgramFiles(x86)%\Microsoft Visual Studio\Installer\vswhere.exe" -legacy -products * -version [16^,17^) -property installationPath`) do ( + if exist "%%i" if exist "%%i\VC\Auxiliary\Build\vcvarsall.bat" ( + set "VSINSTALLDIR=%%i\" + goto :vswhere + ) +) + +:vswhere + +:: Shorten PATH to avoid the `input line too long` error. +SET MyPath=%PATH% + +setlocal EnableDelayedExpansion + +SET TempPath="%MyPath:;=";"%" +SET var= +FOR %%a IN (%TempPath%) DO ( + IF EXIST %%~sa ( + SET "var=!var!;%%~sa" + ) +) + +set "TempPath=!var:~1!" +endlocal & set "PATH=%TempPath%" + +:: Shorten current directory too +FOR %%A IN (.) DO CD "%%~sA" + +:: other things added by install_activate.bat at package build time diff --git a/packaging/vs2019/conda_build_config.yaml b/packaging/vs2019/conda_build_config.yaml new file mode 100644 index 0000000000..358052ec01 --- /dev/null +++ b/packaging/vs2019/conda_build_config.yaml @@ -0,0 +1,24 @@ +blas_impl: + - mkl # [x86_64] +c_compiler: + - vs2019 # [win] +cxx_compiler: + - vs2019 # [win] +python: + - 3.5 + - 3.6 +# This differs from target_platform in that it determines what subdir the compiler +# will target, not what subdir the compiler package will be itself. +# For example, we need a win-64 vs2008_win-32 package, so that we compile win-32 +# code on win-64 miniconda. +cross_compiler_target_platform: + - win-64 # [win] +target_platform: + - win-64 # [win] +vc: + - 14 +zip_keys: + - # [win] + - vc # [win] + - c_compiler # [win] + - cxx_compiler # [win] diff --git a/packaging/vs2019/install_activate.bat b/packaging/vs2019/install_activate.bat new file mode 100644 index 0000000000..3c38253aa5 --- /dev/null +++ b/packaging/vs2019/install_activate.bat @@ -0,0 +1,30 @@ +set YEAR=2019 +set VER=16 + +mkdir "%PREFIX%\etc\conda\activate.d" +COPY "%RECIPE_DIR%\activate.bat" "%PREFIX%\etc\conda\activate.d\vs%YEAR%_compiler_vars.bat" + +IF "%cross_compiler_target_platform%" == "win-64" ( + set "target_platform=amd64" + echo SET "CMAKE_GENERATOR=Visual Studio %VER% %YEAR% Win64" >> "%PREFIX%\etc\conda\activate.d\vs%YEAR%_compiler_vars.bat" + echo pushd "%%VSINSTALLDIR%%" >> "%PREFIX%\etc\conda\activate.d\vs%YEAR%_compiler_vars.bat" + IF "%VSDEVCMD_ARGS%" == "" ( + echo CALL "VC\Auxiliary\Build\vcvarsall.bat" x64 >> "%PREFIX%\etc\conda\activate.d\vs%YEAR%_compiler_vars.bat" + echo popd >> "%PREFIX%\etc\conda\activate.d\vs%YEAR%_compiler_vars.bat" + echo pushd "%%VSINSTALLDIR%%" >> "%PREFIX%\etc\conda\activate.d\vs%YEAR%_compiler_vars.bat" + echo CALL "VC\Auxiliary\Build\vcvarsall.bat" x86_amd64 >> "%PREFIX%\etc\conda\activate.d\vs%YEAR%_compiler_vars.bat" + ) ELSE ( + echo CALL "VC\Auxiliary\Build\vcvarsall.bat" x64 %VSDEVCMD_ARGS% >> "%PREFIX%\etc\conda\activate.d\vs%YEAR%_compiler_vars.bat" + echo popd >> "%PREFIX%\etc\conda\activate.d\vs%YEAR%_compiler_vars.bat" + echo pushd "%%VSINSTALLDIR%%" >> "%PREFIX%\etc\conda\activate.d\vs%YEAR%_compiler_vars.bat" + echo CALL "VC\Auxiliary\Build\vcvarsall.bat" x86_amd64 %VSDEVCMD_ARGS% >> "%PREFIX%\etc\conda\activate.d\vs%YEAR%_compiler_vars.bat" + ) + echo popd >> "%PREFIX%\etc\conda\activate.d\vs%YEAR%_compiler_vars.bat" + ) else ( + set "target_platform=x86" + echo SET "CMAKE_GENERATOR=Visual Studio %VER% %YEAR%" >> "%PREFIX%\etc\conda\activate.d\vs%YEAR%_compiler_vars.bat" + echo pushd "%%VSINSTALLDIR%%" >> "%PREFIX%\etc\conda\activate.d\vs%YEAR%_compiler_vars.bat" + echo CALL "VC\Auxiliary\Build\vcvars32.bat" >> "%PREFIX%\etc\conda\activate.d\vs%YEAR%_compiler_vars.bat" + echo popd + ) + diff --git a/packaging/vs2019/install_runtime.bat b/packaging/vs2019/install_runtime.bat new file mode 100644 index 0000000000..e09a5ccfb0 --- /dev/null +++ b/packaging/vs2019/install_runtime.bat @@ -0,0 +1,49 @@ +set VC_PATH=x86 +if "%ARCH%"=="64" ( + set VC_PATH=x64 +) + +set MSC_VER=2019 + +rem :: This should always be present for VC installed with VS. Not sure about VC installed with Visual C++ Build Tools 2015 +rem FOR /F "usebackq tokens=3*" %%A IN (`REG QUERY "HKEY_LOCAL_MACHINE\Software\Microsoft\DevDiv\VC\Servicing\14.0\IDE.x64" /v UpdateVersion`) DO ( +rem set SP=%%A +rem ) + +rem if not "%SP%" == "%PKG_VERSION%" ( +rem echo "Version detected from registry: %SP%" +rem echo "does not match version of package being built (%PKG_VERSION%)" +rem echo "Do you have current updates for VS 2015 installed?" +rem exit 1 +rem ) + + +REM ========== REQUIRES Win 10 SDK be installed, or files otherwise copied to location below! +robocopy "C:\Program Files (x86)\Windows Kits\10\Redist\ucrt\DLLs\%VC_PATH%" "%LIBRARY_BIN%" *.dll /E +robocopy "C:\Program Files (x86)\Windows Kits\10\Redist\ucrt\DLLs\%VC_PATH%" "%PREFIX%" *.dll /E +if %ERRORLEVEL% GEQ 8 exit 1 + +REM ========== This one comes from visual studio 2019 +set "VC_VER=142" + +for /f "usebackq tokens=*" %%i in (`"%ProgramFiles(x86)%\Microsoft Visual Studio\Installer\vswhere.exe" -legacy -products * -version [16^,17^) -property installationPath`) do ( + if exist "%%i" if exist "%%i\VC\Auxiliary\Build\vcvarsall.bat" ( + set "VS15VCVARSALL=%%i\VC\Auxiliary\Build\vcvarsall.bat" + goto :eof + ) +) + +@setlocal +call "%VS15VARSALL%" x64 + +set "REDIST_ROOT=%VCToolsRedistDir%%VC_PATH%" + +robocopy "%REDIST_ROOT%\Microsoft.VC%VC_VER%.CRT" "%LIBRARY_BIN%" *.dll /E +if %ERRORLEVEL% LSS 8 exit 0 +robocopy "%REDIST_ROOT%\Microsoft.VC%VC_VER%.CRT" "%PREFIX%" *.dll /E +if %ERRORLEVEL% LSS 8 exit 0 +robocopy "%REDIST_ROOT%\Microsoft.VC%VC_VER%.OpenMP" "%LIBRARY_BIN%" *.dll /E +if %ERRORLEVEL% LSS 8 exit 0 +robocopy "%REDIST_ROOT%\Microsoft.VC%VC_VER%.OpenMP" "%PREFIX%" *.dll /E +if %ERRORLEVEL% LSS 8 exit 0 +@endlocal diff --git a/packaging/vs2019/meta.yaml b/packaging/vs2019/meta.yaml new file mode 100644 index 0000000000..94a0ed4db3 --- /dev/null +++ b/packaging/vs2019/meta.yaml @@ -0,0 +1,24 @@ +{% set vcver="14.2" %} +{% set vcfeature="14" %} +{% set vsyear="2019" %} +{% set fullver="15.4.27004.2010" %} + +package: + name: vs{{ vsyear }} + version: {{ fullver }} + +build: + skip: True [not win] + script_env: + - VSDEVCMD_ARGS # [win] + +outputs: + - name: vs{{ vsyear }}_{{ cross_compiler_target_platform }} + script: install_activate.bat + track_features: + # VS 2019 is binary-compatible with VS 2017/vc 14.1 and 2015/vc14. Tools are "v142". + strong: + - vc{{ vcfeature }} + about: + summary: Activation and version verification of MSVC {{ vcver }} (VS {{ vsyear }}) compiler + license: BSD 3-clause diff --git a/setup.cfg b/setup.cfg new file mode 100644 index 0000000000..182c9f7e3f --- /dev/null +++ b/setup.cfg @@ -0,0 +1,2 @@ +[pydocstyle] +select = D417 # Missing argument descriptions in the docstring diff --git a/setup.py b/setup.py index 1ee56dfcb7..255ac9894d 100644 --- a/setup.py +++ b/setup.py @@ -12,7 +12,7 @@ # Creating the version file -version = '0.8.0a0' +version = '0.9.0a0' sha = 'Unknown' try: @@ -76,6 +76,7 @@ def run(self): "Programming Language :: Python :: 3.6", "Programming Language :: Python :: 3.7", "Programming Language :: Python :: 3.8", + "Programming Language :: Python :: 3.9", "Programming Language :: Python :: Implementation :: CPython", "Topic :: Multimedia :: Sound/Audio", "Topic :: Scientific/Engineering :: Artificial Intelligence" diff --git a/test/torchaudio_unittest/README.md b/test/torchaudio_unittest/README.md index d61c64b015..69f8498f05 100644 --- a/test/torchaudio_unittest/README.md +++ b/test/torchaudio_unittest/README.md @@ -8,7 +8,7 @@ https://docs.pytest.org/ for the detail of how to use `pytest` command. For testing, the following packages are needed: ```bash -pip install typing pytest scipy numpy parametrized +pip install typing pytest scipy numpy parameterized ``` Make sure to follow the installation instruction in the [contributing @@ -40,7 +40,7 @@ We use PyTorch's test utilities instead of `pytest` frameworks when writing test Also, while we recommend using `pytest` for *running* the tests, we cannot make `pytest` a testing dependency of `torchaudio`. As a result, you should not import `pytest` or its submodules in the test files; Use the Python -`unittest` builtin module instead, or the `parametrized` package to +`unittest` builtin module instead, or the `parameterized` package to parametrize tests. ## Structure of tests @@ -50,17 +50,17 @@ The following is an overview of the tests and related modules for `torchaudio`. ### Purpose specific test suites #### Numerical compatibility against existing software -- [Librosa compatibility test](./librosa_compatibility_test.py) +- [Librosa compatibility test](./transforms/librosa_compatibility_test.py) Test suite for numerical compatibility against librosa. -- [SoX compatibility test](./sox_compatibility_test.py) +- [SoX compatibility test](./transforms/sox_compatibility_test.py) Test suite for numerical compatibility against SoX. -- [Kaldi compatibility test](./kaldi_compatibility_test.py) +- [Kaldi compatibility test](./transforms/kaldi_compatibility_impl.py) Test suite for numerical compatibility against Kaldi. #### Result consistency with PyTorch framework -- [TorchScript consistency test](./torchscript_consistency_impl.py) +- [TorchScript consistency test](./transforms/torchscript_consistency_impl.py) Test suite to check 1. if an API is TorchScript-able, and 2. the results from Python and Torchscript match. -- [Batch consistency test](./batch_consistency_test.py) +- [Batch consistency test](./transforms/batch_consistency_test.py) Test suite to check if functionals/Transforms handle single sample input and batch input and return the same result. ### Module specific test suites @@ -69,7 +69,7 @@ The following test modules are defined for corresponding `torchaudio` module/fun - [`torchaudio.datasets`](./datasets) - [`torchaudio.functional`](./functional) -- [`torchaudio.transforms`](./transforms_test.py) +- [`torchaudio.transforms`](./transforms/transforms_test.py) - [`torchaudio.compliance.kaldi`](./compliance_kaldi_test.py) - [`torchaudio.kaldi_io`](./kaldi_io_test.py) - [`torchaudio.sox_effects`](./sox_effect) @@ -142,7 +142,7 @@ The following is the current practice of torchaudio test suite. - Set class memeber `dtype`, `device` and `backend` for the desired behavior. - If you do not set `backend` value in your test suite, then I/O functions will be unassigned and attempt to load/save file will fail. - For `backend` value, in addition to available backends, you can also provide the value "default" and backend will be picked automatically based on availability. -1. If you are writing tests that should pass on diffrent dtype/devices, write a common class inheriting `common_utils.TestBaseMixin`, then inherit `common_utils.PytorchTestCase` and define class attributes (`dtype` / `device` / `backend`) there. See [Torchscript consistency test implementation](./torchscript_consistency_impl.py) and test definitions for [CPU](./torchscript_consistency_cpu_test.py) and [CUDA](./torchscript_consistency_cuda_test.py) devices. +1. If you are writing tests that should pass on diffrent dtype/devices, write a common class inheriting `common_utils.TestBaseMixin`, then inherit `common_utils.PytorchTestCase` and define class attributes (`dtype` / `device` / `backend`) there. See [Torchscript consistency test implementation](./transforms/torchscript_consistency_impl.py) and test definitions for [CPU](./transforms/torchscript_consistency_cpu_test.py) and [CUDA](./transforms/torchscript_consistency_cuda_test.py) devices. 1. For numerically comparing Tensors, use `assertEqual` method from torchaudio_unittest.common_utils.PytorchTestCase` class. This method has a better support for a wide variety of Tensor types. When you add a new feature(functional/transform), consider the following diff --git a/test/torchaudio_unittest/assets/kaldi_test_fbank_args.json b/test/torchaudio_unittest/assets/kaldi_test_fbank_args.jsonl similarity index 100% rename from test/torchaudio_unittest/assets/kaldi_test_fbank_args.json rename to test/torchaudio_unittest/assets/kaldi_test_fbank_args.jsonl diff --git a/test/torchaudio_unittest/assets/kaldi_test_mfcc_args.json b/test/torchaudio_unittest/assets/kaldi_test_mfcc_args.jsonl similarity index 100% rename from test/torchaudio_unittest/assets/kaldi_test_mfcc_args.json rename to test/torchaudio_unittest/assets/kaldi_test_mfcc_args.jsonl diff --git a/test/torchaudio_unittest/assets/kaldi_test_pitch_args.jsonl b/test/torchaudio_unittest/assets/kaldi_test_pitch_args.jsonl new file mode 100644 index 0000000000..9844bd6c72 --- /dev/null +++ b/test/torchaudio_unittest/assets/kaldi_test_pitch_args.jsonl @@ -0,0 +1,5 @@ +{"sample_rate": 8000} +{"sample_rate": 8000, "frames_per_chunk": 200} +{"sample_rate": 8000, "frames_per_chunk": 200, "simulate_first_pass_online": true} +{"sample_rate": 16000} +{"sample_rate": 44100} diff --git a/test/torchaudio_unittest/assets/kaldi_test_spectrogram_args.json b/test/torchaudio_unittest/assets/kaldi_test_spectrogram_args.jsonl similarity index 100% rename from test/torchaudio_unittest/assets/kaldi_test_spectrogram_args.json rename to test/torchaudio_unittest/assets/kaldi_test_spectrogram_args.jsonl diff --git a/test/torchaudio_unittest/assets/sox_effect_test_args.json b/test/torchaudio_unittest/assets/sox_effect_test_args.jsonl similarity index 100% rename from test/torchaudio_unittest/assets/sox_effect_test_args.json rename to test/torchaudio_unittest/assets/sox_effect_test_args.jsonl diff --git a/test/torchaudio_unittest/backend/legacy_test.py b/test/torchaudio_unittest/backend/legacy_test.py deleted file mode 100644 index 3dbc419bde..0000000000 --- a/test/torchaudio_unittest/backend/legacy_test.py +++ /dev/null @@ -1,290 +0,0 @@ -import os -import math -import shutil -import tempfile -import unittest - -import torch -import torchaudio -from torchaudio.utils import sox_utils -from torchaudio._internal.module_utils import is_module_available - -from torchaudio_unittest.common_utils import get_asset_path - -BACKENDS = [] -BACKENDS_MP3 = [] - -if is_module_available('soundfile'): - BACKENDS.append('soundfile') - -if is_module_available('torchaudio._torchaudio'): - BACKENDS.append('sox') - - if ( - 'mp3' in sox_utils.list_read_formats() and - 'mp3' in sox_utils.list_write_formats() - ): - BACKENDS_MP3 = ['sox'] - - -def create_temp_assets_dir(): - """ - Creates a temporary directory and moves all files from test/assets there. - Returns a Tuple[string, TemporaryDirectory] which is the folder path - and object. - """ - tmp_dir = tempfile.TemporaryDirectory() - shutil.copytree(get_asset_path(), os.path.join(tmp_dir.name, "assets")) - return tmp_dir.name, tmp_dir - - -class Test_LoadSave(unittest.TestCase): - test_dirpath, test_dir = create_temp_assets_dir() - test_filepath = os.path.join(test_dirpath, "assets", - "steam-train-whistle-daniel_simon.mp3") - test_filepath_wav = os.path.join(test_dirpath, "assets", - "steam-train-whistle-daniel_simon.wav") - - def setUp(self): - torchaudio.USE_SOUNDFILE_LEGACY_INTERFACE = True - - def test_1_save(self): - for backend in BACKENDS_MP3: - with self.subTest(): - torchaudio.set_audio_backend(backend) - self._test_1_save(self.test_filepath, False) - - for backend in BACKENDS: - with self.subTest(): - torchaudio.set_audio_backend(backend) - self._test_1_save(self.test_filepath_wav, True) - - def _test_1_save(self, test_filepath, normalization): - # load signal - x, sr = torchaudio.load(test_filepath, normalization=normalization) - - # check save - new_filepath = os.path.join(self.test_dirpath, "test.wav") - torchaudio.save(new_filepath, x, sr) - self.assertTrue(os.path.isfile(new_filepath)) - os.unlink(new_filepath) - - # check automatic normalization - x /= 1 << 31 - torchaudio.save(new_filepath, x, sr) - self.assertTrue(os.path.isfile(new_filepath)) - os.unlink(new_filepath) - - # test save 1d tensor - x = x[0, :] # get mono signal - x.squeeze_() # remove channel dim - torchaudio.save(new_filepath, x, sr) - self.assertTrue(os.path.isfile(new_filepath)) - os.unlink(new_filepath) - - # don't allow invalid sizes as inputs - with self.assertRaises(ValueError): - x.unsqueeze_(1) # L x C not C x L - torchaudio.save(new_filepath, x, sr) - - with self.assertRaises(ValueError): - x.squeeze_() - x.unsqueeze_(1) - x.unsqueeze_(0) # 1 x L x 1 - torchaudio.save(new_filepath, x, sr) - - # don't save to folders that don't exist - with self.assertRaises(OSError): - new_filepath = os.path.join(self.test_dirpath, "no-path", - "test.wav") - torchaudio.save(new_filepath, x, sr) - - def test_1_save_sine(self): - for backend in BACKENDS: - with self.subTest(): - torchaudio.set_audio_backend(backend) - self._test_1_save_sine() - - def _test_1_save_sine(self): - - # save created file - sinewave_filepath = os.path.join(self.test_dirpath, "assets", - "sinewave.wav") - sr = 16000 - freq = 440 - volume = 0.3 - - y = (torch.cos( - 2 * math.pi * torch.arange(0, 4 * sr).float() * freq / sr)) - y.unsqueeze_(0) - # y is between -1 and 1, so must scale - y = (y * volume * (2**31)).long() - torchaudio.save(sinewave_filepath, y, sr) - self.assertTrue(os.path.isfile(sinewave_filepath)) - - # test precision - new_precision = 32 - new_filepath = os.path.join(self.test_dirpath, "test.wav") - si, ei = torchaudio.info(sinewave_filepath) - torchaudio.save(new_filepath, y, sr, new_precision) - si32, ei32 = torchaudio.info(new_filepath) - self.assertEqual(si.precision, 16) - self.assertEqual(si32.precision, new_precision) - os.unlink(new_filepath) - - def test_2_load(self): - for backend in BACKENDS_MP3: - with self.subTest(): - torchaudio.set_audio_backend(backend) - self._test_2_load(self.test_filepath, 278756) - - for backend in BACKENDS: - with self.subTest(): - torchaudio.set_audio_backend(backend) - self._test_2_load(self.test_filepath_wav, 276858) - - def _test_2_load(self, test_filepath, length): - # check normal loading - x, sr = torchaudio.load(test_filepath) - self.assertEqual(sr, 44100) - self.assertEqual(x.size(), (2, length)) - - # check offset - offset = 15 - x, _ = torchaudio.load(test_filepath) - x_offset, _ = torchaudio.load(test_filepath, offset=offset) - self.assertTrue(x[:, offset:].allclose(x_offset)) - - # check number of frames - n = 201 - x, _ = torchaudio.load(test_filepath, num_frames=n) - self.assertTrue(x.size(), (2, n)) - - # check channels first - x, _ = torchaudio.load(test_filepath, channels_first=False) - self.assertEqual(x.size(), (length, 2)) - - # check raising errors - with self.assertRaises(OSError): - torchaudio.load("file-does-not-exist.mp3") - - with self.assertRaises(OSError): - tdir = os.path.join( - os.path.dirname(self.test_dirpath), "torchaudio") - torchaudio.load(tdir) - - def test_2_load_nonormalization(self): - for backend in BACKENDS_MP3: - if backend == 'sox_io': - continue - with self.subTest(): - torchaudio.set_audio_backend(backend) - self._test_2_load_nonormalization(self.test_filepath, 278756) - - def _test_2_load_nonormalization(self, test_filepath, length): - - # check no normalizing - x, _ = torchaudio.load(test_filepath, normalization=False) - self.assertTrue(x.min() <= -1.0) - self.assertTrue(x.max() >= 1.0) - - # check different input tensor type - x, _ = torchaudio.load(test_filepath, torch.LongTensor(), normalization=False) - self.assertTrue(isinstance(x, torch.LongTensor)) - - def test_3_load_and_save_is_identity(self): - for backend in BACKENDS: - if backend == 'sox_io': - continue - with self.subTest(): - torchaudio.set_audio_backend(backend) - self._test_3_load_and_save_is_identity() - - def _test_3_load_and_save_is_identity(self): - input_path = os.path.join(self.test_dirpath, 'assets', 'sinewave.wav') - tensor, sample_rate = torchaudio.load(input_path) - output_path = os.path.join(self.test_dirpath, 'test.wav') - torchaudio.save(output_path, tensor, sample_rate) - tensor2, sample_rate2 = torchaudio.load(output_path) - self.assertTrue(tensor.allclose(tensor2)) - self.assertEqual(sample_rate, sample_rate2) - os.unlink(output_path) - - @unittest.skipIf(any(be not in BACKENDS for be in ["sox", "soundfile"]), "sox and soundfile are not available") - def test_3_load_and_save_is_identity_across_backend(self): - with self.subTest(): - self._test_3_load_and_save_is_identity_across_backend("sox", "soundfile") - with self.subTest(): - self._test_3_load_and_save_is_identity_across_backend("soundfile", "sox") - - def _test_3_load_and_save_is_identity_across_backend(self, backend1, backend2): - torchaudio.set_audio_backend(backend1) - input_path = os.path.join(self.test_dirpath, 'assets', 'sinewave.wav') - tensor1, sample_rate1 = torchaudio.load(input_path) - - output_path = os.path.join(self.test_dirpath, 'test.wav') - torchaudio.save(output_path, tensor1, sample_rate1) - - torchaudio.set_audio_backend(backend2) - tensor2, sample_rate2 = torchaudio.load(output_path) - - self.assertTrue(tensor1.allclose(tensor2)) - self.assertEqual(sample_rate1, sample_rate2) - os.unlink(output_path) - - def test_4_load_partial(self): - for backend in BACKENDS_MP3: - with self.subTest(): - torchaudio.set_audio_backend(backend) - self._test_4_load_partial() - - def _test_4_load_partial(self): - num_frames = 101 - offset = 201 - # load entire mono sinewave wav file, load a partial copy and then compare - input_sine_path = os.path.join(self.test_dirpath, 'assets', 'sinewave.wav') - x_sine_full, sr_sine = torchaudio.load(input_sine_path) - x_sine_part, _ = torchaudio.load(input_sine_path, num_frames=num_frames, offset=offset) - l1_error = x_sine_full[:, offset:(num_frames + offset)].sub(x_sine_part).abs().sum().item() - # test for the correct number of samples and that the correct portion was loaded - self.assertEqual(x_sine_part.size(1), num_frames) - self.assertEqual(l1_error, 0.) - # create a two channel version of this wavefile - x_2ch_sine = x_sine_full.repeat(1, 2) - out_2ch_sine_path = os.path.join(self.test_dirpath, 'assets', '2ch_sinewave.wav') - torchaudio.save(out_2ch_sine_path, x_2ch_sine, sr_sine) - x_2ch_sine_load, _ = torchaudio.load(out_2ch_sine_path, num_frames=num_frames, offset=offset) - os.unlink(out_2ch_sine_path) - l1_error = x_2ch_sine_load.sub(x_2ch_sine[:, offset:(offset + num_frames)]).abs().sum().item() - self.assertEqual(l1_error, 0.) - - # test with two channel mp3 - x_2ch_full, sr_2ch = torchaudio.load(self.test_filepath, normalization=True) - x_2ch_part, _ = torchaudio.load(self.test_filepath, normalization=True, num_frames=num_frames, offset=offset) - l1_error = x_2ch_full[:, offset:(offset + num_frames)].sub(x_2ch_part).abs().sum().item() - self.assertEqual(x_2ch_part.size(1), num_frames) - self.assertEqual(l1_error, 0.) - - # check behavior if number of samples would exceed file length - offset_ns = 300 - x_ns, _ = torchaudio.load(input_sine_path, num_frames=100000, offset=offset_ns) - self.assertEqual(x_ns.size(1), x_sine_full.size(1) - offset_ns) - - # check when offset is beyond the end of the file - with self.assertRaises(RuntimeError): - torchaudio.load(input_sine_path, offset=100000) - - def test_5_get_info(self): - for backend in BACKENDS: - with self.subTest(): - torchaudio.set_audio_backend(backend) - self._test_5_get_info() - - def _test_5_get_info(self): - input_path = os.path.join(self.test_dirpath, 'assets', 'sinewave.wav') - channels, samples, rate, precision = (1, 64000, 16000, 16) - si, ei = torchaudio.info(input_path) - self.assertEqual(si.channels, channels) - self.assertEqual(si.length, samples) - self.assertEqual(si.rate, rate) - self.assertEqual(ei.bits_per_sample, precision) diff --git a/test/torchaudio_unittest/backend/soundfile/common.py b/test/torchaudio_unittest/backend/soundfile/common.py index 8f991fb0f8..c6b014dd4c 100644 --- a/test/torchaudio_unittest/backend/soundfile/common.py +++ b/test/torchaudio_unittest/backend/soundfile/common.py @@ -32,3 +32,26 @@ def skipIfFormatNotSupported(fmt): def parameterize(*params): return parameterized.expand(list(itertools.product(*params)), name_func=name_func) + + +def fetch_wav_subtype(dtype, encoding, bits_per_sample): + subtype = { + (None, None): dtype2subtype(dtype), + (None, 8): "PCM_U8", + ('PCM_U', None): "PCM_U8", + ('PCM_U', 8): "PCM_U8", + ('PCM_S', None): "PCM_32", + ('PCM_S', 16): "PCM_16", + ('PCM_S', 32): "PCM_32", + ('PCM_F', None): "FLOAT", + ('PCM_F', 32): "FLOAT", + ('PCM_F', 64): "DOUBLE", + ('ULAW', None): "ULAW", + ('ULAW', 8): "ULAW", + ('ALAW', None): "ALAW", + ('ALAW', 8): "ALAW", + }.get((encoding, bits_per_sample)) + if subtype: + return subtype + raise ValueError( + f"wav does not support ({encoding}, {bits_per_sample}).") diff --git a/test/torchaudio_unittest/backend/soundfile/info_test.py b/test/torchaudio_unittest/backend/soundfile/info_test.py index 3b3f792281..b6b8722410 100644 --- a/test/torchaudio_unittest/backend/soundfile/info_test.py +++ b/test/torchaudio_unittest/backend/soundfile/info_test.py @@ -3,7 +3,7 @@ import tarfile import torch -from torchaudio.backend import _soundfile_backend as soundfile_backend +from torchaudio.backend import soundfile_backend from torchaudio._internal import module_utils as _mod_utils from torchaudio_unittest.common_utils import ( @@ -12,6 +12,7 @@ skipIfNoModule, get_wav_data, save_wav, + nested_params, ) from torchaudio_unittest.backend.common import ( get_bits_per_sample, @@ -77,7 +78,14 @@ def test_ogg(self, sample_rate, num_channels): assert info.bits_per_sample == 0 assert info.encoding == "VORBIS" - @parameterize([8000, 16000], [1, 2], [('PCM_24', 24), ('PCM_32', 32)]) + @nested_params( + [8000, 16000], + [1, 2], + [ + ('PCM_24', 24), + ('PCM_32', 32) + ], + ) @skipIfFormatNotSupported("NIST") def test_sphere(self, sample_rate, num_channels, subtype_and_bit_depth): """`soundfile_backend.info` can check sph file correctly""" diff --git a/test/torchaudio_unittest/backend/soundfile/load_test.py b/test/torchaudio_unittest/backend/soundfile/load_test.py index 399266de8f..0e3a240d26 100644 --- a/test/torchaudio_unittest/backend/soundfile/load_test.py +++ b/test/torchaudio_unittest/backend/soundfile/load_test.py @@ -4,7 +4,7 @@ import torch from torchaudio._internal import module_utils as _mod_utils -from torchaudio.backend import _soundfile_backend as soundfile_backend +from torchaudio.backend import soundfile_backend from parameterized import parameterized from torchaudio_unittest.common_utils import ( diff --git a/test/torchaudio_unittest/backend/soundfile/save_test.py b/test/torchaudio_unittest/backend/soundfile/save_test.py index 2f2741c303..e4e8c93631 100644 --- a/test/torchaudio_unittest/backend/soundfile/save_test.py +++ b/test/torchaudio_unittest/backend/soundfile/save_test.py @@ -2,7 +2,7 @@ from unittest.mock import patch from torchaudio._internal import module_utils as _mod_utils -from torchaudio.backend import _soundfile_backend as soundfile_backend +from torchaudio.backend import soundfile_backend from torchaudio_unittest.common_utils import ( TempDirMixin, @@ -10,38 +10,65 @@ skipIfNoModule, get_wav_data, load_wav, + nested_params, +) +from .common import ( + fetch_wav_subtype, + parameterize, + skipIfFormatNotSupported, ) -from .common import parameterize, dtype2subtype, skipIfFormatNotSupported if _mod_utils.is_module_available("soundfile"): import soundfile class MockedSaveTest(PytorchTestCase): - @parameterize( - ["float32", "int32", "int16", "uint8"], [8000, 16000], [1, 2], [False, True], + @nested_params( + ["float32", "int32", "int16", "uint8"], + [8000, 16000], + [1, 2], + [False, True], + [ + (None, None), + ('PCM_U', None), + ('PCM_U', 8), + ('PCM_S', None), + ('PCM_S', 16), + ('PCM_S', 32), + ('PCM_F', None), + ('PCM_F', 32), + ('PCM_F', 64), + ('ULAW', None), + ('ULAW', 8), + ('ALAW', None), + ('ALAW', 8), + ], ) @patch("soundfile.write") - def test_wav(self, dtype, sample_rate, num_channels, channels_first, mocked_write): + def test_wav(self, dtype, sample_rate, num_channels, channels_first, + enc_params, mocked_write): """soundfile_backend.save passes correct subtype to soundfile.write when WAV""" filepath = "foo.wav" input_tensor = get_wav_data( dtype, num_channels, num_frames=3 * sample_rate, - normalize=dtype == "flaot32", + normalize=dtype == "float32", channels_first=channels_first, ).t() + encoding, bits_per_sample = enc_params soundfile_backend.save( - filepath, input_tensor, sample_rate, channels_first=channels_first + filepath, input_tensor, sample_rate, channels_first=channels_first, + encoding=encoding, bits_per_sample=bits_per_sample ) # on +Py3.8 call_args.kwargs is more descreptive args = mocked_write.call_args[1] assert args["file"] == filepath assert args["samplerate"] == sample_rate - assert args["subtype"] == dtype2subtype(dtype) + assert args["subtype"] == fetch_wav_subtype( + dtype, encoding, bits_per_sample) assert args["format"] is None self.assertEqual( args["data"], input_tensor.t() if channels_first else input_tensor @@ -49,7 +76,8 @@ def test_wav(self, dtype, sample_rate, num_channels, channels_first, mocked_writ @patch("soundfile.write") def assert_non_wav( - self, fmt, dtype, sample_rate, num_channels, channels_first, mocked_write + self, fmt, dtype, sample_rate, num_channels, channels_first, mocked_write, + encoding=None, bits_per_sample=None, ): """soundfile_backend.save passes correct subtype and format to soundfile.write when SPHERE""" filepath = f"foo.{fmt}" @@ -63,39 +91,56 @@ def assert_non_wav( expected_data = input_tensor.t() if channels_first else input_tensor soundfile_backend.save( - filepath, input_tensor, sample_rate, channels_first=channels_first + filepath, input_tensor, sample_rate, channels_first, + encoding=encoding, bits_per_sample=bits_per_sample, ) # on +Py3.8 call_args.kwargs is more descreptive args = mocked_write.call_args[1] assert args["file"] == filepath assert args["samplerate"] == sample_rate - assert args["subtype"] is None if fmt in ["sph", "nist", "nis"]: assert args["format"] == "NIST" else: assert args["format"] is None self.assertEqual(args["data"], expected_data) - @parameterize( + @nested_params( ["sph", "nist", "nis"], ["int32", "int16"], [8000, 16000], [1, 2], [False, True], + [ + ('PCM_S', 8), + ('PCM_S', 16), + ('PCM_S', 24), + ('PCM_S', 32), + ('ULAW', 8), + ('ALAW', 8), + ('ALAW', 16), + ('ALAW', 24), + ('ALAW', 32), + ], ) - def test_sph(self, fmt, dtype, sample_rate, num_channels, channels_first): + def test_sph(self, fmt, dtype, sample_rate, num_channels, channels_first, enc_params): """soundfile_backend.save passes default format and subtype (None-s) to soundfile.write when not WAV""" - self.assert_non_wav(fmt, dtype, sample_rate, num_channels, channels_first) + encoding, bits_per_sample = enc_params + self.assert_non_wav(fmt, dtype, sample_rate, num_channels, + channels_first, encoding=encoding, + bits_per_sample=bits_per_sample) @parameterize( ["int32", "int16"], [8000, 16000], [1, 2], [False, True], + [8, 16, 24], ) - def test_flac(self, dtype, sample_rate, num_channels, channels_first): + def test_flac(self, dtype, sample_rate, num_channels, + channels_first, bits_per_sample): """soundfile_backend.save passes default format and subtype (None-s) to soundfile.write when not WAV""" - self.assert_non_wav("flac", dtype, sample_rate, num_channels, channels_first) + self.assert_non_wav("flac", dtype, sample_rate, num_channels, + channels_first, bits_per_sample=bits_per_sample) @parameterize( ["int32", "int16"], [8000, 16000], [1, 2], [False, True], @@ -199,7 +244,7 @@ def test_ogg(self, sample_rate, num_channels): class TestSaveParams(TempDirMixin, PytorchTestCase): """Test the correctness of optional parameters of `soundfile_backend.save`""" - @parameterize([(True,), (False,)]) + @parameterize([True, False]) def test_channels_first(self, channels_first): """channels_first swaps axes""" path = self.get_temp_path("data.wav") @@ -228,7 +273,7 @@ def _test_fileobj(self, ext): found, sr = soundfile.read(fileobj, dtype='float32') assert sr == sample_rate - self.assertEqual(expected, found) + self.assertEqual(expected, found, atol=1e-4, rtol=1e-8) def test_fileobj_wav(self): """Saving audio via file-like object works""" diff --git a/test/torchaudio_unittest/backend/sox_io/common.py b/test/torchaudio_unittest/backend/sox_io/common.py index eb85937236..c2538b2bc4 100644 --- a/test/torchaudio_unittest/backend/sox_io/common.py +++ b/test/torchaudio_unittest/backend/sox_io/common.py @@ -1,2 +1,14 @@ def name_func(func, _, params): return f'{func.__name__}_{"_".join(str(arg) for arg in params.args)}' + + +def get_enc_params(dtype): + if dtype == 'float32': + return 'PCM_F', 32 + if dtype == 'int32': + return 'PCM_S', 32 + if dtype == 'int16': + return 'PCM_S', 16 + if dtype == 'uint8': + return 'PCM_U', 8 + raise ValueError(f'Unexpected dtype: {dtype}') diff --git a/test/torchaudio_unittest/backend/sox_io/info_test.py b/test/torchaudio_unittest/backend/sox_io/info_test.py index a2a93648a1..d459061eee 100644 --- a/test/torchaudio_unittest/backend/sox_io/info_test.py +++ b/test/torchaudio_unittest/backend/sox_io/info_test.py @@ -16,8 +16,8 @@ HttpServerMixin, PytorchTestCase, skipIfNoExec, - skipIfNoExtension, skipIfNoModule, + skipIfNoSox, get_asset_path, get_wav_data, save_wav, @@ -33,7 +33,7 @@ @skipIfNoExec('sox') -@skipIfNoExtension +@skipIfNoSox class TestInfo(TempDirMixin, PytorchTestCase): @parameterized.expand(list(itertools.product( ['float32', 'int32', 'int16', 'uint8'], @@ -205,7 +205,7 @@ def test_ulaw(self): assert info.encoding == "ULAW" def test_alaw(self): - """`sox_io_backend.info` can check ulaw file correctly""" + """`sox_io_backend.info` can check alaw file correctly""" duration = 1 num_channels = 1 sample_rate = 8000 @@ -221,8 +221,39 @@ def test_alaw(self): assert info.bits_per_sample == 8 assert info.encoding == "ALAW" + def test_gsm(self): + """`sox_io_backend.info` can check gsm file correctly""" + duration = 1 + num_channels = 1 + sample_rate = 8000 + path = self.get_temp_path('data.gsm') + sox_utils.gen_audio_file( + path, sample_rate=sample_rate, num_channels=num_channels, + duration=duration) + info = sox_io_backend.info(path) + assert info.sample_rate == sample_rate + assert info.num_channels == num_channels + assert info.bits_per_sample == 0 + assert info.encoding == "GSM" + + def test_htk(self): + """`sox_io_backend.info` can check HTK file correctly""" + duration = 1 + num_channels = 1 + sample_rate = 8000 + path = self.get_temp_path('data.htk') + sox_utils.gen_audio_file( + path, sample_rate=sample_rate, num_channels=num_channels, + bit_depth=16, duration=duration) + info = sox_io_backend.info(path) + assert info.sample_rate == sample_rate + assert info.num_frames == sample_rate * duration + assert info.num_channels == num_channels + assert info.bits_per_sample == 16 + assert info.encoding == "PCM_S" + -@skipIfNoExtension +@skipIfNoSox class TestInfoOpus(PytorchTestCase): @parameterized.expand(list(itertools.product( ['96k'], @@ -240,7 +271,7 @@ def test_opus(self, bitrate, num_channels, compression_level): assert info.encoding == "OPUS" -@skipIfNoExtension +@skipIfNoSox class TestLoadWithoutExtension(PytorchTestCase): def test_mp3(self): """Providing `format` allows to read mp3 without extension @@ -275,7 +306,7 @@ def _gen_file(self, ext, dtype, sample_rate, num_channels, num_frames): return path -@skipIfNoExtension +@skipIfNoSox @skipIfNoExec('sox') class TestFileObject(FileObjTestBase, PytorchTestCase): def _query_fileobj(self, ext, dtype, sample_rate, num_channels, num_frames): @@ -407,7 +438,7 @@ def test_tarfile(self, ext, dtype): assert sinfo.encoding == get_encoding(ext, dtype) -@skipIfNoExtension +@skipIfNoSox @skipIfNoExec('sox') @skipIfNoModule("requests") class TestFileObjectHttp(HttpServerMixin, FileObjTestBase, PytorchTestCase): diff --git a/test/torchaudio_unittest/backend/sox_io/load_test.py b/test/torchaudio_unittest/backend/sox_io/load_test.py index f2a514ea61..f8d06a4da9 100644 --- a/test/torchaudio_unittest/backend/sox_io/load_test.py +++ b/test/torchaudio_unittest/backend/sox_io/load_test.py @@ -11,8 +11,8 @@ HttpServerMixin, PytorchTestCase, skipIfNoExec, - skipIfNoExtension, skipIfNoModule, + skipIfNoSox, get_asset_path, get_wav_data, load_wav, @@ -29,178 +29,80 @@ class LoadTestBase(TempDirMixin, PytorchTestCase): - def assert_wav(self, dtype, sample_rate, num_channels, normalize, duration): - """`sox_io_backend.load` can load wav format correctly. - - Wav data loaded with sox_io backend should match those with scipy - """ - path = self.get_temp_path('reference.wav') - data = get_wav_data(dtype, num_channels, normalize=normalize, num_frames=duration * sample_rate) - save_wav(path, data, sample_rate) - expected = load_wav(path, normalize=normalize)[0] - data, sr = sox_io_backend.load(path, normalize=normalize) - assert sr == sample_rate - self.assertEqual(data, expected) - - def assert_mp3(self, sample_rate, num_channels, bit_rate, duration): - """`sox_io_backend.load` can load mp3 format. - - mp3 encoding introduces delay and boundary effects so - we create reference wav file from mp3 + def assert_format( + self, + format: str, + sample_rate: float, + num_channels: int, + compression: float = None, + bit_depth: int = None, + duration: float = 1, + normalize: bool = True, + encoding: str = None, + atol: float = 4e-05, + rtol: float = 1.3e-06, + ): + """`sox_io_backend.load` can load given format correctly. + + file encodings introduce delay and boundary effects so + we create a reference wav file from the original file format x | - | 1. Generate mp3 with Sox + | 1. Generate given format with Sox | v 2. Convert to wav with Sox - mp3 ------------------------------> wav + given format ----------------------> wav | | - | 3. Load with torchaudio | 4. Load with scipy + | 3. Load with torchaudio | 4. Load with scipy | | v v tensor ----------> x <----------- tensor 5. Compare Underlying assumptions are; - i. Conversion of mp3 to wav with Sox preserves data. + i. Conversion of given format to wav with Sox preserves data. ii. Loading wav file with scipy is correct. - By combining i & ii, step 2. and 4. allows to load reference mp3 data - without using torchaudio - """ - path = self.get_temp_path('1.original.mp3') - ref_path = self.get_temp_path('2.reference.wav') - - # 1. Generate mp3 with sox - sox_utils.gen_audio_file( - path, sample_rate, num_channels, - compression=bit_rate, duration=duration) - # 2. Convert to wav with sox - sox_utils.convert_audio_file(path, ref_path) - # 3. Load mp3 with torchaudio - data, sr = sox_io_backend.load(path) - # 4. Load wav with scipy - data_ref = load_wav(ref_path)[0] - # 5. Compare - assert sr == sample_rate - self.assertEqual(data, data_ref, atol=3e-03, rtol=1.3e-06) - - def assert_flac(self, sample_rate, num_channels, compression_level, duration): - """`sox_io_backend.load` can load flac format. - - This test takes the same strategy as mp3 to compare the result - """ - path = self.get_temp_path('1.original.flac') - ref_path = self.get_temp_path('2.reference.wav') - - # 1. Generate flac with sox - sox_utils.gen_audio_file( - path, sample_rate, num_channels, - compression=compression_level, bit_depth=16, duration=duration) - # 2. Convert to wav with sox - sox_utils.convert_audio_file(path, ref_path) - # 3. Load flac with torchaudio - data, sr = sox_io_backend.load(path) - # 4. Load wav with scipy - data_ref = load_wav(ref_path)[0] - # 5. Compare - assert sr == sample_rate - self.assertEqual(data, data_ref, atol=4e-05, rtol=1.3e-06) - - def assert_vorbis(self, sample_rate, num_channels, quality_level, duration): - """`sox_io_backend.load` can load vorbis format. - - This test takes the same strategy as mp3 to compare the result - """ - path = self.get_temp_path('1.original.vorbis') - ref_path = self.get_temp_path('2.reference.wav') - - # 1. Generate vorbis with sox - sox_utils.gen_audio_file( - path, sample_rate, num_channels, - compression=quality_level, bit_depth=16, duration=duration) - # 2. Convert to wav with sox - sox_utils.convert_audio_file(path, ref_path) - # 3. Load vorbis with torchaudio - data, sr = sox_io_backend.load(path) - # 4. Load wav with scipy - data_ref = load_wav(ref_path)[0] - # 5. Compare - assert sr == sample_rate - self.assertEqual(data, data_ref, atol=4e-05, rtol=1.3e-06) - - def assert_sphere(self, sample_rate, num_channels, duration): - """`sox_io_backend.load` can load sph format. - - This test takes the same strategy as mp3 to compare the result + By combining i & ii, step 2. and 4. allows to load reference given format + data without using torchaudio """ - path = self.get_temp_path('1.original.sph') - ref_path = self.get_temp_path('2.reference.wav') - # 1. Generate sph with sox - sox_utils.gen_audio_file( - path, sample_rate, num_channels, - bit_depth=32, duration=duration) - # 2. Convert to wav with sox - sox_utils.convert_audio_file(path, ref_path) - # 3. Load sph with torchaudio - data, sr = sox_io_backend.load(path) - # 4. Load wav with scipy - data_ref = load_wav(ref_path)[0] - # 5. Compare - assert sr == sample_rate - self.assertEqual(data, data_ref, atol=4e-05, rtol=1.3e-06) - - def assert_amb(self, dtype, sample_rate, num_channels, normalize, duration): - """`sox_io_backend.load` can load amb format. - - This test takes the same strategy as mp3 to compare the result - """ - path = self.get_temp_path('1.original.amb') + path = self.get_temp_path(f'1.original.{format}') ref_path = self.get_temp_path('2.reference.wav') - # 1. Generate amb with sox + # 1. Generate the given format with sox sox_utils.gen_audio_file( - path, sample_rate, num_channels, - encoding=sox_utils.get_encoding(dtype), - bit_depth=sox_utils.get_bit_depth(dtype), duration=duration) + path, sample_rate, num_channels, encoding=encoding, + compression=compression, bit_depth=bit_depth, duration=duration, + ) # 2. Convert to wav with sox - sox_utils.convert_audio_file(path, ref_path) - # 3. Load amb with torchaudio + wav_bit_depth = 32 if bit_depth == 24 else None # for 24-bit wav + sox_utils.convert_audio_file(path, ref_path, bit_depth=wav_bit_depth) + # 3. Load the given format with torchaudio data, sr = sox_io_backend.load(path, normalize=normalize) # 4. Load wav with scipy data_ref = load_wav(ref_path, normalize=normalize)[0] # 5. Compare assert sr == sample_rate - self.assertEqual(data, data_ref, atol=4e-05, rtol=1.3e-06) + self.assertEqual(data, data_ref, atol=atol, rtol=rtol) - def assert_amr_nb(self, duration): - """`sox_io_backend.load` can load amr-nb format. + def assert_wav(self, dtype, sample_rate, num_channels, normalize, duration): + """`sox_io_backend.load` can load wav format correctly. - This test takes the same strategy as mp3 to compare the result + Wav data loaded with sox_io backend should match those with scipy """ - sample_rate = 8000 - num_channels = 1 - path = self.get_temp_path('1.original.amr-nb') - ref_path = self.get_temp_path('2.reference.wav') - - # 1. Generate amr-nb with sox - sox_utils.gen_audio_file( - path, sample_rate, num_channels, - bit_depth=32, duration=duration) - # 2. Convert to wav with sox - sox_utils.convert_audio_file(path, ref_path) - # 3. Load amr-nb with torchaudio - data, sr = sox_io_backend.load(path) - # 4. Load wav with scipy - data_ref = load_wav(ref_path)[0] - # 5. Compare + path = self.get_temp_path('reference.wav') + data = get_wav_data(dtype, num_channels, normalize=normalize, num_frames=duration * sample_rate) + save_wav(path, data, sample_rate) + expected = load_wav(path, normalize=normalize)[0] + data, sr = sox_io_backend.load(path, normalize=normalize) assert sr == sample_rate - self.assertEqual(data, data_ref, atol=4e-05, rtol=1.3e-06) + self.assertEqual(data, expected) @skipIfNoExec('sox') -@skipIfNoExtension +@skipIfNoSox class TestLoad(LoadTestBase): """Test the correctness of `sox_io_backend.load` for various formats""" @parameterized.expand(list(itertools.product( @@ -213,6 +115,15 @@ def test_wav(self, dtype, sample_rate, num_channels, normalize): """`sox_io_backend.load` can load wav format correctly.""" self.assert_wav(dtype, sample_rate, num_channels, normalize, duration=1) + @parameterized.expand(list(itertools.product( + [8000, 16000], + [1, 2], + [False, True], + )), name_func=name_func) + def test_24bit_wav(self, sample_rate, num_channels, normalize): + """`sox_io_backend.load` can load 24bit wav format correctly. Corectly casts it to ``int32`` tensor dtype.""" + self.assert_format("wav", sample_rate, num_channels, bit_depth=24, normalize=normalize, duration=1) + @parameterized.expand(list(itertools.product( ['int16'], [16000], @@ -241,7 +152,7 @@ def test_multiple_channels(self, dtype, num_channels): )), name_func=name_func) def test_mp3(self, sample_rate, num_channels, bit_rate): """`sox_io_backend.load` can load mp3 format correctly.""" - self.assert_mp3(sample_rate, num_channels, bit_rate, duration=1) + self.assert_format("mp3", sample_rate, num_channels, compression=bit_rate, duration=1, atol=5e-05) @parameterized.expand(list(itertools.product( [16000], @@ -251,7 +162,7 @@ def test_mp3(self, sample_rate, num_channels, bit_rate): def test_mp3_large(self, sample_rate, num_channels, bit_rate): """`sox_io_backend.load` can load large mp3 file correctly.""" two_hours = 2 * 60 * 60 - self.assert_mp3(sample_rate, num_channels, bit_rate, two_hours) + self.assert_format("mp3", sample_rate, num_channels, compression=bit_rate, duration=two_hours, atol=5e-05) @parameterized.expand(list(itertools.product( [8000, 16000], @@ -260,7 +171,7 @@ def test_mp3_large(self, sample_rate, num_channels, bit_rate): )), name_func=name_func) def test_flac(self, sample_rate, num_channels, compression_level): """`sox_io_backend.load` can load flac format correctly.""" - self.assert_flac(sample_rate, num_channels, compression_level, duration=1) + self.assert_format("flac", sample_rate, num_channels, compression=compression_level, bit_depth=16, duration=1) @parameterized.expand(list(itertools.product( [16000], @@ -270,7 +181,8 @@ def test_flac(self, sample_rate, num_channels, compression_level): def test_flac_large(self, sample_rate, num_channels, compression_level): """`sox_io_backend.load` can load large flac file correctly.""" two_hours = 2 * 60 * 60 - self.assert_flac(sample_rate, num_channels, compression_level, two_hours) + self.assert_format( + "flac", sample_rate, num_channels, compression=compression_level, bit_depth=16, duration=two_hours) @parameterized.expand(list(itertools.product( [8000, 16000], @@ -279,7 +191,7 @@ def test_flac_large(self, sample_rate, num_channels, compression_level): )), name_func=name_func) def test_vorbis(self, sample_rate, num_channels, quality_level): """`sox_io_backend.load` can load vorbis format correctly.""" - self.assert_vorbis(sample_rate, num_channels, quality_level, duration=1) + self.assert_format("vorbis", sample_rate, num_channels, compression=quality_level, bit_depth=16, duration=1) @parameterized.expand(list(itertools.product( [16000], @@ -289,7 +201,8 @@ def test_vorbis(self, sample_rate, num_channels, quality_level): def test_vorbis_large(self, sample_rate, num_channels, quality_level): """`sox_io_backend.load` can load large vorbis file correctly.""" two_hours = 2 * 60 * 60 - self.assert_vorbis(sample_rate, num_channels, quality_level, two_hours) + self.assert_format( + "vorbis", sample_rate, num_channels, compression=quality_level, bit_depth=16, duration=two_hours) @parameterized.expand(list(itertools.product( ['96k'], @@ -314,7 +227,7 @@ def test_opus(self, bitrate, num_channels, compression_level): )), name_func=name_func) def test_sphere(self, sample_rate, num_channels): """`sox_io_backend.load` can load sph format correctly.""" - self.assert_sphere(sample_rate, num_channels, duration=1) + self.assert_format("sph", sample_rate, num_channels, bit_depth=32, duration=1) @parameterized.expand(list(itertools.product( ['float32', 'int32', 'int16'], @@ -323,16 +236,19 @@ def test_sphere(self, sample_rate, num_channels): [False, True], )), name_func=name_func) def test_amb(self, dtype, sample_rate, num_channels, normalize): - """`sox_io_backend.load` can load sph format correctly.""" - self.assert_amb(dtype, sample_rate, num_channels, normalize, duration=1) + """`sox_io_backend.load` can load amb format correctly.""" + bit_depth = sox_utils.get_bit_depth(dtype) + encoding = sox_utils.get_encoding(dtype) + self.assert_format( + "amb", sample_rate, num_channels, bit_depth=bit_depth, duration=1, encoding=encoding, normalize=normalize) def test_amr_nb(self): """`sox_io_backend.load` can load amr_nb format correctly.""" - self.assert_amr_nb(duration=1) + self.assert_format("amr-nb", sample_rate=8000, num_channels=1, bit_depth=32, duration=1) @skipIfNoExec('sox') -@skipIfNoExtension +@skipIfNoSox class TestLoadParams(TempDirMixin, PytorchTestCase): """Test the correctness of frame parameters of `sox_io_backend.load`""" original = None @@ -363,7 +279,7 @@ def test_channels_first(self, channels_first): self.assertEqual(found, expected) -@skipIfNoExtension +@skipIfNoSox class TestLoadWithoutExtension(PytorchTestCase): def test_mp3(self): """Providing format allows to read mp3 without extension @@ -393,7 +309,7 @@ def read(self, n): return ret -@skipIfNoExtension +@skipIfNoSox @skipIfNoExec('sox') class TestFileObject(TempDirMixin, PytorchTestCase): """ @@ -553,7 +469,7 @@ def test_tarfile(self, ext, compression): self.assertEqual(expected, found) -@skipIfNoExtension +@skipIfNoSox @skipIfNoExec('sox') @skipIfNoModule("requests") class TestFileObjectHttp(HttpServerMixin, PytorchTestCase): diff --git a/test/torchaudio_unittest/backend/sox_io/roundtrip_test.py b/test/torchaudio_unittest/backend/sox_io/roundtrip_test.py index 85aa3019e0..32c920eea1 100644 --- a/test/torchaudio_unittest/backend/sox_io/roundtrip_test.py +++ b/test/torchaudio_unittest/backend/sox_io/roundtrip_test.py @@ -7,16 +7,17 @@ TempDirMixin, PytorchTestCase, skipIfNoExec, - skipIfNoExtension, + skipIfNoSox, get_wav_data, ) from .common import ( name_func, + get_enc_params, ) @skipIfNoExec('sox') -@skipIfNoExtension +@skipIfNoSox class TestRoundTripIO(TempDirMixin, PytorchTestCase): """save/load round trip should not degrade data for lossless formats""" @parameterized.expand(list(itertools.product( @@ -27,10 +28,11 @@ class TestRoundTripIO(TempDirMixin, PytorchTestCase): def test_wav(self, dtype, sample_rate, num_channels): """save/load round trip should not degrade data for wav formats""" original = get_wav_data(dtype, num_channels, normalize=False) + enc, bps = get_enc_params(dtype) data = original for i in range(10): path = self.get_temp_path(f'{i}.wav') - sox_io_backend.save(path, data, sample_rate) + sox_io_backend.save(path, data, sample_rate, encoding=enc, bits_per_sample=bps) data, sr = sox_io_backend.load(path, normalize=False) assert sr == sample_rate self.assertEqual(original, data) diff --git a/test/torchaudio_unittest/backend/sox_io/save_test.py b/test/torchaudio_unittest/backend/sox_io/save_test.py index fc378f9c70..4356972342 100644 --- a/test/torchaudio_unittest/backend/sox_io/save_test.py +++ b/test/torchaudio_unittest/backend/sox_io/save_test.py @@ -1,53 +1,79 @@ import io -import itertools +import unittest -import torch from torchaudio.backend import sox_io_backend from parameterized import parameterized from torchaudio_unittest.common_utils import ( TempDirMixin, + TorchaudioTestCase, PytorchTestCase, skipIfNoExec, - skipIfNoExtension, + skipIfNoSox, get_wav_data, load_wav, save_wav, sox_utils, + nested_params, ) from .common import ( name_func, + get_enc_params, ) -class SaveTestBase(TempDirMixin, PytorchTestCase): - def assert_wav(self, dtype, sample_rate, num_channels, num_frames): - """`sox_io_backend.save` can save wav format.""" - path = self.get_temp_path('data.wav') - expected = get_wav_data(dtype, num_channels, num_frames=num_frames) - sox_io_backend.save(path, expected, sample_rate, dtype=None) - found, sr = load_wav(path) - assert sample_rate == sr - self.assertEqual(found, expected) - - def assert_mp3(self, sample_rate, num_channels, bit_rate, duration): - """`sox_io_backend.save` can save mp3 format. - - mp3 encoding introduces delay and boundary effects so - we convert the resulting mp3 to wav and compare the results there - - | - | 1. Generate original wav file with SciPy +def _get_sox_encoding(encoding): + encodings = { + 'PCM_F': 'floating-point', + 'PCM_S': 'signed-integer', + 'PCM_U': 'unsigned-integer', + 'ULAW': 'u-law', + 'ALAW': 'a-law', + } + return encodings.get(encoding) + + +class SaveTestBase(TempDirMixin, TorchaudioTestCase): + def assert_save_consistency( + self, + format: str, + *, + compression: float = None, + encoding: str = None, + bits_per_sample: int = None, + sample_rate: float = 8000, + num_channels: int = 2, + num_frames: float = 3 * 8000, + src_dtype: str = 'int32', + test_mode: str = "path", + ): + """`save` function produces file that is comparable with `sox` command + + To compare that the file produced by `save` function agains the file produced by + the equivalent `sox` command, we need to load both files. + But there are many formats that cannot be opened with common Python modules (like + SciPy). + So we use `sox` command to prepare the original data and convert the saved files + into a format that SciPy can read (PCM wav). + The following diagram illustrates this process. The difference is 2.1. and 3.1. + + This assumes that + - loading data with SciPy preserves the data well. + - converting the resulting files into WAV format with `sox` preserve the data well. + + x + | 1. Generate source wav file with SciPy | v -------------- wav ---------------- | | - | 2.1. load with scipy | 3.1. Convert to mp3 with Sox - | then save with torchaudio | + | 2.1. load with scipy | 3.1. Convert to the target + | then save it into the target | format depth with sox + | format with torchaudio | v v - mp3 mp3 + target format target format | | - | 2.2. Convert to wav with Sox | 3.2. Convert to wav with Sox + | 2.2. Convert to wav with sox | 3.2. Convert to wav with sox | | v v wav wav @@ -58,463 +84,306 @@ def assert_mp3(self, sample_rate, num_channels, bit_rate, duration): tensor -------> compare <--------- tensor """ - src_path = self.get_temp_path('1.reference.wav') - mp3_path = self.get_temp_path('2.1.torchaudio.mp3') - wav_path = self.get_temp_path('2.2.torchaudio.wav') - mp3_path_sox = self.get_temp_path('3.1.sox.mp3') - wav_path_sox = self.get_temp_path('3.2.sox.wav') + cmp_encoding = 'floating-point' + cmp_bit_depth = 32 - # 1. Generate original wav - data = get_wav_data('float32', num_channels, normalize=True, num_frames=duration * sample_rate) - save_wav(src_path, data, sample_rate) - # 2.1. Convert the original wav to mp3 with torchaudio - sox_io_backend.save( - mp3_path, load_wav(src_path)[0], sample_rate, compression=bit_rate, dtype=None) - # 2.2. Convert the mp3 to wav with Sox - sox_utils.convert_audio_file(mp3_path, wav_path) - # 2.3. Load - found = load_wav(wav_path)[0] - - # 3.1. Convert the original wav to mp3 with SoX - sox_utils.convert_audio_file(src_path, mp3_path_sox, compression=bit_rate) - # 3.2. Convert the mp3 to wav with Sox - sox_utils.convert_audio_file(mp3_path_sox, wav_path_sox) - # 3.3. Load - expected = load_wav(wav_path_sox)[0] - - self.assertEqual(found, expected) - - def assert_flac(self, sample_rate, num_channels, compression_level, duration): - """`sox_io_backend.save` can save flac format. - - This test takes the same strategy as mp3 to compare the result - """ - src_path = self.get_temp_path('1.reference.wav') - flc_path = self.get_temp_path('2.1.torchaudio.flac') - wav_path = self.get_temp_path('2.2.torchaudio.wav') - flc_path_sox = self.get_temp_path('3.1.sox.flac') - wav_path_sox = self.get_temp_path('3.2.sox.wav') + src_path = self.get_temp_path('1.source.wav') + tgt_path = self.get_temp_path(f'2.1.torchaudio.{format}') + tst_path = self.get_temp_path('2.2.result.wav') + sox_path = self.get_temp_path(f'3.1.sox.{format}') + ref_path = self.get_temp_path('3.2.ref.wav') # 1. Generate original wav - data = get_wav_data('float32', num_channels, normalize=True, num_frames=duration * sample_rate) + data = get_wav_data(src_dtype, num_channels, normalize=False, num_frames=num_frames) save_wav(src_path, data, sample_rate) - # 2.1. Convert the original wav to flac with torchaudio - sox_io_backend.save( - flc_path, load_wav(src_path)[0], sample_rate, compression=compression_level, dtype=None) - # 2.2. Convert the flac to wav with Sox - # converting to 32 bit because flac file has 24 bit depth which scipy cannot handle. - sox_utils.convert_audio_file(flc_path, wav_path, bit_depth=32) - # 2.3. Load - found = load_wav(wav_path)[0] - - # 3.1. Convert the original wav to flac with SoX - sox_utils.convert_audio_file(src_path, flc_path_sox, compression=compression_level) - # 3.2. Convert the flac to wav with Sox - # converting to 32 bit because flac file has 24 bit depth which scipy cannot handle. - sox_utils.convert_audio_file(flc_path_sox, wav_path_sox, bit_depth=32) - # 3.3. Load - expected = load_wav(wav_path_sox)[0] - - self.assertEqual(found, expected) - - def _assert_vorbis(self, sample_rate, num_channels, quality_level, duration): - """`sox_io_backend.save` can save vorbis format. - - This test takes the same strategy as mp3 to compare the result - """ - src_path = self.get_temp_path('1.reference.wav') - vbs_path = self.get_temp_path('2.1.torchaudio.vorbis') - wav_path = self.get_temp_path('2.2.torchaudio.wav') - vbs_path_sox = self.get_temp_path('3.1.sox.vorbis') - wav_path_sox = self.get_temp_path('3.2.sox.wav') - # 1. Generate original wav - data = get_wav_data('int16', num_channels, normalize=False, num_frames=duration * sample_rate) - save_wav(src_path, data, sample_rate) - # 2.1. Convert the original wav to vorbis with torchaudio - sox_io_backend.save( - vbs_path, load_wav(src_path)[0], sample_rate, compression=quality_level, dtype=None) - # 2.2. Convert the vorbis to wav with Sox - sox_utils.convert_audio_file(vbs_path, wav_path) - # 2.3. Load - found = load_wav(wav_path)[0] - - # 3.1. Convert the original wav to vorbis with SoX - sox_utils.convert_audio_file(src_path, vbs_path_sox, compression=quality_level) - # 3.2. Convert the vorbis to wav with Sox - sox_utils.convert_audio_file(vbs_path_sox, wav_path_sox) - # 3.3. Load - expected = load_wav(wav_path_sox)[0] - - # sox's vorbis encoding has some random boundary effect, which cause small number of - # samples yields higher descrepency than the others. - # so we allow small portions of data to be outside of absolute torelance. - # make sure to pass somewhat long duration - atol = 1.0e-4 - max_failure_allowed = 0.01 # this percent of samples are allowed to outside of atol. - failure_ratio = ((found - expected).abs() > atol).sum().item() / found.numel() - if failure_ratio > max_failure_allowed: - # it's failed and this will give a better error message. - self.assertEqual(found, expected, atol=atol, rtol=1.3e-6) - - def assert_vorbis(self, *args, **kwargs): - # sox's vorbis encoding has some randomness, so we run tests multiple time - max_retry = 5 - error = None - for _ in range(max_retry): - try: - self._assert_vorbis(*args, **kwargs) - break - except AssertionError as e: - error = e + # 2.1. Convert the original wav to target format with torchaudio + data = load_wav(src_path, normalize=False)[0] + if test_mode == "path": + sox_io_backend.save( + tgt_path, data, sample_rate, + compression=compression, encoding=encoding, bits_per_sample=bits_per_sample) + elif test_mode == "fileobj": + with open(tgt_path, 'bw') as file_: + sox_io_backend.save( + file_, data, sample_rate, + format=format, compression=compression, + encoding=encoding, bits_per_sample=bits_per_sample) + elif test_mode == "bytesio": + file_ = io.BytesIO() + sox_io_backend.save( + file_, data, sample_rate, + format=format, compression=compression, + encoding=encoding, bits_per_sample=bits_per_sample) + file_.seek(0) + with open(tgt_path, 'bw') as f: + f.write(file_.read()) else: - raise error - - def assert_sphere(self, sample_rate, num_channels, duration): - """`sox_io_backend.save` can save sph format. - - This test takes the same strategy as mp3 to compare the result - """ - src_path = self.get_temp_path('1.reference.wav') - flc_path = self.get_temp_path('2.1.torchaudio.sph') - wav_path = self.get_temp_path('2.2.torchaudio.wav') - flc_path_sox = self.get_temp_path('3.1.sox.sph') - wav_path_sox = self.get_temp_path('3.2.sox.wav') - - # 1. Generate original wav - data = get_wav_data('float32', num_channels, normalize=True, num_frames=duration * sample_rate) - save_wav(src_path, data, sample_rate) - # 2.1. Convert the original wav to sph with torchaudio - sox_io_backend.save(flc_path, load_wav(src_path)[0], sample_rate, dtype=None) - # 2.2. Convert the sph to wav with Sox - # converting to 32 bit because sph file has 24 bit depth which scipy cannot handle. - sox_utils.convert_audio_file(flc_path, wav_path, bit_depth=32) - # 2.3. Load - found = load_wav(wav_path)[0] - - # 3.1. Convert the original wav to sph with SoX - sox_utils.convert_audio_file(src_path, flc_path_sox) - # 3.2. Convert the sph to wav with Sox - # converting to 32 bit because sph file has 24 bit depth which scipy cannot handle. - sox_utils.convert_audio_file(flc_path_sox, wav_path_sox, bit_depth=32) - # 3.3. Load - expected = load_wav(wav_path_sox)[0] + raise ValueError(f"Unexpected test mode: {test_mode}") + # 2.2. Convert the target format to wav with sox + sox_utils.convert_audio_file( + tgt_path, tst_path, encoding=cmp_encoding, bit_depth=cmp_bit_depth) + # 2.3. Load with SciPy + found = load_wav(tst_path, normalize=False)[0] + + # 3.1. Convert the original wav to target format with sox + sox_encoding = _get_sox_encoding(encoding) + sox_utils.convert_audio_file( + src_path, sox_path, + compression=compression, encoding=sox_encoding, bit_depth=bits_per_sample) + # 3.2. Convert the target format to wav with sox + sox_utils.convert_audio_file( + sox_path, ref_path, encoding=cmp_encoding, bit_depth=cmp_bit_depth) + # 3.3. Load with SciPy + expected = load_wav(ref_path, normalize=False)[0] self.assertEqual(found, expected) - def assert_amb(self, dtype, sample_rate, num_channels, duration): - """`sox_io_backend.save` can save amb format. - - This test takes the same strategy as mp3 to compare the result - """ - src_path = self.get_temp_path('1.reference.wav') - amb_path = self.get_temp_path('2.1.torchaudio.amb') - wav_path = self.get_temp_path('2.2.torchaudio.wav') - amb_path_sox = self.get_temp_path('3.1.sox.amb') - wav_path_sox = self.get_temp_path('3.2.sox.wav') - - # 1. Generate original wav - data = get_wav_data(dtype, num_channels, normalize=False, num_frames=duration * sample_rate) - save_wav(src_path, data, sample_rate) - # 2.1. Convert the original wav to amb with torchaudio - sox_io_backend.save(amb_path, load_wav(src_path, normalize=False)[0], sample_rate, dtype=None) - # 2.2. Convert the amb to wav with Sox - sox_utils.convert_audio_file(amb_path, wav_path) - # 2.3. Load - found = load_wav(wav_path)[0] - - # 3.1. Convert the original wav to amb with SoX - sox_utils.convert_audio_file(src_path, amb_path_sox) - # 3.2. Convert the amb to wav with Sox - sox_utils.convert_audio_file(amb_path_sox, wav_path_sox) - # 3.3. Load - expected = load_wav(wav_path_sox)[0] - - self.assertEqual(found, expected) - def assert_amr_nb(self, duration): - """`sox_io_backend.save` can save amr_nb format. +@skipIfNoExec('sox') +@skipIfNoSox +class SaveTest(SaveTestBase): + @nested_params( + ["path", "fileobj", "bytesio"], + [ + ('PCM_U', 8), + ('PCM_S', 16), + ('PCM_S', 32), + ('PCM_F', 32), + ('PCM_F', 64), + ('ULAW', 8), + ('ALAW', 8), + ], + ) + def test_save_wav(self, test_mode, enc_params): + encoding, bits_per_sample = enc_params + self.assert_save_consistency( + "wav", encoding=encoding, bits_per_sample=bits_per_sample, test_mode=test_mode) + + @nested_params( + ["path", "fileobj", "bytesio"], + [ + ('float32', ), + ('int32', ), + ('int16', ), + ('uint8', ), + ], + ) + def test_save_wav_dtype(self, test_mode, params): + dtype, = params + self.assert_save_consistency( + "wav", src_dtype=dtype, test_mode=test_mode) + + @nested_params( + ["path", "fileobj", "bytesio"], + [ + None, + -4.2, + -0.2, + 0, + 0.2, + 96, + 128, + 160, + 192, + 224, + 256, + 320, + ], + ) + def test_save_mp3(self, test_mode, bit_rate): + if test_mode in ["fileobj", "bytesio"]: + if bit_rate is not None and bit_rate < 1: + raise unittest.SkipTest( + "mp3 format with variable bit rate is known to " + "not yield the exact same result as sox command.") + self.assert_save_consistency( + "mp3", compression=bit_rate, test_mode=test_mode) + + @nested_params( + ["path", "fileobj", "bytesio"], + [8, 16, 24], + [ + None, + 0, + 1, + 2, + 3, + 4, + 5, + 6, + 7, + 8, + ], + ) + def test_save_flac(self, test_mode, bits_per_sample, compression_level): + self.assert_save_consistency( + "flac", compression=compression_level, + bits_per_sample=bits_per_sample, test_mode=test_mode) + + @nested_params( + ["path", "fileobj", "bytesio"], + ) + def test_save_htk(self, test_mode): + self.assert_save_consistency("htk", test_mode=test_mode, num_channels=1) + + @nested_params( + ["path", "fileobj", "bytesio"], + [ + None, + -1, + 0, + 1, + 2, + 3, + 3.6, + 5, + 10, + ], + ) + def test_save_vorbis(self, test_mode, quality_level): + self.assert_save_consistency( + "vorbis", compression=quality_level, test_mode=test_mode) + + @nested_params( + ["path", "fileobj", "bytesio"], + [ + ('PCM_S', 8, ), + ('PCM_S', 16, ), + ('PCM_S', 24, ), + ('PCM_S', 32, ), + ('ULAW', 8), + ('ALAW', 8), + ('ALAW', 16), + ('ALAW', 24), + ('ALAW', 32), + ], + ) + def test_save_sphere(self, test_mode, enc_params): + encoding, bits_per_sample = enc_params + self.assert_save_consistency( + "sph", encoding=encoding, bits_per_sample=bits_per_sample, test_mode=test_mode) + + @nested_params( + ["path", "fileobj", "bytesio"], + [ + ('PCM_U', 8, ), + ('PCM_S', 16, ), + ('PCM_S', 24, ), + ('PCM_S', 32, ), + ('PCM_F', 32, ), + ('PCM_F', 64, ), + ('ULAW', 8, ), + ('ALAW', 8, ), + ], + ) + def test_save_amb(self, test_mode, enc_params): + encoding, bits_per_sample = enc_params + self.assert_save_consistency( + "amb", encoding=encoding, bits_per_sample=bits_per_sample, test_mode=test_mode) + + @nested_params( + ["path", "fileobj", "bytesio"], + [ + None, + 0, + 1, + 2, + 3, + 4, + 5, + 6, + 7, + ], + ) + def test_save_amr_nb(self, test_mode, bit_rate): + self.assert_save_consistency( + "amr-nb", compression=bit_rate, num_channels=1, test_mode=test_mode) + + @nested_params( + ["path", "fileobj", "bytesio"], + ) + def test_save_gsm(self, test_mode): + self.assert_save_consistency( + "gsm", num_channels=1, test_mode=test_mode) + with self.assertRaises( + RuntimeError, msg="gsm format only supports single channel audio."): + self.assert_save_consistency( + "gsm", num_channels=2, test_mode=test_mode) + with self.assertRaises( + RuntimeError, msg="gsm format only supports a sampling rate of 8kHz."): + self.assert_save_consistency( + "gsm", sample_rate=16000, test_mode=test_mode) - This test takes the same strategy as mp3 to compare the result - """ + @parameterized.expand([ + ("wav", "PCM_S", 16), + ("mp3", ), + ("flac", ), + ("vorbis", ), + ("sph", "PCM_S", 16), + ("amr-nb", ), + ("amb", "PCM_S", 16), + ], name_func=name_func) + def test_save_large(self, format, encoding=None, bits_per_sample=None): + """`sox_io_backend.save` can save large files.""" sample_rate = 8000 - num_channels = 1 - src_path = self.get_temp_path('1.reference.wav') - amr_path = self.get_temp_path('2.1.torchaudio.amr-nb') - wav_path = self.get_temp_path('2.2.torchaudio.wav') - amr_path_sox = self.get_temp_path('3.1.sox.amr-nb') - wav_path_sox = self.get_temp_path('3.2.sox.wav') - - # 1. Generate original wav - data = get_wav_data('int16', num_channels, normalize=False, num_frames=duration * sample_rate) - save_wav(src_path, data, sample_rate) - # 2.1. Convert the original wav to amr_nb with torchaudio - sox_io_backend.save(amr_path, load_wav(src_path, normalize=False)[0], sample_rate, dtype=None) - # 2.2. Convert the amr_nb to wav with Sox - sox_utils.convert_audio_file(amr_path, wav_path) - # 2.3. Load - found = load_wav(wav_path)[0] - - # 3.1. Convert the original wav to amr_nb with SoX - sox_utils.convert_audio_file(src_path, amr_path_sox) - # 3.2. Convert the amr_nb to wav with Sox - sox_utils.convert_audio_file(amr_path_sox, wav_path_sox) - # 3.3. Load - expected = load_wav(wav_path_sox)[0] - - self.assertEqual(found, expected) - + one_hour = 60 * 60 * sample_rate + self.assert_save_consistency( + format, num_channels=1, sample_rate=8000, num_frames=one_hour, + encoding=encoding, bits_per_sample=bits_per_sample) -@skipIfNoExec('sox') -@skipIfNoExtension -class TestSave(SaveTestBase): - @parameterized.expand(list(itertools.product( - ['float32', 'int32', 'int16', 'uint8'], - [8000, 16000], - [1, 2], - )), name_func=name_func) - def test_wav(self, dtype, sample_rate, num_channels): - """`sox_io_backend.save` can save wav format.""" - self.assert_wav(dtype, sample_rate, num_channels, num_frames=None) - - @parameterized.expand(list(itertools.product( - ['float32'], - [16000], - [2], - )), name_func=name_func) - def test_wav_large(self, dtype, sample_rate, num_channels): - """`sox_io_backend.save` can save large wav file.""" - two_hours = 2 * 60 * 60 * sample_rate - self.assert_wav(dtype, sample_rate, num_channels, num_frames=two_hours) - - @parameterized.expand(list(itertools.product( - ['float32', 'int32', 'int16', 'uint8'], - [4, 8, 16, 32], - )), name_func=name_func) - def test_multiple_channels(self, dtype, num_channels): - """`sox_io_backend.save` can save wav with more than 2 channels.""" - sample_rate = 8000 - self.assert_wav(dtype, sample_rate, num_channels, num_frames=None) - - @parameterized.expand(list(itertools.product( - [8000, 16000], - [1, 2], - [-4.2, -0.2, 0, 0.2, 96, 128, 160, 192, 224, 256, 320], - )), name_func=name_func) - def test_mp3(self, sample_rate, num_channels, bit_rate): - """`sox_io_backend.save` can save mp3 format.""" - self.assert_mp3(sample_rate, num_channels, bit_rate, duration=1) - - @parameterized.expand(list(itertools.product( - [16000], - [2], - [128], - )), name_func=name_func) - def test_mp3_large(self, sample_rate, num_channels, bit_rate): - """`sox_io_backend.save` can save large mp3 file.""" - two_hours = 2 * 60 * 60 - self.assert_mp3(sample_rate, num_channels, bit_rate, duration=two_hours) - - @parameterized.expand(list(itertools.product( - [8000, 16000], - [1, 2], - [None] + list(range(9)), - )), name_func=name_func) - def test_flac(self, sample_rate, num_channels, compression_level): - """`sox_io_backend.save` can save flac format.""" - self.assert_flac(sample_rate, num_channels, compression_level, duration=1) - - @parameterized.expand(list(itertools.product( - [16000], - [2], - [0], - )), name_func=name_func) - def test_flac_large(self, sample_rate, num_channels, compression_level): - """`sox_io_backend.save` can save large flac file.""" - two_hours = 2 * 60 * 60 - self.assert_flac(sample_rate, num_channels, compression_level, duration=two_hours) - - @parameterized.expand(list(itertools.product( - [8000, 16000], - [1, 2], - [None, -1, 0, 1, 2, 3, 3.6, 5, 10], - )), name_func=name_func) - def test_vorbis(self, sample_rate, num_channels, quality_level): - """`sox_io_backend.save` can save vorbis format.""" - self.assert_vorbis(sample_rate, num_channels, quality_level, duration=20) - - # note: torchaudio can load large vorbis file, but cannot save large volbis file - # the following test causes Segmentation fault - # - ''' - @parameterized.expand(list(itertools.product( - [16000], - [2], - [10], - )), name_func=name_func) - def test_vorbis_large(self, sample_rate, num_channels, quality_level): - """`sox_io_backend.save` can save large vorbis file correctly.""" - two_hours = 2 * 60 * 60 - self.assert_vorbis(sample_rate, num_channels, quality_level, two_hours) - ''' - - @parameterized.expand(list(itertools.product( - [8000, 16000], - [1, 2], - )), name_func=name_func) - def test_sphere(self, sample_rate, num_channels): - """`sox_io_backend.save` can save sph format.""" - self.assert_sphere(sample_rate, num_channels, duration=1) - - @parameterized.expand(list(itertools.product( - ['float32', 'int32', 'int16', 'uint8'], - [8000, 16000], - [1, 2], - )), name_func=name_func) - def test_amb(self, dtype, sample_rate, num_channels): - """`sox_io_backend.save` can save amb format.""" - self.assert_amb(dtype, sample_rate, num_channels, duration=1) - - def test_amr_nb(self): - """`sox_io_backend.save` can save amr-nb format.""" - self.assert_amr_nb(duration=1) + @parameterized.expand([ + (32, ), + (64, ), + (128, ), + (256, ), + ], name_func=name_func) + def test_save_multi_channels(self, num_channels): + """`sox_io_backend.save` can save audio with many channels""" + self.assert_save_consistency( + "wav", encoding="PCM_S", bits_per_sample=16, + num_channels=num_channels) @skipIfNoExec('sox') -@skipIfNoExtension +@skipIfNoSox class TestSaveParams(TempDirMixin, PytorchTestCase): """Test the correctness of optional parameters of `sox_io_backend.save`""" @parameterized.expand([(True, ), (False, )], name_func=name_func) - def test_channels_first(self, channels_first): + def test_save_channels_first(self, channels_first): """channels_first swaps axes""" path = self.get_temp_path('data.wav') - data = get_wav_data('int32', 2, channels_first=channels_first) + data = get_wav_data( + 'int16', 2, channels_first=channels_first, normalize=False) sox_io_backend.save( - path, data, 8000, channels_first=channels_first, dtype=None) - found = load_wav(path)[0] + path, data, 8000, channels_first=channels_first) + found = load_wav(path, normalize=False)[0] expected = data if channels_first else data.transpose(1, 0) self.assertEqual(found, expected) @parameterized.expand([ 'float32', 'int32', 'int16', 'uint8' ], name_func=name_func) - def test_noncontiguous(self, dtype): + def test_save_noncontiguous(self, dtype): """Noncontiguous tensors are saved correctly""" path = self.get_temp_path('data.wav') - expected = get_wav_data(dtype, 4)[::2, ::2] + enc, bps = get_enc_params(dtype) + expected = get_wav_data(dtype, 4, normalize=False)[::2, ::2] assert not expected.is_contiguous() - sox_io_backend.save(path, expected, 8000, dtype=None) - found = load_wav(path)[0] + sox_io_backend.save( + path, expected, 8000, encoding=enc, bits_per_sample=bps) + found = load_wav(path, normalize=False)[0] self.assertEqual(found, expected) @parameterized.expand([ 'float32', 'int32', 'int16', 'uint8', ]) - def test_tensor_preserve(self, dtype): + def test_save_tensor_preserve(self, dtype): """save function should not alter Tensor""" path = self.get_temp_path('data.wav') - expected = get_wav_data(dtype, 4)[::2, ::2] + expected = get_wav_data(dtype, 4, normalize=False)[::2, ::2] data = expected.clone() - sox_io_backend.save(path, data, 8000, dtype=None) + sox_io_backend.save(path, data, 8000) self.assertEqual(data, expected) - - @parameterized.expand([ - ('float32', torch.tensor([-1.0, -0.5, 0, 0.5, 1.0]).to(torch.float32)), - ('int32', torch.tensor([-2147483648, -1073741824, 0, 1073741824, 2147483647]).to(torch.int32)), - ('int16', torch.tensor([-32768, -16384, 0, 16384, 32767]).to(torch.int16)), - ('uint8', torch.tensor([0, 64, 128, 192, 255]).to(torch.uint8)), - ]) - def test_dtype_conversion(self, dtype, expected): - """`save` performs dtype conversion on float32 src tensors only.""" - path = self.get_temp_path("data.wav") - data = torch.tensor([-1.0, -0.5, 0, 0.5, 1.0]).to(torch.float32).view(-1, 1) - sox_io_backend.save(path, data, 8000, dtype=dtype) - found = load_wav(path, normalize=False)[0] - self.assertEqual(found, expected.view(-1, 1)) - - -@skipIfNoExtension -@skipIfNoExec('sox') -class TestFileObject(SaveTestBase): - """ - We campare the result of file-like object input against file path input because - `save` function is rigrously tested for file path inputs to match libsox's result, - """ - @parameterized.expand([ - ('wav', None), - ('mp3', 128), - ('mp3', 320), - ('flac', 0), - ('flac', 5), - ('flac', 8), - ('vorbis', -1), - ('vorbis', 10), - ('amb', None), - ]) - def test_fileobj(self, ext, compression): - """Saving audio to file object returns the same result as via file path.""" - sample_rate = 16000 - dtype = 'float32' - num_channels = 2 - num_frames = 16000 - channels_first = True - - data = get_wav_data(dtype, num_channels, num_frames=num_frames) - - ref_path = self.get_temp_path(f'reference.{ext}') - res_path = self.get_temp_path(f'test.{ext}') - sox_io_backend.save( - ref_path, data, channels_first=channels_first, - sample_rate=sample_rate, compression=compression, dtype=None) - with open(res_path, 'wb') as fileobj: - sox_io_backend.save( - fileobj, data, channels_first=channels_first, - sample_rate=sample_rate, compression=compression, format=ext, dtype=None) - - expected_data, _ = sox_io_backend.load(ref_path) - data, sr = sox_io_backend.load(res_path) - - assert sample_rate == sr - self.assertEqual(expected_data, data) - - @parameterized.expand([ - ('wav', None), - ('mp3', 128), - ('mp3', 320), - ('flac', 0), - ('flac', 5), - ('flac', 8), - ('vorbis', -1), - ('vorbis', 10), - ('amb', None), - ]) - def test_bytesio(self, ext, compression): - """Saving audio to BytesIO object returns the same result as via file path.""" - sample_rate = 16000 - dtype = 'float32' - num_channels = 2 - num_frames = 16000 - channels_first = True - - data = get_wav_data(dtype, num_channels, num_frames=num_frames) - - ref_path = self.get_temp_path(f'reference.{ext}') - res_path = self.get_temp_path(f'test.{ext}') - sox_io_backend.save( - ref_path, data, channels_first=channels_first, - sample_rate=sample_rate, compression=compression, dtype=None) - fileobj = io.BytesIO() - sox_io_backend.save( - fileobj, data, channels_first=channels_first, - sample_rate=sample_rate, compression=compression, format=ext, dtype=None) - fileobj.seek(0) - with open(res_path, 'wb') as file_: - file_.write(fileobj.read()) - - expected_data, _ = sox_io_backend.load(ref_path) - data, sr = sox_io_backend.load(res_path) - - assert sample_rate == sr - self.assertEqual(expected_data, data) diff --git a/test/torchaudio_unittest/backend/sox_io/smoke_test.py b/test/torchaudio_unittest/backend/sox_io/smoke_test.py index 598a98bd3d..656cfd9fbe 100644 --- a/test/torchaudio_unittest/backend/sox_io/smoke_test.py +++ b/test/torchaudio_unittest/backend/sox_io/smoke_test.py @@ -4,26 +4,26 @@ from torchaudio.utils import sox_utils from torchaudio.backend import sox_io_backend -from torchaudio._internal.module_utils import is_module_available +from torchaudio._internal.module_utils import is_sox_available from parameterized import parameterized from torchaudio_unittest.common_utils import ( TempDirMixin, TorchaudioTestCase, - skipIfNoExtension, + skipIfNoSox, get_wav_data, ) from .common import name_func skipIfNoMP3 = unittest.skipIf( - not is_module_available('torchaudio._torchaudio') or + not is_sox_available() or 'mp3' not in sox_utils.list_read_formats() or 'mp3' not in sox_utils.list_write_formats(), '"sox_io" backend does not support MP3') -@skipIfNoExtension +@skipIfNoSox class SmokeTest(TempDirMixin, TorchaudioTestCase): """Run smoke test on various audio format @@ -88,7 +88,7 @@ def test_flac(self, sample_rate, num_channels, compression_level): self.run_smoke_test('flac', sample_rate, num_channels, compression=compression_level) -@skipIfNoExtension +@skipIfNoSox class SmokeTestFileObj(TorchaudioTestCase): """Run smoke test on various audio format diff --git a/test/torchaudio_unittest/backend/sox_io/torchscript_test.py b/test/torchaudio_unittest/backend/sox_io/torchscript_test.py index dad678cbc0..7fefd2b182 100644 --- a/test/torchaudio_unittest/backend/sox_io/torchscript_test.py +++ b/test/torchaudio_unittest/backend/sox_io/torchscript_test.py @@ -9,7 +9,7 @@ TempDirMixin, TorchaudioTestCase, skipIfNoExec, - skipIfNoExtension, + skipIfNoSox, get_wav_data, save_wav, load_wav, @@ -17,6 +17,7 @@ ) from .common import ( name_func, + get_enc_params, ) @@ -35,12 +36,16 @@ def py_save_func( sample_rate: int, channels_first: bool = True, compression: Optional[float] = None, + encoding: Optional[str] = None, + bits_per_sample: Optional[int] = None, ): - torchaudio.save(filepath, tensor, sample_rate, channels_first, compression) + torchaudio.save( + filepath, tensor, sample_rate, channels_first, + compression, None, encoding, bits_per_sample) @skipIfNoExec('sox') -@skipIfNoExtension +@skipIfNoSox class SoxIO(TempDirMixin, TorchaudioTestCase): """TorchScript-ability Test suite for `sox_io_backend`""" backend = 'sox_io' @@ -102,15 +107,16 @@ def test_save_wav(self, dtype, sample_rate, num_channels): torch.jit.script(py_save_func).save(script_path) ts_save_func = torch.jit.load(script_path) - expected = get_wav_data(dtype, num_channels) + expected = get_wav_data(dtype, num_channels, normalize=False) py_path = self.get_temp_path(f'test_save_py_{dtype}_{sample_rate}_{num_channels}.wav') ts_path = self.get_temp_path(f'test_save_ts_{dtype}_{sample_rate}_{num_channels}.wav') + enc, bps = get_enc_params(dtype) - py_save_func(py_path, expected, sample_rate, True, None) - ts_save_func(ts_path, expected, sample_rate, True, None) + py_save_func(py_path, expected, sample_rate, True, None, enc, bps) + ts_save_func(ts_path, expected, sample_rate, True, None, enc, bps) - py_data, py_sr = load_wav(py_path) - ts_data, ts_sr = load_wav(ts_path) + py_data, py_sr = load_wav(py_path, normalize=False) + ts_data, ts_sr = load_wav(ts_path, normalize=False) self.assertEqual(sample_rate, py_sr) self.assertEqual(sample_rate, ts_sr) @@ -131,8 +137,8 @@ def test_save_flac(self, sample_rate, num_channels, compression_level): py_path = self.get_temp_path(f'test_save_py_{sample_rate}_{num_channels}_{compression_level}.flac') ts_path = self.get_temp_path(f'test_save_ts_{sample_rate}_{num_channels}_{compression_level}.flac') - py_save_func(py_path, expected, sample_rate, True, compression_level) - ts_save_func(ts_path, expected, sample_rate, True, compression_level) + py_save_func(py_path, expected, sample_rate, True, compression_level, None, None) + ts_save_func(ts_path, expected, sample_rate, True, compression_level, None, None) # converting to 32 bit because flac file has 24 bit depth which scipy cannot handle. py_path_wav = f'{py_path}.wav' diff --git a/test/torchaudio_unittest/backend/utils_test.py b/test/torchaudio_unittest/backend/utils_test.py index 3f355be0cb..c89f1e9788 100644 --- a/test/torchaudio_unittest/backend/utils_test.py +++ b/test/torchaudio_unittest/backend/utils_test.py @@ -15,7 +15,6 @@ def test_switch(self): else: assert torchaudio.get_audio_backend() == self.backend assert torchaudio.load == self.backend_module.load - assert torchaudio.load_wav == self.backend_module.load_wav assert torchaudio.save == self.backend_module.save assert torchaudio.info == self.backend_module.info @@ -25,31 +24,13 @@ class TestBackendSwitch_NoBackend(BackendSwitchMixin, common_utils.TorchaudioTes backend_module = torchaudio.backend.no_backend -@common_utils.skipIfNoExtension -class TestBackendSwitch_SoX(BackendSwitchMixin, common_utils.TorchaudioTestCase): - backend = 'sox' - backend_module = torchaudio.backend.sox_backend - - -@common_utils.skipIfNoExtension +@common_utils.skipIfNoSox class TestBackendSwitch_SoXIO(BackendSwitchMixin, common_utils.TorchaudioTestCase): backend = 'sox_io' backend_module = torchaudio.backend.sox_io_backend -@common_utils.skipIfNoModule('soundfile') -class TestBackendSwitch_soundfile_legacy(BackendSwitchMixin, common_utils.TorchaudioTestCase): - backend = 'soundfile' - backend_module = torchaudio.backend.soundfile_backend - - def setUp(self): - torchaudio.USE_SOUNDFILE_LEGACY_INTERFACE = True - - def tearDown(self): - torchaudio.USE_SOUNDFILE_LEGACY_INTERFACE = None - - @common_utils.skipIfNoModule('soundfile') class TestBackendSwitch_soundfile(BackendSwitchMixin, common_utils.TorchaudioTestCase): backend = 'soundfile' - backend_module = torchaudio.backend._soundfile_backend + backend_module = torchaudio.backend.soundfile_backend diff --git a/test/torchaudio_unittest/common_utils/__init__.py b/test/torchaudio_unittest/common_utils/__init__.py index 8cc44c3529..22cb18a08e 100644 --- a/test/torchaudio_unittest/common_utils/__init__.py +++ b/test/torchaudio_unittest/common_utils/__init__.py @@ -15,7 +15,8 @@ skipIfNoCuda, skipIfNoExec, skipIfNoModule, - skipIfNoExtension, + skipIfNoKaldi, + skipIfNoSox, skipIfNoSoxBackend, ) from .wav_utils import ( @@ -26,9 +27,11 @@ ) from .parameterized_utils import ( load_params, + nested_params ) __all__ = ['get_asset_path', 'get_whitenoise', 'get_sinusoid', 'set_audio_backend', 'TempDirMixin', 'HttpServerMixin', 'TestBaseMixin', 'PytorchTestCase', 'TorchaudioTestCase', - 'skipIfNoCuda', 'skipIfNoExec', 'skipIfNoModule', 'skipIfNoExtension', 'skipIfNoSoxBackend', - 'get_wav_data', 'normalize_wav', 'load_wav', 'save_wav', 'load_params'] + 'skipIfNoCuda', 'skipIfNoExec', 'skipIfNoModule', 'skipIfNoKaldi', 'skipIfNoSox', + 'skipIfNoSoxBackend', 'get_wav_data', 'normalize_wav', 'load_wav', 'save_wav', 'load_params', + 'nested_params'] diff --git a/test/torchaudio_unittest/common_utils/backend_utils.py b/test/torchaudio_unittest/common_utils/backend_utils.py index 7e519c80eb..84dd73ed2e 100644 --- a/test/torchaudio_unittest/common_utils/backend_utils.py +++ b/test/torchaudio_unittest/common_utils/backend_utils.py @@ -6,15 +6,13 @@ def set_audio_backend(backend): """Allow additional backend value, 'default'""" backends = torchaudio.list_audio_backends() - if backend == 'soundfile-new': + if backend == 'soundfile': be = 'soundfile' - torchaudio.USE_SOUNDFILE_LEGACY_INTERFACE = False elif backend == 'default': if 'sox_io' in backends: be = 'sox_io' elif 'soundfile' in backends: be = 'soundfile' - torchaudio.USE_SOUNDFILE_LEGACY_INTERFACE = True else: raise unittest.SkipTest('No default backend available') else: diff --git a/test/torchaudio_unittest/common_utils/case_utils.py b/test/torchaudio_unittest/common_utils/case_utils.py index 9a9d491541..5d476072bb 100644 --- a/test/torchaudio_unittest/common_utils/case_utils.py +++ b/test/torchaudio_unittest/common_utils/case_utils.py @@ -8,7 +8,11 @@ import torch from torch.testing._internal.common_utils import TestCase as PytorchTestCase import torchaudio -from torchaudio._internal.module_utils import is_module_available +from torchaudio._internal.module_utils import ( + is_module_available, + is_sox_available, + is_kaldi_available +) from .backend_utils import set_audio_backend @@ -95,11 +99,5 @@ def skipIfNoModule(module, display_name=None): skipIfNoSoxBackend = unittest.skipIf( 'sox' not in torchaudio.list_audio_backends(), 'Sox backend not available') skipIfNoCuda = unittest.skipIf(not torch.cuda.is_available(), reason='CUDA not available') - - -def skipIfNoExtension(test_item): - if is_module_available('torchaudio._torchaudio'): - return test_item - if 'TORCHAUDIO_TEST_FAIL_IF_NO_EXTENSION' in os.environ: - raise RuntimeError('torchaudio C++ extension is not available.') - return unittest.skip('torchaudio C++ extension is not available')(test_item) +skipIfNoSox = unittest.skipIf(not is_sox_available(), reason='Sox not available') +skipIfNoKaldi = unittest.skipIf(not is_kaldi_available(), reason='Kaldi not available') diff --git a/test/torchaudio_unittest/common_utils/data_utils.py b/test/torchaudio_unittest/common_utils/data_utils.py index de19d8174f..9bbafe4f36 100644 --- a/test/torchaudio_unittest/common_utils/data_utils.py +++ b/test/torchaudio_unittest/common_utils/data_utils.py @@ -68,11 +68,11 @@ def get_whitenoise( # so we only fork on CPU, generate values and move the data to the given device with torch.random.fork_rng([]): torch.random.manual_seed(seed) - tensor = torch.randn([int(sample_rate * duration)], dtype=torch.float32, device='cpu') + tensor = torch.randn([n_channels, int(sample_rate * duration)], + dtype=torch.float32, device='cpu') tensor /= 2.0 tensor *= scale_factor tensor.clamp_(-1.0, 1.0) - tensor = tensor.repeat([n_channels, 1]) if not channels_first: tensor = tensor.t() return convert_tensor_encoding(tensor, dtype) diff --git a/test/torchaudio_unittest/common_utils/kaldi_utils.py b/test/torchaudio_unittest/common_utils/kaldi_utils.py new file mode 100644 index 0000000000..71053bd003 --- /dev/null +++ b/test/torchaudio_unittest/common_utils/kaldi_utils.py @@ -0,0 +1,38 @@ +import subprocess + +import torch + + +def convert_args(**kwargs): + args = [] + for key, value in kwargs.items(): + if key == 'sample_rate': + key = 'sample_frequency' + key = '--' + key.replace('_', '-') + value = str(value).lower() if value in [True, False] else str(value) + args.append('%s=%s' % (key, value)) + return args + + +def run_kaldi(command, input_type, input_value): + """Run provided Kaldi command, pass a tensor and get the resulting tensor + + Args: + command (list of str): The command with arguments + input_type (str): 'ark' or 'scp' + input_value (Tensor for 'ark', string for 'scp'): The input to pass. + Must be a path to an audio file for 'scp'. + """ + import kaldi_io + + key = 'foo' + process = subprocess.Popen(command, stdin=subprocess.PIPE, stdout=subprocess.PIPE) + if input_type == 'ark': + kaldi_io.write_mat(process.stdin, input_value.cpu().numpy(), key=key) + elif input_type == 'scp': + process.stdin.write(f'{key} {input_value}'.encode('utf8')) + else: + raise NotImplementedError('Unexpected type') + process.stdin.close() + result = dict(kaldi_io.read_mat_ark(process.stdout))['foo'] + return torch.from_numpy(result.copy()) # copy supresses some torch warning diff --git a/test/torchaudio_unittest/common_utils/parameterized_utils.py b/test/torchaudio_unittest/common_utils/parameterized_utils.py index 24404a6edd..412ee82554 100644 --- a/test/torchaudio_unittest/common_utils/parameterized_utils.py +++ b/test/torchaudio_unittest/common_utils/parameterized_utils.py @@ -1,6 +1,7 @@ import json +from itertools import product -from parameterized import param +from parameterized import param, parameterized from .data_utils import get_asset_path @@ -8,3 +9,19 @@ def load_params(*paths): with open(get_asset_path(*paths), 'r') as file: return [param(json.loads(line)) for line in file] + + +def nested_params(*params): + def _name_func(func, _, params): + strs = [] + for arg in params.args: + if isinstance(arg, tuple): + strs.append("_".join(str(a) for a in arg)) + else: + strs.append(str(arg)) + return f'{func.__name__}_{"_".join(strs)}' + + return parameterized.expand( + list(product(*params)), + name_func=_name_func + ) diff --git a/test/torchaudio_unittest/common_utils/sox_utils.py b/test/torchaudio_unittest/common_utils/sox_utils.py index 0267017393..fd0949f31a 100644 --- a/test/torchaudio_unittest/common_utils/sox_utils.py +++ b/test/torchaudio_unittest/common_utils/sox_utils.py @@ -1,3 +1,4 @@ +import sys import subprocess import warnings @@ -32,6 +33,7 @@ def gen_audio_file( command = [ 'sox', '-V3', # verbose + '--no-dither', # disable automatic dithering '-R', # -R is supposed to be repeatable, though the implementation looks suspicious # and not setting the seed to a fixed value. @@ -61,21 +63,23 @@ def gen_audio_file( ] if attenuation is not None: command += ['vol', f'-{attenuation}dB'] - print(' '.join(command)) + print(' '.join(command), file=sys.stderr) subprocess.run(command, check=True) def convert_audio_file( src_path, dst_path, - *, bit_depth=None, compression=None): + *, encoding=None, bit_depth=None, compression=None): """Convert audio file with `sox` command.""" - command = ['sox', '-V3', '-R', str(src_path)] + command = ['sox', '-V3', '--no-dither', '-R', str(src_path)] + if encoding is not None: + command += ['--encoding', str(encoding)] if bit_depth is not None: command += ['--bits', str(bit_depth)] if compression is not None: command += ['--compression', str(compression)] command += [dst_path] - print(' '.join(command)) + print(' '.join(command), file=sys.stderr) subprocess.run(command, check=True) diff --git a/test/torchaudio_unittest/compliance/generate_fbank_data.py b/test/torchaudio_unittest/compliance/generate_fbank_data.py index 96a935d116..f1935564dc 100644 --- a/test/torchaudio_unittest/compliance/generate_fbank_data.py +++ b/test/torchaudio_unittest/compliance/generate_fbank_data.py @@ -6,6 +6,7 @@ import torch import torchaudio import utils +from torchaudio_unittest import common_utils def run(exe_path, scp_path, out_dir, wave_len, num_outputs, remove_files, log_level): @@ -102,7 +103,7 @@ def decode(fn, sound_path, exe_path, scp_path, out_dir): # print args for python inputs['dither'] = 0.0 logging.info(inputs) - sound, sample_rate = torchaudio.load_wav(sound_path) + sound, sample_rate = common_utils.load_wav(sound_path, normalize=False) kaldi_output_dict = {k: v for k, v in torchaudio.kaldi_io.read_mat_ark(out_fn)} res = torchaudio.compliance.kaldi.fbank(sound, **inputs) torch.set_printoptions(precision=10, sci_mode=False) diff --git a/test/torchaudio_unittest/compliance_kaldi_test.py b/test/torchaudio_unittest/compliance_kaldi_test.py index c7b4149819..a98240a9b8 100644 --- a/test/torchaudio_unittest/compliance_kaldi_test.py +++ b/test/torchaudio_unittest/compliance_kaldi_test.py @@ -45,9 +45,9 @@ def first_sample_of_frame(frame, window_size, window_shift, snip_edges): window[f, s] = wave[s_in_wave] -@common_utils.skipIfNoSoxBackend +@common_utils.skipIfNoSox class Test_Kaldi(common_utils.TempDirMixin, common_utils.TorchaudioTestCase): - backend = 'sox' + backend = 'sox_io' kaldi_output_dir = common_utils.get_asset_path('kaldi') test_filepath = common_utils.get_asset_path('kaldi_file.wav') @@ -91,7 +91,7 @@ def _test_get_strided_helper(self, num_samples, window_size, window_shift, snip_ for r in range(m): extract_window(window, waveform, r, window_size, window_shift, snip_edges) - torch.testing.assert_allclose(window, output) + self.assertEqual(window, output) def test_get_strided(self): # generate any combination where 0 < window_size <= num_samples and @@ -116,7 +116,7 @@ def _create_data_set(self): sound, sample_rate = torchaudio.load(self.test_filepath, normalization=False) print(y >> 16) self.assertTrue(sample_rate == sr) - torch.testing.assert_allclose(y, sound) + self.assertEqual(y, sound) def _print_diagnostic(self, output, expect_output): # given an output and expected output, it will print the absolute/relative errors (max and mean squared) @@ -144,7 +144,7 @@ def _compliance_test_helper(self, sound_filepath, filepath_key, expected_num_fil atol (float): absolute tolerance rtol (float): relative tolerance """ - sound, sr = torchaudio.load_wav(sound_filepath) + sound, sr = common_utils.load_wav(sound_filepath, normalize=False) files = self.test_filepaths[filepath_key] assert len(files) == expected_num_files, \ @@ -156,7 +156,7 @@ def _compliance_test_helper(self, sound_filepath, filepath_key, expected_num_fil # Read kaldi's output from file kaldi_output_path = os.path.join(self.kaldi_output_dir, f) - kaldi_output_dict = {k: v for k, v in torchaudio.kaldi_io.read_mat_ark(kaldi_output_path)} + kaldi_output_dict = dict(torchaudio.kaldi_io.read_mat_ark(kaldi_output_path)) assert len(kaldi_output_dict) == 1 and 'my_id' in kaldi_output_dict, 'invalid test kaldi ark file' kaldi_output = kaldi_output_dict['my_id'] @@ -170,7 +170,7 @@ def _compliance_test_helper(self, sound_filepath, filepath_key, expected_num_fil output = get_output_fn(sound, args) self._print_diagnostic(output, kaldi_output) - torch.testing.assert_allclose(output, kaldi_output, atol=atol, rtol=rtol) + self.assertEqual(output, kaldi_output, atol=atol, rtol=rtol) def test_mfcc_empty(self): # Passing in an empty tensor should result in an error @@ -178,7 +178,7 @@ def test_mfcc_empty(self): def test_resample_waveform(self): def get_output_fn(sound, args): - output = kaldi.resample_waveform(sound, args[1], args[2]) + output = kaldi.resample_waveform(sound.to(torch.float32), args[1], args[2]) return output self._compliance_test_helper(self.test2_filepath, 'resample', 32, 3, get_output_fn, atol=1e-2, rtol=1e-5) @@ -221,7 +221,7 @@ def _test_resample_waveform_accuracy(self, up_scale_factor=None, down_scale_fact ground_truth = ground_truth[..., n_to_trim:-n_to_trim] estimate = estimate[..., n_to_trim:-n_to_trim] - torch.testing.assert_allclose(estimate, ground_truth, atol=atol, rtol=rtol) + self.assertEqual(estimate, ground_truth, atol=atol, rtol=rtol) def test_resample_waveform_downsample_accuracy(self): for i in range(1, 20): @@ -246,4 +246,4 @@ def test_resample_waveform_multi_channel(self): single_channel = self.test1_signal * (i + 1) * 1.5 single_channel_sampled = kaldi.resample_waveform(single_channel, self.test1_signal_sr, self.test1_signal_sr // 2) - torch.testing.assert_allclose(multi_sound_sampled[i, :], single_channel_sampled[0], rtol=1e-4, atol=1e-7) + self.assertEqual(multi_sound_sampled[i, :], single_channel_sampled[0], rtol=1e-4, atol=1e-7) diff --git a/test/torchaudio_unittest/datasets/tedlium_test.py b/test/torchaudio_unittest/datasets/tedlium_test.py index abb6ea5b5c..00c3e1748e 100644 --- a/test/torchaudio_unittest/datasets/tedlium_test.py +++ b/test/torchaudio_unittest/datasets/tedlium_test.py @@ -7,6 +7,7 @@ TorchaudioTestCase, get_whitenoise, save_wav, + skipIfNoSox ) from torchaudio.datasets import tedlium @@ -143,13 +144,7 @@ class TestTedliumSoundfile(Tedlium, TorchaudioTestCase): backend = "soundfile" -class TestTedliumSoundfileNew(Tedlium, TorchaudioTestCase): - backend = "soundfile-new" - - if platform.system() != "Windows": - class TestTedliumSox(Tedlium, TorchaudioTestCase): - backend = "sox" - + @skipIfNoSox class TestTedliumSoxIO(Tedlium, TorchaudioTestCase): backend = "sox_io" diff --git a/test/torchaudio_unittest/functional/autograd_cpu_test.py b/test/torchaudio_unittest/functional/autograd_cpu_test.py new file mode 100644 index 0000000000..a33e82fa56 --- /dev/null +++ b/test/torchaudio_unittest/functional/autograd_cpu_test.py @@ -0,0 +1,8 @@ +import torch +from .autograd_impl import Autograd +from torchaudio_unittest import common_utils + + +class TestAutogradLfilterCPU(Autograd, common_utils.PytorchTestCase): + dtype = torch.float64 + device = torch.device('cpu') diff --git a/test/torchaudio_unittest/functional/autograd_cuda_test.py b/test/torchaudio_unittest/functional/autograd_cuda_test.py new file mode 100644 index 0000000000..09ac74d721 --- /dev/null +++ b/test/torchaudio_unittest/functional/autograd_cuda_test.py @@ -0,0 +1,9 @@ +import torch +from .autograd_impl import Autograd +from torchaudio_unittest import common_utils + + +@common_utils.skipIfNoCuda +class TestAutogradLfilterCUDA(Autograd, common_utils.PytorchTestCase): + dtype = torch.float64 + device = torch.device('cuda') diff --git a/test/torchaudio_unittest/functional/autograd_impl.py b/test/torchaudio_unittest/functional/autograd_impl.py new file mode 100644 index 0000000000..02477d0d33 --- /dev/null +++ b/test/torchaudio_unittest/functional/autograd_impl.py @@ -0,0 +1,40 @@ +import torch +import torchaudio.functional as F +from torch.autograd import gradcheck +from torchaudio_unittest import common_utils + + +class Autograd(common_utils.TestBaseMixin): + def test_x_grad(self): + torch.random.manual_seed(2434) + x = torch.rand(2, 4, 256 * 2, dtype=self.dtype, device=self.device) + a = torch.tensor([0.7, 0.2, 0.6], dtype=self.dtype, device=self.device) + b = torch.tensor([0.4, 0.2, 0.9], dtype=self.dtype, device=self.device) + x.requires_grad = True + assert gradcheck(F.lfilter, (x, a, b), eps=1e-10) + + def test_a_grad(self): + torch.random.manual_seed(2434) + x = torch.rand(2, 4, 256 * 2, dtype=self.dtype, device=self.device) + a = torch.tensor([0.7, 0.2, 0.6], dtype=self.dtype, device=self.device) + b = torch.tensor([0.4, 0.2, 0.9], dtype=self.dtype, device=self.device) + a.requires_grad = True + assert gradcheck(F.lfilter, (x, a, b), eps=1e-10) + + def test_b_grad(self): + torch.random.manual_seed(2434) + x = torch.rand(2, 4, 256 * 2, dtype=self.dtype, device=self.device) + a = torch.tensor([0.7, 0.2, 0.6], dtype=self.dtype, device=self.device) + b = torch.tensor([0.4, 0.2, 0.9], dtype=self.dtype, device=self.device) + b.requires_grad = True + assert gradcheck(F.lfilter, (x, a, b), eps=1e-10) + + def test_all_grad(self): + torch.random.manual_seed(2434) + x = torch.rand(2, 4, 256 * 2, dtype=self.dtype, device=self.device) + a = torch.tensor([0.7, 0.2, 0.6], dtype=self.dtype, device=self.device) + b = torch.tensor([0.4, 0.2, 0.9], dtype=self.dtype, device=self.device) + b.requires_grad = True + a.requires_grad = True + x.requires_grad = True + assert gradcheck(F.lfilter, (x, a, b), eps=1e-10) diff --git a/test/torchaudio_unittest/functional/batch_consistency_test.py b/test/torchaudio_unittest/functional/batch_consistency_test.py new file mode 100644 index 0000000000..44a9580fe8 --- /dev/null +++ b/test/torchaudio_unittest/functional/batch_consistency_test.py @@ -0,0 +1,224 @@ +"""Test numerical consistency among single input and batched input.""" +import itertools +import math + +from parameterized import parameterized, parameterized_class +import torch +import torchaudio.functional as F + +from torchaudio_unittest import common_utils + + +def _name_from_args(func, _, params): + """Return a parameterized test name, based on parameter values.""" + return "{}_{}".format( + func.__name__, + "_".join(str(arg) for arg in params.args)) + + +@parameterized_class([ + # Single-item batch isolates problems that come purely from adding a + # dimension (rather than processing multiple items) + {"batch_size": 1}, + {"batch_size": 3}, +]) +class TestFunctional(common_utils.TorchaudioTestCase): + """Test functions defined in `functional` module""" + backend = 'default' + + def assert_batch_consistency( + self, functional, batch, *args, atol=1e-8, rtol=1e-5, seed=42, + **kwargs): + n = batch.size(0) + + # Compute items separately, then batch the result + torch.random.manual_seed(seed) + items_input = batch.clone() + items_result = torch.stack([ + functional(items_input[i], *args, **kwargs) for i in range(n) + ]) + + # Batch the input and run + torch.random.manual_seed(seed) + batch_input = batch.clone() + batch_result = functional(batch_input, *args, **kwargs) + + self.assertEqual(items_input, batch_input, rtol=rtol, atol=atol) + self.assertEqual(items_result, batch_result, rtol=rtol, atol=atol) + + def test_griffinlim(self): + n_fft = 400 + ws = 400 + hop = 200 + window = torch.hann_window(ws) + power = 2 + momentum = 0.99 + n_iter = 32 + length = 1000 + torch.random.manual_seed(0) + batch = torch.rand(self.batch_size, 1, 201, 6) + self.assert_batch_consistency( + F.griffinlim, batch, window, n_fft, hop, ws, power, + n_iter, momentum, length, 0, atol=5e-5) + + @parameterized.expand(list(itertools.product( + [8000, 16000, 44100], + [1, 2], + )), name_func=_name_from_args) + def test_detect_pitch_frequency(self, sample_rate, n_channels): + # Use different frequencies to ensure each item in the batch returns a + # different answer. + torch.manual_seed(0) + frequencies = torch.randint(100, 1000, [self.batch_size]) + waveforms = torch.stack([ + common_utils.get_sinusoid( + frequency=frequency, sample_rate=sample_rate, + n_channels=n_channels, duration=5) + for frequency in frequencies + ]) + self.assert_batch_consistency( + F.detect_pitch_frequency, waveforms, sample_rate) + + def test_amplitude_to_DB(self): + torch.manual_seed(0) + spec = torch.rand(self.batch_size, 2, 100, 100) * 200 + + amplitude_mult = 20. + amin = 1e-10 + ref = 1.0 + db_mult = math.log10(max(amin, ref)) + + # Test with & without a `top_db` clamp + self.assert_batch_consistency( + F.amplitude_to_DB, spec, amplitude_mult, + amin, db_mult, top_db=None) + self.assert_batch_consistency( + F.amplitude_to_DB, spec, amplitude_mult, + amin, db_mult, top_db=40.) + + def test_amplitude_to_DB_itemwise_clamps(self): + """Ensure that the clamps are separate for each spectrogram in a batch. + + The clamp was determined per-batch in a prior implementation, which + meant it was determined by the loudest item, thus items weren't + independent. See: + + https://github.com/pytorch/audio/issues/994 + + """ + amplitude_mult = 20. + amin = 1e-10 + ref = 1.0 + db_mult = math.log10(max(amin, ref)) + top_db = 20. + + # Make a batch of noise + torch.manual_seed(0) + spec = torch.rand([2, 2, 100, 100]) * 200 + # Make one item blow out the other + spec[0] += 50 + + batchwise_dbs = F.amplitude_to_DB(spec, amplitude_mult, amin, + db_mult, top_db=top_db) + itemwise_dbs = torch.stack([ + F.amplitude_to_DB(item, amplitude_mult, amin, + db_mult, top_db=top_db) + for item in spec + ]) + + self.assertEqual(batchwise_dbs, itemwise_dbs) + + def test_amplitude_to_DB_not_channelwise_clamps(self): + """Check that clamps are applied per-item, not per channel.""" + amplitude_mult = 20. + amin = 1e-10 + ref = 1.0 + db_mult = math.log10(max(amin, ref)) + top_db = 40. + + torch.manual_seed(0) + spec = torch.rand([1, 2, 100, 100]) * 200 + # Make one channel blow out the other + spec[:, 0] += 50 + + specwise_dbs = F.amplitude_to_DB(spec, amplitude_mult, amin, + db_mult, top_db=top_db) + channelwise_dbs = torch.stack([ + F.amplitude_to_DB(spec[:, i], amplitude_mult, amin, + db_mult, top_db=top_db) + for i in range(spec.size(-3)) + ]) + + # Just check channelwise gives a different answer. + difference = (specwise_dbs - channelwise_dbs).abs() + assert (difference >= 1e-5).any() + + def test_contrast(self): + torch.random.manual_seed(0) + waveforms = torch.rand(self.batch_size, 2, 100) - 0.5 + self.assert_batch_consistency( + F.contrast, waveforms, enhancement_amount=80.) + + def test_dcshift(self): + torch.random.manual_seed(0) + waveforms = torch.rand(self.batch_size, 2, 100) - 0.5 + self.assert_batch_consistency( + F.dcshift, waveforms, shift=0.5, limiter_gain=0.05) + + def test_overdrive(self): + torch.random.manual_seed(0) + waveforms = torch.rand(self.batch_size, 2, 100) - 0.5 + self.assert_batch_consistency( + F.overdrive, waveforms, gain=45, colour=30) + + def test_phaser(self): + sample_rate = 44100 + n_channels = 2 + waveform = common_utils.get_whitenoise( + sample_rate=sample_rate, n_channels=self.batch_size * n_channels, + duration=1) + batch = waveform.view(self.batch_size, n_channels, waveform.size(-1)) + self.assert_batch_consistency(F.phaser, batch, sample_rate) + + def test_flanger(self): + torch.random.manual_seed(0) + waveforms = torch.rand(self.batch_size, 2, 100) - 0.5 + sample_rate = 44100 + self.assert_batch_consistency(F.flanger, waveforms, sample_rate) + + @parameterized.expand(list(itertools.product( + [True, False], # center + [True, False], # norm_vars + )), name_func=_name_from_args) + def test_sliding_window_cmn(self, center, norm_vars): + torch.manual_seed(0) + spectrogram = torch.rand(self.batch_size, 2, 1024, 1024) * 200 + self.assert_batch_consistency( + F.sliding_window_cmn, spectrogram, center=center, + norm_vars=norm_vars) + + def test_vad_from_file(self): + filepath = common_utils.get_asset_path("vad-go-stereo-44100.wav") + waveform, sample_rate = common_utils.load_wav(filepath) + # Each channel is slightly offset - we can use this to create a batch + # with different items. + batch = waveform.view(2, 1, -1) + self.assert_batch_consistency(F.vad, batch, sample_rate=sample_rate) + + def test_vad_different_items(self): + """Separate test to ensure VAD consistency with differing items.""" + sample_rate = 44100 + torch.manual_seed(0) + waveforms = torch.rand(self.batch_size, 2, 100) - 0.5 + self.assert_batch_consistency( + F.vad, waveforms, sample_rate=sample_rate) + + @common_utils.skipIfNoKaldi + def test_compute_kaldi_pitch(self): + sample_rate = 44100 + n_channels = 2 + waveform = common_utils.get_whitenoise( + sample_rate=sample_rate, n_channels=self.batch_size * n_channels) + batch = waveform.view(self.batch_size, n_channels, waveform.size(-1)) + self.assert_batch_consistency( + F.compute_kaldi_pitch, batch, sample_rate=sample_rate) diff --git a/test/torchaudio_unittest/functional/functional_cpu_test.py b/test/torchaudio_unittest/functional/functional_cpu_test.py index 21e5a3e1b7..7669d96744 100644 --- a/test/torchaudio_unittest/functional/functional_cpu_test.py +++ b/test/torchaudio_unittest/functional/functional_cpu_test.py @@ -6,8 +6,14 @@ import torchaudio.functional as F from parameterized import parameterized import itertools +import unittest from torchaudio_unittest import common_utils +from torchaudio_unittest.common_utils import ( + TorchaudioTestCase, + skipIfNoSox, +) + from .functional_impl import Lfilter, Spectrogram @@ -15,6 +21,10 @@ class TestLFilterFloat32(Lfilter, common_utils.PytorchTestCase): dtype = torch.float32 device = torch.device('cpu') + @unittest.expectedFailure + def test_9th_order_filter_stability(self): + super().test_9th_order_filter_stability() + class TestLFilterFloat64(Lfilter, common_utils.PytorchTestCase): dtype = torch.float64 @@ -53,6 +63,7 @@ def test_warning(self): class TestComputeDeltas(common_utils.TorchaudioTestCase): """Test suite for correctness of compute_deltas""" + def test_one_channel(self): specgram = torch.tensor([[[1.0, 2.0, 3.0, 4.0]]]) expected = torch.tensor([[[0.5, 1.0, 1.0, 0.5]]]) @@ -211,3 +222,45 @@ def test_mask_along_axis_iid(self, mask_param, mask_value, axis): assert mask_specgrams.size() == specgrams.size() assert (num_masked_columns < mask_param).sum() == num_masked_columns.numel() + + +@skipIfNoSox +class TestApplyCodec(TorchaudioTestCase): + backend = "sox_io" + + def _smoke_test(self, format, compression, check_num_frames): + """ + The purpose of this test suite is to verify that apply_codec functionalities do not exhibit + abnormal behaviors. + """ + torch.random.manual_seed(42) + sample_rate = 8000 + num_frames = 3 * sample_rate + num_channels = 2 + waveform = torch.rand(num_channels, num_frames) + + augmented = F.apply_codec(waveform, + sample_rate, + format, + True, + compression + ) + assert augmented.dtype == waveform.dtype + assert augmented.shape[0] == num_channels + if check_num_frames: + assert augmented.shape[1] == num_frames + + def test_wave(self): + self._smoke_test("wav", compression=None, check_num_frames=True) + + @parameterized.expand([(96,), (128,), (160,), (192,), (224,), (256,), (320,)]) + def test_mp3(self, compression): + self._smoke_test("mp3", compression, check_num_frames=False) + + @parameterized.expand([(0,), (1,), (2,), (3,), (4,), (5,), (6,), (7,), (8,)]) + def test_flac(self, compression): + self._smoke_test("flac", compression, check_num_frames=False) + + @parameterized.expand([(-1,), (0,), (1,), (2,), (3,), (3.6,), (5,), (10,)]) + def test_vorbis(self, compression): + self._smoke_test("vorbis", compression, check_num_frames=False) diff --git a/test/torchaudio_unittest/functional/functional_cuda_test.py b/test/torchaudio_unittest/functional/functional_cuda_test.py index c89795be01..f4db6ca3a0 100644 --- a/test/torchaudio_unittest/functional/functional_cuda_test.py +++ b/test/torchaudio_unittest/functional/functional_cuda_test.py @@ -1,4 +1,5 @@ import torch +import unittest from torchaudio_unittest import common_utils from .functional_impl import Lfilter, Spectrogram @@ -9,6 +10,10 @@ class TestLFilterFloat32(Lfilter, common_utils.PytorchTestCase): dtype = torch.float32 device = torch.device('cuda') + @unittest.expectedFailure + def test_9th_order_filter_stability(self): + super().test_9th_order_filter_stability() + @common_utils.skipIfNoCuda class TestLFilterFloat64(Lfilter, common_utils.PytorchTestCase): diff --git a/test/torchaudio_unittest/functional/functional_impl.py b/test/torchaudio_unittest/functional/functional_impl.py index 1ba5e21fbb..f7f8c17ecb 100644 --- a/test/torchaudio_unittest/functional/functional_impl.py +++ b/test/torchaudio_unittest/functional/functional_impl.py @@ -2,6 +2,7 @@ import torch import torchaudio.functional as F from parameterized import parameterized +from scipy import signal from torchaudio_unittest import common_utils @@ -31,6 +32,42 @@ def test_clamp(self): output_signal = F.lfilter(input_signal, a_coeffs, b_coeffs, clamp=False) assert output_signal.max() > 1 + @parameterized.expand([ + ((44100,),), + ((3, 44100),), + ((2, 3, 44100),), + ((1, 2, 3, 44100),) + ]) + def test_shape(self, shape): + torch.random.manual_seed(42) + waveform = torch.rand(*shape, dtype=self.dtype, device=self.device) + b_coeffs = torch.tensor([0, 0, 0, 1], dtype=self.dtype, device=self.device) + a_coeffs = torch.tensor([1, 0, 0, 0], dtype=self.dtype, device=self.device) + output_waveform = F.lfilter(waveform, a_coeffs, b_coeffs) + assert shape == waveform.size() == output_waveform.size() + + def test_9th_order_filter_stability(self): + """ + Validate the precision of lfilter against reference scipy implementation when using high order filter. + The reference implementation use cascaded second-order filters so is more numerically accurate. + """ + # create an impulse signal + x = torch.zeros(1024, dtype=self.dtype, device=self.device) + x[0] = 1 + + # get target impulse response + sos = signal.butter(9, 850, 'hp', fs=22050, output='sos') + y = torch.from_numpy(signal.sosfilt(sos, x.cpu().numpy())).to(self.dtype).to(self.device) + + # get lfilter coefficients + b, a = signal.butter(9, 850, 'hp', fs=22050, output='ba') + b, a = torch.from_numpy(b).to(self.dtype).to(self.device), torch.from_numpy( + a).to(self.dtype).to(self.device) + + # predict impulse response + yhat = F.lfilter(x, a, b, False) + self.assertEqual(yhat, y, atol=1e-4, rtol=1e-5) + class Spectrogram(common_utils.TestBaseMixin): @parameterized.expand([(0., ), (1., ), (2., ), (3., )]) diff --git a/test/torchaudio_unittest/functional/kaldi_compatibility_cpu_test.py b/test/torchaudio_unittest/functional/kaldi_compatibility_cpu_test.py new file mode 100644 index 0000000000..90a634746c --- /dev/null +++ b/test/torchaudio_unittest/functional/kaldi_compatibility_cpu_test.py @@ -0,0 +1,19 @@ +import torch + +from torchaudio_unittest.common_utils import PytorchTestCase +from .kaldi_compatibility_test_impl import Kaldi, KaldiCPUOnly + + +class TestKaldiCPUOnly(KaldiCPUOnly, PytorchTestCase): + dtype = torch.float32 + device = torch.device('cpu') + + +class TestKaldiFloat32(Kaldi, PytorchTestCase): + dtype = torch.float32 + device = torch.device('cpu') + + +class TestKaldiFloat64(Kaldi, PytorchTestCase): + dtype = torch.float64 + device = torch.device('cpu') diff --git a/test/torchaudio_unittest/functional/kaldi_compatibility_cuda_test.py b/test/torchaudio_unittest/functional/kaldi_compatibility_cuda_test.py new file mode 100644 index 0000000000..47a1bea338 --- /dev/null +++ b/test/torchaudio_unittest/functional/kaldi_compatibility_cuda_test.py @@ -0,0 +1,16 @@ +import torch + +from torchaudio_unittest.common_utils import PytorchTestCase, skipIfNoCuda +from .kaldi_compatibility_test_impl import Kaldi + + +@skipIfNoCuda +class TestKaldiFloat32(Kaldi, PytorchTestCase): + dtype = torch.float32 + device = torch.device('cuda') + + +@skipIfNoCuda +class TestKaldiFloat64(Kaldi, PytorchTestCase): + dtype = torch.float64 + device = torch.device('cuda') diff --git a/test/torchaudio_unittest/functional/kaldi_compatibility_test_impl.py b/test/torchaudio_unittest/functional/kaldi_compatibility_test_impl.py new file mode 100644 index 0000000000..bad30afd9a --- /dev/null +++ b/test/torchaudio_unittest/functional/kaldi_compatibility_test_impl.py @@ -0,0 +1,60 @@ +from parameterized import parameterized +import torch +import torchaudio.functional as F + +from torchaudio_unittest.common_utils import ( + get_sinusoid, + load_params, + save_wav, + skipIfNoExec, + TempDirMixin, + TestBaseMixin, +) +from torchaudio_unittest.common_utils.kaldi_utils import ( + convert_args, + run_kaldi, +) + + +class Kaldi(TempDirMixin, TestBaseMixin): + def assert_equal(self, output, *, expected, rtol=None, atol=None): + expected = expected.to(dtype=self.dtype, device=self.device) + self.assertEqual(output, expected, rtol=rtol, atol=atol) + + @skipIfNoExec('apply-cmvn-sliding') + def test_sliding_window_cmn(self): + """sliding_window_cmn should be numerically compatible with apply-cmvn-sliding""" + kwargs = { + 'cmn_window': 600, + 'min_cmn_window': 100, + 'center': False, + 'norm_vars': False, + } + + tensor = torch.randn(40, 10, dtype=self.dtype, device=self.device) + result = F.sliding_window_cmn(tensor, **kwargs) + command = ['apply-cmvn-sliding'] + convert_args(**kwargs) + ['ark:-', 'ark:-'] + kaldi_result = run_kaldi(command, 'ark', tensor) + self.assert_equal(result, expected=kaldi_result) + + +class KaldiCPUOnly(TempDirMixin, TestBaseMixin): + def assert_equal(self, output, *, expected, rtol=None, atol=None): + expected = expected.to(dtype=self.dtype, device=self.device) + self.assertEqual(output, expected, rtol=rtol, atol=atol) + + @parameterized.expand(load_params('kaldi_test_pitch_args.jsonl')) + @skipIfNoExec('compute-kaldi-pitch-feats') + def test_pitch_feats(self, kwargs): + """compute_kaldi_pitch produces numerically compatible result with compute-kaldi-pitch-feats""" + sample_rate = kwargs['sample_rate'] + waveform = get_sinusoid(dtype='float32', sample_rate=sample_rate) + result = F.compute_kaldi_pitch(waveform[0], **kwargs) + + waveform = get_sinusoid(dtype='int16', sample_rate=sample_rate) + wave_file = self.get_temp_path('test.wav') + save_wav(wave_file, waveform, sample_rate) + + command = ['compute-kaldi-pitch-feats'] + convert_args(**kwargs) + ['scp:-', 'ark:-'] + kaldi_result = run_kaldi(command, 'scp', wave_file) + self.assert_equal(result, expected=kaldi_result) diff --git a/test/torchaudio_unittest/functional/librosa_compatibility_test.py b/test/torchaudio_unittest/functional/librosa_compatibility_test.py new file mode 100644 index 0000000000..c88d9f3ccd --- /dev/null +++ b/test/torchaudio_unittest/functional/librosa_compatibility_test.py @@ -0,0 +1,155 @@ +import itertools +import unittest +from distutils.version import StrictVersion + +import torch +from parameterized import parameterized, param + +import torchaudio.functional as F +from torchaudio._internal.module_utils import is_module_available + +LIBROSA_AVAILABLE = is_module_available('librosa') + +if LIBROSA_AVAILABLE: + import numpy as np + import librosa + +from torchaudio_unittest import common_utils + + +@unittest.skipIf(not LIBROSA_AVAILABLE, "Librosa not available") +class TestFunctional(common_utils.TorchaudioTestCase): + """Test suite for functions in `functional` module.""" + def test_griffinlim(self): + # NOTE: This test is flaky without a fixed random seed + # See https://github.com/pytorch/audio/issues/382 + torch.random.manual_seed(42) + tensor = torch.rand((1, 1000)) + + n_fft = 400 + ws = 400 + hop = 100 + window = torch.hann_window(ws) + normalize = False + momentum = 0.99 + n_iter = 8 + length = 1000 + rand_init = False + init = 'random' if rand_init else None + + specgram = F.spectrogram(tensor, 0, window, n_fft, hop, ws, 2, normalize).sqrt() + ta_out = F.griffinlim(specgram, window, n_fft, hop, ws, 1, + n_iter, momentum, length, rand_init) + lr_out = librosa.griffinlim(specgram.squeeze(0).numpy(), n_iter=n_iter, hop_length=hop, + momentum=momentum, init=init, length=length) + lr_out = torch.from_numpy(lr_out).unsqueeze(0) + + self.assertEqual(ta_out, lr_out, atol=5e-5, rtol=1e-5) + + @parameterized.expand([ + param(norm=norm, mel_scale=mel_scale, **p.kwargs) + for p in [ + param(), + param(n_mels=128, sample_rate=44100), + param(n_mels=128, fmin=2000.0, fmax=5000.0), + param(n_mels=56, fmin=100.0, fmax=9000.0), + param(n_mels=56, fmin=800.0, fmax=900.0), + param(n_mels=56, fmin=1900.0, fmax=900.0), + param(n_mels=10, fmin=1900.0, fmax=900.0), + ] + for norm in [None, 'slaney'] + for mel_scale in ['htk', 'slaney'] + ]) + def test_create_fb(self, n_mels=40, sample_rate=22050, n_fft=2048, + fmin=0.0, fmax=8000.0, norm=None, mel_scale="htk"): + if (norm == "slaney" and StrictVersion(librosa.__version__) < StrictVersion("0.7.2")): + self.skipTest('Test is known to fail with older versions of librosa.') + + librosa_fb = librosa.filters.mel(sr=sample_rate, + n_fft=n_fft, + n_mels=n_mels, + fmax=fmax, + fmin=fmin, + htk=mel_scale == "htk", + norm=norm) + fb = F.create_fb_matrix(sample_rate=sample_rate, + n_mels=n_mels, + f_max=fmax, + f_min=fmin, + n_freqs=(n_fft // 2 + 1), + norm=norm, + mel_scale=mel_scale) + + for i_mel_bank in range(n_mels): + self.assertEqual( + fb[:, i_mel_bank], torch.tensor(librosa_fb[i_mel_bank]), atol=1e-4, rtol=1e-5) + + def test_amplitude_to_DB(self): + spec = torch.rand((6, 201)) + + amin = 1e-10 + db_multiplier = 0.0 + top_db = 80.0 + + # Power to DB + multiplier = 10.0 + + ta_out = F.amplitude_to_DB(spec, multiplier, amin, db_multiplier, top_db) + lr_out = librosa.core.power_to_db(spec.numpy()) + lr_out = torch.from_numpy(lr_out) + + self.assertEqual(ta_out, lr_out, atol=5e-5, rtol=1e-5) + + # Amplitude to DB + multiplier = 20.0 + + ta_out = F.amplitude_to_DB(spec, multiplier, amin, db_multiplier, top_db) + lr_out = librosa.core.amplitude_to_db(spec.numpy()) + lr_out = torch.from_numpy(lr_out) + + self.assertEqual(ta_out, lr_out, atol=5e-5, rtol=1e-5) + + +@unittest.skipIf(not LIBROSA_AVAILABLE, "Librosa not available") +class TestPhaseVocoder(common_utils.TorchaudioTestCase): + @parameterized.expand(list(itertools.product( + [(2, 1025, 400, 2)], + [0.5, 1.01, 1.3], + [256] + ))) + def test_phase_vocoder(self, shape, rate, hop_length): + # Due to cummulative sum, numerical error in using torch.float32 will + # result in bottom right values of the stretched sectrogram to not + # match with librosa. + torch.random.manual_seed(42) + complex_specgrams = torch.randn(*shape) + complex_specgrams = complex_specgrams.type(torch.float64) + phase_advance = torch.linspace( + 0, + np.pi * hop_length, + complex_specgrams.shape[-3], + dtype=torch.float64)[..., None] + + complex_specgrams_stretch = F.phase_vocoder(complex_specgrams, rate=rate, phase_advance=phase_advance) + + # == Test shape + expected_size = list(complex_specgrams.size()) + expected_size[-2] = int(np.ceil(expected_size[-2] / rate)) + + assert complex_specgrams.dim() == complex_specgrams_stretch.dim() + assert complex_specgrams_stretch.size() == torch.Size(expected_size) + + # == Test values + index = [0] * (complex_specgrams.dim() - 3) + [slice(None)] * 3 + mono_complex_specgram = complex_specgrams[index].numpy() + mono_complex_specgram = mono_complex_specgram[..., 0] + \ + mono_complex_specgram[..., 1] * 1j + expected_complex_stretch = librosa.phase_vocoder( + mono_complex_specgram, + rate=rate, + hop_length=hop_length) + + complex_stretch = complex_specgrams_stretch[index].numpy() + complex_stretch = complex_stretch[..., 0] + 1j * complex_stretch[..., 1] + + self.assertEqual(complex_stretch, torch.from_numpy(expected_complex_stretch), atol=1e-5, rtol=1e-5) diff --git a/test/torchaudio_unittest/sox_compatibility_test.py b/test/torchaudio_unittest/functional/sox_compatibility_test.py similarity index 90% rename from test/torchaudio_unittest/sox_compatibility_test.py rename to test/torchaudio_unittest/functional/sox_compatibility_test.py index c68e529427..21f082683c 100644 --- a/test/torchaudio_unittest/sox_compatibility_test.py +++ b/test/torchaudio_unittest/functional/sox_compatibility_test.py @@ -1,7 +1,5 @@ import torch import torchaudio.functional as F -import torchaudio.transforms as T -from parameterized import parameterized from torchaudio_unittest.common_utils import ( skipIfNoSoxBackend, @@ -299,31 +297,3 @@ def test_perf_biquad_filtering(self): data, path = self.get_whitenoise() result = F.lfilter(data, torch.tensor([a0, a1, a2]), torch.tensor([b0, b1, b2])) self.assert_sox_effect(result, path, ['biquad', b0, b1, b2, a0, a1, a2]) - - @parameterized.expand([ - ('q', 'quarter_sine'), - ('h', 'half_sine'), - ('t', 'linear'), - ]) - def test_fade(self, fade_shape_sox, fade_shape): - fade_in_len, fade_out_len = 44100, 44100 - data, path = self.get_whitenoise(sample_rate=44100) - result = T.Fade(fade_in_len, fade_out_len, fade_shape)(data) - self.assert_sox_effect(result, path, ['fade', fade_shape_sox, '1', '0', '1']) - - @parameterized.expand([ - ('amplitude', 1.1), - ('db', 2), - ('power', 2), - ]) - def test_vol(self, gain_type, gain): - data, path = self.get_whitenoise() - result = T.Vol(gain, gain_type)(data) - self.assert_sox_effect(result, path, ['vol', f'{gain}', gain_type]) - - @parameterized.expand(['vad-go-stereo-44100.wav', 'vad-go-mono-32000.wav']) - def test_vad(self, filename): - path = get_asset_path(filename) - data, sample_rate = load_wav(path) - result = T.Vad(sample_rate)(data) - self.assert_sox_effect(result, path, ['vad']) diff --git a/test/torchaudio_unittest/functional/torchscript_consistency_impl.py b/test/torchaudio_unittest/functional/torchscript_consistency_impl.py index 83f7e8e95d..b6aec04d9c 100644 --- a/test/torchaudio_unittest/functional/torchscript_consistency_impl.py +++ b/test/torchaudio_unittest/functional/torchscript_consistency_impl.py @@ -41,12 +41,11 @@ def func(tensor): hop = 200 window = torch.hann_window(ws, device=tensor.device, dtype=tensor.dtype) power = 2. - normalize = False momentum = 0.99 n_iter = 32 length = 1000 rand_int = False - return F.griffinlim(tensor, window, n_fft, hop, ws, power, normalize, n_iter, momentum, length, rand_int) + return F.griffinlim(tensor, window, n_fft, hop, ws, power, n_iter, momentum, length, rand_int) tensor = torch.rand((1, 201, 6)) self._assert_consistency(func, tensor) @@ -547,3 +546,30 @@ def func(tensor): tensor = common_utils.get_whitenoise(sample_rate=44100) self._assert_consistency(func, tensor) + + def test_phase_vocoder(self): + def func(tensor, device: torch.device = self.device): + rate = 0.5 + hop_length = 256 + phase_advance = torch.linspace( + 0, + 3.14 * hop_length, + tensor.shape[-3], + dtype=torch.float64, + ).to(device)[..., None] + return F.phase_vocoder(tensor, rate, phase_advance) + + tensor = torch.randn(2, 1025, 400, 2) + self._assert_consistency(func, tensor) + + @common_utils.skipIfNoKaldi + def test_compute_kaldi_pitch(self): + if self.dtype != torch.float32 or self.device != torch.device('cpu'): + raise unittest.SkipTest("Only float32, cpu is supported.") + + def func(tensor): + sample_rate: float = 44100. + return F.compute_kaldi_pitch(tensor, sample_rate) + + tensor = common_utils.get_whitenoise(sample_rate=44100) + self._assert_consistency(func, tensor) diff --git a/test/torchaudio_unittest/kaldi_compatibility_impl.py b/test/torchaudio_unittest/kaldi_compatibility_impl.py deleted file mode 100644 index 983805fff5..0000000000 --- a/test/torchaudio_unittest/kaldi_compatibility_impl.py +++ /dev/null @@ -1,103 +0,0 @@ -"""Test suites for checking numerical compatibility against Kaldi""" -import subprocess - -import kaldi_io -import torch -import torchaudio.functional as F -import torchaudio.compliance.kaldi -from parameterized import parameterized - -from torchaudio_unittest.common_utils import ( - TestBaseMixin, - load_params, - skipIfNoExec, - get_asset_path, - load_wav -) - - -def _convert_args(**kwargs): - args = [] - for key, value in kwargs.items(): - key = '--' + key.replace('_', '-') - value = str(value).lower() if value in [True, False] else str(value) - args.append('%s=%s' % (key, value)) - return args - - -def _run_kaldi(command, input_type, input_value): - """Run provided Kaldi command, pass a tensor and get the resulting tensor - - Args: - input_type: str - 'ark' or 'scp' - input_value: - Tensor for 'ark' - string for 'scp' (path to an audio file) - """ - key = 'foo' - process = subprocess.Popen(command, stdin=subprocess.PIPE, stdout=subprocess.PIPE) - if input_type == 'ark': - kaldi_io.write_mat(process.stdin, input_value.cpu().numpy(), key=key) - elif input_type == 'scp': - process.stdin.write(f'{key} {input_value}'.encode('utf8')) - else: - raise NotImplementedError('Unexpected type') - process.stdin.close() - result = dict(kaldi_io.read_mat_ark(process.stdout))['foo'] - return torch.from_numpy(result.copy()) # copy supresses some torch warning - - -class Kaldi(TestBaseMixin): - def assert_equal(self, output, *, expected, rtol=None, atol=None): - expected = expected.to(dtype=self.dtype, device=self.device) - self.assertEqual(output, expected, rtol=rtol, atol=atol) - - @skipIfNoExec('apply-cmvn-sliding') - def test_sliding_window_cmn(self): - """sliding_window_cmn should be numerically compatible with apply-cmvn-sliding""" - kwargs = { - 'cmn_window': 600, - 'min_cmn_window': 100, - 'center': False, - 'norm_vars': False, - } - - tensor = torch.randn(40, 10, dtype=self.dtype, device=self.device) - result = F.sliding_window_cmn(tensor, **kwargs) - command = ['apply-cmvn-sliding'] + _convert_args(**kwargs) + ['ark:-', 'ark:-'] - kaldi_result = _run_kaldi(command, 'ark', tensor) - self.assert_equal(result, expected=kaldi_result) - - @parameterized.expand(load_params('kaldi_test_fbank_args.json')) - @skipIfNoExec('compute-fbank-feats') - def test_fbank(self, kwargs): - """fbank should be numerically compatible with compute-fbank-feats""" - wave_file = get_asset_path('kaldi_file.wav') - waveform = load_wav(wave_file, normalize=False)[0].to(dtype=self.dtype, device=self.device) - result = torchaudio.compliance.kaldi.fbank(waveform, **kwargs) - command = ['compute-fbank-feats'] + _convert_args(**kwargs) + ['scp:-', 'ark:-'] - kaldi_result = _run_kaldi(command, 'scp', wave_file) - self.assert_equal(result, expected=kaldi_result, rtol=1e-4, atol=1e-8) - - @parameterized.expand(load_params('kaldi_test_spectrogram_args.json')) - @skipIfNoExec('compute-spectrogram-feats') - def test_spectrogram(self, kwargs): - """spectrogram should be numerically compatible with compute-spectrogram-feats""" - wave_file = get_asset_path('kaldi_file.wav') - waveform = load_wav(wave_file, normalize=False)[0].to(dtype=self.dtype, device=self.device) - result = torchaudio.compliance.kaldi.spectrogram(waveform, **kwargs) - command = ['compute-spectrogram-feats'] + _convert_args(**kwargs) + ['scp:-', 'ark:-'] - kaldi_result = _run_kaldi(command, 'scp', wave_file) - self.assert_equal(result, expected=kaldi_result, rtol=1e-4, atol=1e-8) - - @parameterized.expand(load_params('kaldi_test_mfcc_args.json')) - @skipIfNoExec('compute-mfcc-feats') - def test_mfcc(self, kwargs): - """mfcc should be numerically compatible with compute-mfcc-feats""" - wave_file = get_asset_path('kaldi_file.wav') - waveform = load_wav(wave_file, normalize=False)[0].to(dtype=self.dtype, device=self.device) - result = torchaudio.compliance.kaldi.mfcc(waveform, **kwargs) - command = ['compute-mfcc-feats'] + _convert_args(**kwargs) + ['scp:-', 'ark:-'] - kaldi_result = _run_kaldi(command, 'scp', wave_file) - self.assert_equal(result, expected=kaldi_result, rtol=1e-4, atol=1e-8) diff --git a/test/torchaudio_unittest/librosa_compatibility_test.py b/test/torchaudio_unittest/librosa_compatibility_test.py deleted file mode 100644 index 9e070b141a..0000000000 --- a/test/torchaudio_unittest/librosa_compatibility_test.py +++ /dev/null @@ -1,366 +0,0 @@ -"""Test suites for numerical compatibility with librosa""" -import os -import unittest -from distutils.version import StrictVersion - -import torch -import torchaudio -import torchaudio.functional as F -from torchaudio._internal.module_utils import is_module_available -from parameterized import parameterized -import itertools - -LIBROSA_AVAILABLE = is_module_available('librosa') - -if LIBROSA_AVAILABLE: - import numpy as np - import librosa - import scipy - -from torchaudio_unittest import common_utils - - -@unittest.skipIf(not LIBROSA_AVAILABLE, "Librosa not available") -class TestFunctional(common_utils.TorchaudioTestCase): - """Test suite for functions in `functional` module.""" - def test_griffinlim(self): - # NOTE: This test is flaky without a fixed random seed - # See https://github.com/pytorch/audio/issues/382 - torch.random.manual_seed(42) - tensor = torch.rand((1, 1000)) - - n_fft = 400 - ws = 400 - hop = 100 - window = torch.hann_window(ws) - normalize = False - momentum = 0.99 - n_iter = 8 - length = 1000 - rand_init = False - init = 'random' if rand_init else None - - specgram = F.spectrogram(tensor, 0, window, n_fft, hop, ws, 2, normalize).sqrt() - ta_out = F.griffinlim(specgram, window, n_fft, hop, ws, 1, normalize, - n_iter, momentum, length, rand_init) - lr_out = librosa.griffinlim(specgram.squeeze(0).numpy(), n_iter=n_iter, hop_length=hop, - momentum=momentum, init=init, length=length) - lr_out = torch.from_numpy(lr_out).unsqueeze(0) - - self.assertEqual(ta_out, lr_out, atol=5e-5, rtol=1e-5) - - def _test_create_fb(self, n_mels=40, sample_rate=22050, n_fft=2048, fmin=0.0, fmax=8000.0, norm=None): - librosa_fb = librosa.filters.mel(sr=sample_rate, - n_fft=n_fft, - n_mels=n_mels, - fmax=fmax, - fmin=fmin, - htk=True, - norm=norm) - fb = F.create_fb_matrix(sample_rate=sample_rate, - n_mels=n_mels, - f_max=fmax, - f_min=fmin, - n_freqs=(n_fft // 2 + 1), - norm=norm) - - for i_mel_bank in range(n_mels): - self.assertEqual( - fb[:, i_mel_bank], torch.tensor(librosa_fb[i_mel_bank]), atol=1e-4, rtol=1e-5) - - def test_create_fb(self): - self._test_create_fb() - self._test_create_fb(n_mels=128, sample_rate=44100) - self._test_create_fb(n_mels=128, fmin=2000.0, fmax=5000.0) - self._test_create_fb(n_mels=56, fmin=100.0, fmax=9000.0) - self._test_create_fb(n_mels=56, fmin=800.0, fmax=900.0) - self._test_create_fb(n_mels=56, fmin=1900.0, fmax=900.0) - self._test_create_fb(n_mels=10, fmin=1900.0, fmax=900.0) - if StrictVersion(librosa.__version__) < StrictVersion("0.7.2"): - return - self._test_create_fb(n_mels=128, sample_rate=44100, norm="slaney") - self._test_create_fb(n_mels=128, fmin=2000.0, fmax=5000.0, norm="slaney") - self._test_create_fb(n_mels=56, fmin=100.0, fmax=9000.0, norm="slaney") - self._test_create_fb(n_mels=56, fmin=800.0, fmax=900.0, norm="slaney") - self._test_create_fb(n_mels=56, fmin=1900.0, fmax=900.0, norm="slaney") - self._test_create_fb(n_mels=10, fmin=1900.0, fmax=900.0, norm="slaney") - - def test_amplitude_to_DB(self): - spec = torch.rand((6, 201)) - - amin = 1e-10 - db_multiplier = 0.0 - top_db = 80.0 - - # Power to DB - multiplier = 10.0 - - ta_out = F.amplitude_to_DB(spec, multiplier, amin, db_multiplier, top_db) - lr_out = librosa.core.power_to_db(spec.numpy()) - lr_out = torch.from_numpy(lr_out) - - self.assertEqual(ta_out, lr_out, atol=5e-5, rtol=1e-5) - - # Amplitude to DB - multiplier = 20.0 - - ta_out = F.amplitude_to_DB(spec, multiplier, amin, db_multiplier, top_db) - lr_out = librosa.core.amplitude_to_db(spec.numpy()) - lr_out = torch.from_numpy(lr_out) - - self.assertEqual(ta_out, lr_out, atol=5e-5, rtol=1e-5) - - -@unittest.skipIf(not LIBROSA_AVAILABLE, "Librosa not available") -class TestPhaseVocoder(common_utils.TorchaudioTestCase): - @parameterized.expand(list(itertools.product( - [(2, 1025, 400, 2)], - [0.5, 1.01, 1.3], - [256] - ))) - def test_phase_vocoder(self, shape, rate, hop_length): - # Due to cummulative sum, numerical error in using torch.float32 will - # result in bottom right values of the stretched sectrogram to not - # match with librosa. - torch.random.manual_seed(42) - complex_specgrams = torch.randn(*shape) - complex_specgrams = complex_specgrams.type(torch.float64) - phase_advance = torch.linspace( - 0, - np.pi * hop_length, - complex_specgrams.shape[-3], - dtype=torch.float64)[..., None] - - complex_specgrams_stretch = F.phase_vocoder(complex_specgrams, rate=rate, phase_advance=phase_advance) - - # == Test shape - expected_size = list(complex_specgrams.size()) - expected_size[-2] = int(np.ceil(expected_size[-2] / rate)) - - assert complex_specgrams.dim() == complex_specgrams_stretch.dim() - assert complex_specgrams_stretch.size() == torch.Size(expected_size) - - # == Test values - index = [0] * (complex_specgrams.dim() - 3) + [slice(None)] * 3 - mono_complex_specgram = complex_specgrams[index].numpy() - mono_complex_specgram = mono_complex_specgram[..., 0] + \ - mono_complex_specgram[..., 1] * 1j - expected_complex_stretch = librosa.phase_vocoder( - mono_complex_specgram, - rate=rate, - hop_length=hop_length) - - complex_stretch = complex_specgrams_stretch[index].numpy() - complex_stretch = complex_stretch[..., 0] + 1j * complex_stretch[..., 1] - - self.assertEqual(complex_stretch, torch.from_numpy(expected_complex_stretch), atol=1e-5, rtol=1e-5) - - -def _load_audio_asset(*asset_paths, **kwargs): - file_path = common_utils.get_asset_path(*asset_paths) - sound, sample_rate = torchaudio.load(file_path, **kwargs) - return sound, sample_rate - - -@unittest.skipIf(not LIBROSA_AVAILABLE, "Librosa not available") -class TestTransforms(common_utils.TorchaudioTestCase): - """Test suite for functions in `transforms` module.""" - def assert_compatibilities(self, n_fft, hop_length, power, n_mels, n_mfcc, sample_rate): - common_utils.set_audio_backend('default') - path = common_utils.get_asset_path('sinewave.wav') - sound, sample_rate = common_utils.load_wav(path) - sound_librosa = sound.cpu().numpy().squeeze() # (64000) - - # test core spectrogram - spect_transform = torchaudio.transforms.Spectrogram( - n_fft=n_fft, hop_length=hop_length, power=power) - out_librosa, _ = librosa.core.spectrum._spectrogram( - y=sound_librosa, n_fft=n_fft, hop_length=hop_length, power=power) - - out_torch = spect_transform(sound).squeeze().cpu() - self.assertEqual(out_torch, torch.from_numpy(out_librosa), atol=1e-5, rtol=1e-5) - - # test mel spectrogram - melspect_transform = torchaudio.transforms.MelSpectrogram( - sample_rate=sample_rate, window_fn=torch.hann_window, - hop_length=hop_length, n_mels=n_mels, n_fft=n_fft) - librosa_mel = librosa.feature.melspectrogram( - y=sound_librosa, sr=sample_rate, n_fft=n_fft, - hop_length=hop_length, n_mels=n_mels, htk=True, norm=None) - librosa_mel_tensor = torch.from_numpy(librosa_mel) - torch_mel = melspect_transform(sound).squeeze().cpu() - self.assertEqual( - torch_mel.type(librosa_mel_tensor.dtype), librosa_mel_tensor, atol=5e-3, rtol=1e-5) - - # test s2db - power_to_db_transform = torchaudio.transforms.AmplitudeToDB('power', 80.) - power_to_db_torch = power_to_db_transform(spect_transform(sound)).squeeze().cpu() - power_to_db_librosa = librosa.core.spectrum.power_to_db(out_librosa) - self.assertEqual(power_to_db_torch, torch.from_numpy(power_to_db_librosa), atol=5e-3, rtol=1e-5) - - mag_to_db_transform = torchaudio.transforms.AmplitudeToDB('magnitude', 80.) - mag_to_db_torch = mag_to_db_transform(torch.abs(sound)).squeeze().cpu() - mag_to_db_librosa = librosa.core.spectrum.amplitude_to_db(sound_librosa) - self.assertEqual(mag_to_db_torch, torch.from_numpy(mag_to_db_librosa), atol=5e-3, rtol=1e-5) - - power_to_db_torch = power_to_db_transform(melspect_transform(sound)).squeeze().cpu() - db_librosa = librosa.core.spectrum.power_to_db(librosa_mel) - db_librosa_tensor = torch.from_numpy(db_librosa) - self.assertEqual( - power_to_db_torch.type(db_librosa_tensor.dtype), db_librosa_tensor, atol=5e-3, rtol=1e-5) - - # test MFCC - melkwargs = {'hop_length': hop_length, 'n_fft': n_fft} - mfcc_transform = torchaudio.transforms.MFCC( - sample_rate=sample_rate, n_mfcc=n_mfcc, norm='ortho', melkwargs=melkwargs) - - # librosa.feature.mfcc doesn't pass kwargs properly since some of the - # kwargs for melspectrogram and mfcc are the same. We just follow the - # function body in - # https://librosa.github.io/librosa/_modules/librosa/feature/spectral.html#melspectrogram - # to mirror this function call with correct args: - # - # librosa_mfcc = librosa.feature.mfcc( - # y=sound_librosa, sr=sample_rate, n_mfcc = n_mfcc, - # hop_length=hop_length, n_fft=n_fft, htk=True, norm=None, n_mels=n_mels) - - librosa_mfcc = scipy.fftpack.dct(db_librosa, axis=0, type=2, norm='ortho')[:n_mfcc] - librosa_mfcc_tensor = torch.from_numpy(librosa_mfcc) - torch_mfcc = mfcc_transform(sound).squeeze().cpu() - - self.assertEqual( - torch_mfcc.type(librosa_mfcc_tensor.dtype), librosa_mfcc_tensor, atol=5e-3, rtol=1e-5) - - self.assert_compatibilities_spectral_centroid(sample_rate, n_fft, hop_length, sound, sound_librosa) - - def assert_compatibilities_spectral_centroid(self, sample_rate, n_fft, hop_length, sound, sound_librosa): - spect_centroid = torchaudio.transforms.SpectralCentroid( - sample_rate=sample_rate, n_fft=n_fft, hop_length=hop_length) - out_torch = spect_centroid(sound).squeeze().cpu() - - out_librosa = librosa.feature.spectral_centroid( - y=sound_librosa, sr=sample_rate, n_fft=n_fft, hop_length=hop_length) - out_librosa = torch.from_numpy(out_librosa)[0] - - self.assertEqual(out_torch.type(out_librosa.dtype), out_librosa, atol=1e-5, rtol=1e-5) - - def test_basics1(self): - kwargs = { - 'n_fft': 400, - 'hop_length': 200, - 'power': 2.0, - 'n_mels': 128, - 'n_mfcc': 40, - 'sample_rate': 16000 - } - self.assert_compatibilities(**kwargs) - - def test_basics2(self): - kwargs = { - 'n_fft': 600, - 'hop_length': 100, - 'power': 2.0, - 'n_mels': 128, - 'n_mfcc': 20, - 'sample_rate': 16000 - } - self.assert_compatibilities(**kwargs) - - # NOTE: Test passes offline, but fails on TravisCI (and CircleCI), see #372. - @unittest.skipIf('CI' in os.environ, 'Test is known to fail on CI') - def test_basics3(self): - kwargs = { - 'n_fft': 200, - 'hop_length': 50, - 'power': 2.0, - 'n_mels': 128, - 'n_mfcc': 50, - 'sample_rate': 24000 - } - self.assert_compatibilities(**kwargs) - - def test_basics4(self): - kwargs = { - 'n_fft': 400, - 'hop_length': 200, - 'power': 3.0, - 'n_mels': 128, - 'n_mfcc': 40, - 'sample_rate': 16000 - } - self.assert_compatibilities(**kwargs) - - def test_MelScale(self): - """MelScale transform is comparable to that of librosa""" - n_fft = 2048 - n_mels = 256 - hop_length = n_fft // 4 - sample_rate = 44100 - sound = common_utils.get_whitenoise(sample_rate=sample_rate, duration=60) - sound = sound.mean(dim=0, keepdim=True) - spec_ta = F.spectrogram( - sound, pad=0, window=torch.hann_window(n_fft), n_fft=n_fft, - hop_length=hop_length, win_length=n_fft, power=2, normalized=False) - spec_lr = spec_ta.cpu().numpy().squeeze() - # Perform MelScale with torchaudio and librosa - melspec_ta = torchaudio.transforms.MelScale(n_mels=n_mels, sample_rate=sample_rate)(spec_ta) - melspec_lr = librosa.feature.melspectrogram( - S=spec_lr, sr=sample_rate, n_fft=n_fft, hop_length=hop_length, - win_length=n_fft, center=True, window='hann', n_mels=n_mels, htk=True, norm=None) - # Note: Using relaxed rtol instead of atol - self.assertEqual(melspec_ta, torch.from_numpy(melspec_lr[None, ...]), atol=1e-8, rtol=1e-3) - - def test_InverseMelScale(self): - """InverseMelScale transform is comparable to that of librosa""" - n_fft = 2048 - n_mels = 256 - n_stft = n_fft // 2 + 1 - hop_length = n_fft // 4 - - # Prepare mel spectrogram input. We use torchaudio to compute one. - path = common_utils.get_asset_path('steam-train-whistle-daniel_simon.wav') - sound, sample_rate = common_utils.load_wav(path) - sound = sound[:, 2**10:2**10 + 2**14] - sound = sound.mean(dim=0, keepdim=True) - spec_orig = F.spectrogram( - sound, pad=0, window=torch.hann_window(n_fft), n_fft=n_fft, - hop_length=hop_length, win_length=n_fft, power=2, normalized=False) - melspec_ta = torchaudio.transforms.MelScale(n_mels=n_mels, sample_rate=sample_rate)(spec_orig) - melspec_lr = melspec_ta.cpu().numpy().squeeze() - # Perform InverseMelScale with torch audio and librosa - spec_ta = torchaudio.transforms.InverseMelScale( - n_stft, n_mels=n_mels, sample_rate=sample_rate)(melspec_ta) - spec_lr = librosa.feature.inverse.mel_to_stft( - melspec_lr, sr=sample_rate, n_fft=n_fft, power=2.0, htk=True, norm=None) - spec_lr = torch.from_numpy(spec_lr[None, ...]) - - # Align dimensions - # librosa does not return power spectrogram while torchaudio returns power spectrogram - spec_orig = spec_orig.sqrt() - spec_ta = spec_ta.sqrt() - - threshold = 2.0 - # This threshold was choosen empirically, based on the following observation - # - # torch.dist(spec_lr, spec_ta, p=float('inf')) - # >>> tensor(1.9666) - # - # The spectrograms reconstructed by librosa and torchaudio are not comparable elementwise. - # This is because they use different approximation algorithms and resulting values can live - # in different magnitude. (although most of them are very close) - # See - # https://github.com/pytorch/audio/pull/366 for the discussion of the choice of algorithm - # https://github.com/pytorch/audio/pull/448/files#r385747021 for the distribution of P-inf - # distance over frequencies. - self.assertEqual(spec_ta, spec_lr, atol=threshold, rtol=1e-5) - - threshold = 1700.0 - # This threshold was choosen empirically, based on the following observations - # - # torch.dist(spec_orig, spec_ta, p=1) - # >>> tensor(1644.3516) - # torch.dist(spec_orig, spec_lr, p=1) - # >>> tensor(1420.7103) - # torch.dist(spec_lr, spec_ta, p=1) - # >>> tensor(943.2759) - assert torch.dist(spec_orig, spec_ta, p=1) < threshold diff --git a/test/torchaudio_unittest/sox_effect/dataset_test.py b/test/torchaudio_unittest/sox_effect/dataset_test.py index 7e89960186..0b8cc9c4d8 100644 --- a/test/torchaudio_unittest/sox_effect/dataset_test.py +++ b/test/torchaudio_unittest/sox_effect/dataset_test.py @@ -11,7 +11,7 @@ from torchaudio_unittest.common_utils import ( TempDirMixin, PytorchTestCase, - skipIfNoExtension, + skipIfNoSox, get_whitenoise, save_wav, ) @@ -71,7 +71,7 @@ def init_random_seed(worker_id): dataset.rng = np.random.RandomState(worker_id) -@skipIfNoExtension +@skipIfNoSox @skipIf( platform.system() == 'Darwin' and sys.version_info.major == 3 and @@ -134,7 +134,7 @@ def speed(path): return torchaudio.sox_effects.apply_effects_tensor(wav, sample_rate, effects)[0] -@skipIfNoExtension +@skipIfNoSox class TestProcessPoolExecutor(TempDirMixin, PytorchTestCase): backend = "sox_io" diff --git a/test/torchaudio_unittest/sox_effect/smoke_test.py b/test/torchaudio_unittest/sox_effect/smoke_test.py index 3b2b34d3ec..70a6a346ea 100644 --- a/test/torchaudio_unittest/sox_effect/smoke_test.py +++ b/test/torchaudio_unittest/sox_effect/smoke_test.py @@ -4,7 +4,7 @@ from torchaudio_unittest.common_utils import ( TempDirMixin, TorchaudioTestCase, - skipIfNoExtension, + skipIfNoSox, get_wav_data, get_sinusoid, save_wav, @@ -14,7 +14,7 @@ ) -@skipIfNoExtension +@skipIfNoSox class SmokeTest(TempDirMixin, TorchaudioTestCase): """Run smoke test on various effects @@ -25,7 +25,7 @@ class SmokeTest(TempDirMixin, TorchaudioTestCase): however without such tools, the correctness of each function cannot be verified. """ @parameterized.expand( - load_params("sox_effect_test_args.json"), + load_params("sox_effect_test_args.jsonl"), name_func=lambda f, i, p: f'{f.__name__}_{i}_{p.args[0]["effects"][0][0]}', ) def test_apply_effects_tensor(self, args): @@ -39,7 +39,7 @@ def test_apply_effects_tensor(self, args): _found, _sr = sox_effects.apply_effects_tensor(original, input_sr, effects) @parameterized.expand( - load_params("sox_effect_test_args.json"), + load_params("sox_effect_test_args.jsonl"), name_func=lambda f, i, p: f'{f.__name__}_{i}_{p.args[0]["effects"][0][0]}', ) def test_apply_effects_file(self, args): @@ -58,7 +58,7 @@ def test_apply_effects_file(self, args): input_path, effects, normalize=False, channels_first=channels_first) @parameterized.expand( - load_params("sox_effect_test_args.json"), + load_params("sox_effect_test_args.jsonl"), name_func=lambda f, i, p: f'{f.__name__}_{i}_{p.args[0]["effects"][0][0]}', ) def test_apply_effects_fileobj(self, args): diff --git a/test/torchaudio_unittest/sox_effect/sox_effect_test.py b/test/torchaudio_unittest/sox_effect/sox_effect_test.py index ab334613e3..ca93e7d41b 100644 --- a/test/torchaudio_unittest/sox_effect/sox_effect_test.py +++ b/test/torchaudio_unittest/sox_effect/sox_effect_test.py @@ -11,7 +11,7 @@ TempDirMixin, HttpServerMixin, PytorchTestCase, - skipIfNoExtension, + skipIfNoSox, skipIfNoModule, skipIfNoExec, get_asset_path, @@ -31,7 +31,7 @@ import requests -@skipIfNoExtension +@skipIfNoSox class TestSoxEffects(PytorchTestCase): def test_init(self): """Calling init_sox_effects multiple times does not crush""" @@ -39,7 +39,7 @@ def test_init(self): sox_effects.init_sox_effects() -@skipIfNoExtension +@skipIfNoSox class TestSoxEffectsTensor(TempDirMixin, PytorchTestCase): """Test suite for `apply_effects_tensor` function""" @parameterized.expand(list(itertools.product( @@ -64,7 +64,7 @@ def test_apply_no_effect(self, dtype, sample_rate, num_channels, channels_first) self.assertEqual(expected, found) @parameterized.expand( - load_params("sox_effect_test_args.json"), + load_params("sox_effect_test_args.jsonl"), name_func=lambda f, i, p: f'{f.__name__}_{i}_{p.args[0]["effects"][0][0]}', ) def test_apply_effects(self, args): @@ -91,7 +91,7 @@ def test_apply_effects(self, args): self.assertEqual(expected, found) -@skipIfNoExtension +@skipIfNoSox class TestSoxEffectsFile(TempDirMixin, PytorchTestCase): """Test suite for `apply_effects_file` function""" @parameterized.expand(list(itertools.product( @@ -113,7 +113,7 @@ def test_apply_no_effect(self, dtype, sample_rate, num_channels, channels_first) self.assertEqual(expected, found) @parameterized.expand( - load_params("sox_effect_test_args.json"), + load_params("sox_effect_test_args.jsonl"), name_func=lambda f, i, p: f'{f.__name__}_{i}_{p.args[0]["effects"][0][0]}', ) def test_apply_effects_str(self, args): @@ -163,7 +163,7 @@ def test_apply_effects_path(self): self.assertEqual(found, expected) -@skipIfNoExtension +@skipIfNoSox class TestFileFormats(TempDirMixin, PytorchTestCase): """`apply_effects_file` gives the same result as sox on various file formats""" @parameterized.expand(list(itertools.product( @@ -256,7 +256,7 @@ def test_vorbis(self, sample_rate, num_channels): self.assertEqual(found, expected) -@skipIfNoExtension +@skipIfNoSox class TestApplyEffectFileWithoutExtension(PytorchTestCase): def test_mp3(self): """Providing format allows to read mp3 without extension @@ -275,7 +275,7 @@ def test_mp3(self): @skipIfNoExec('sox') -@skipIfNoExtension +@skipIfNoSox class TestFileObject(TempDirMixin, PytorchTestCase): @parameterized.expand([ ('wav', None), @@ -384,7 +384,7 @@ def test_tarfile(self, ext, compression): self.assertEqual(found, expected) -@skipIfNoExtension +@skipIfNoSox @skipIfNoExec('sox') @skipIfNoModule("requests") class TestFileObjectHttp(HttpServerMixin, PytorchTestCase): diff --git a/test/torchaudio_unittest/sox_effect/torchscript_test.py b/test/torchaudio_unittest/sox_effect/torchscript_test.py index 8e1a9a3980..3940e72931 100644 --- a/test/torchaudio_unittest/sox_effect/torchscript_test.py +++ b/test/torchaudio_unittest/sox_effect/torchscript_test.py @@ -7,7 +7,7 @@ from torchaudio_unittest.common_utils import ( TempDirMixin, PytorchTestCase, - skipIfNoExtension, + skipIfNoSox, get_sinusoid, save_wav, ) @@ -43,10 +43,10 @@ def forward(self, path: str): return sox_effects.apply_effects_file(path, self.effects, self.channels_first) -@skipIfNoExtension +@skipIfNoSox class TestTorchScript(TempDirMixin, PytorchTestCase): @parameterized.expand( - load_params("sox_effect_test_args.json"), + load_params("sox_effect_test_args.jsonl"), name_func=lambda f, i, p: f'{f.__name__}_{i}_{p.args[0]["effects"][0][0]}', ) def test_apply_effects_tensor(self, args): @@ -72,7 +72,7 @@ def test_apply_effects_tensor(self, args): self.assertEqual(expected, found) @parameterized.expand( - load_params("sox_effect_test_args.json"), + load_params("sox_effect_test_args.jsonl"), name_func=lambda f, i, p: f'{f.__name__}_{i}_{p.args[0]["effects"][0][0]}', ) def test_apply_effects_file(self, args): diff --git a/test/torchaudio_unittest/transducer_test.py b/test/torchaudio_unittest/transducer_test.py index 3d8dc0683d..209794a5b5 100644 --- a/test/torchaudio_unittest/transducer_test.py +++ b/test/torchaudio_unittest/transducer_test.py @@ -1,7 +1,8 @@ +import unittest import torch from torchaudio.prototype.transducer import RNNTLoss -from torchaudio_unittest import common_utils +from torchaudio_unittest.common_utils import TorchaudioTestCase def get_data_basic(device): @@ -241,6 +242,14 @@ def compute_with_pytorch_transducer(data): return costs, gradients +def skipIfNoTransducer(test_item): + try: + torch.ops.torchaudio.rnnt_loss + return test_item + except RuntimeError: + return unittest.skip("torchaudio C++ extension is not compiled with RNN transducer loss")(test_item) + + class TransducerTester: def test_basic_fp16_error(self): rnnt_loss = RNNTLoss() @@ -271,6 +280,6 @@ def test_costs_and_gradients_B2_T4_U3_D3_fp32(self): self.assertEqual(gradients, ref_gradients, atol=atol, rtol=rtol) -@common_utils.skipIfNoExtension -class CPUTransducerTester(TransducerTester, common_utils.PytorchTestCase): +@skipIfNoTransducer +class CPUTransducerTester(TransducerTester, TorchaudioTestCase): device = "cpu" diff --git a/test/torchaudio_unittest/transforms/__init__.py b/test/torchaudio_unittest/transforms/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/test/torchaudio_unittest/batch_consistency_test.py b/test/torchaudio_unittest/transforms/batch_consistency_test.py similarity index 54% rename from test/torchaudio_unittest/batch_consistency_test.py rename to test/torchaudio_unittest/transforms/batch_consistency_test.py index 4644fe7dd3..745401c328 100644 --- a/test/torchaudio_unittest/batch_consistency_test.py +++ b/test/torchaudio_unittest/transforms/batch_consistency_test.py @@ -1,176 +1,10 @@ """Test numerical consistency among single input and batched input.""" -import itertools -from parameterized import parameterized - -import math - import torch import torchaudio -import torchaudio.functional as F from torchaudio_unittest import common_utils -class TestFunctional(common_utils.TorchaudioTestCase): - backend = 'default' - """Test functions defined in `functional` module""" - def assert_batch_consistency( - self, functional, tensor, *args, batch_size=1, atol=1e-8, rtol=1e-5, seed=42, **kwargs): - # run then batch the result - torch.random.manual_seed(seed) - expected = functional(tensor.clone(), *args, **kwargs) - expected = expected.repeat([batch_size] + [1] * expected.dim()) - - # batch the input and run - torch.random.manual_seed(seed) - pattern = [batch_size] + [1] * tensor.dim() - computed = functional(tensor.repeat(pattern), *args, **kwargs) - - self.assertEqual(computed, expected, rtol=rtol, atol=atol) - - def assert_batch_consistencies( - self, functional, tensor, *args, atol=1e-8, rtol=1e-5, seed=42, **kwargs): - self.assert_batch_consistency( - functional, tensor, *args, batch_size=1, atol=atol, rtol=rtol, seed=seed, **kwargs) - self.assert_batch_consistency( - functional, tensor, *args, batch_size=3, atol=atol, rtol=rtol, seed=seed, **kwargs) - - def test_griffinlim(self): - n_fft = 400 - ws = 400 - hop = 200 - window = torch.hann_window(ws) - power = 2 - normalize = False - momentum = 0.99 - n_iter = 32 - length = 1000 - tensor = torch.rand((1, 201, 6)) - self.assert_batch_consistencies( - F.griffinlim, tensor, window, n_fft, hop, ws, power, normalize, n_iter, momentum, length, 0, atol=5e-5 - ) - - @parameterized.expand(list(itertools.product( - [100, 440], - [8000, 16000, 44100], - [1, 2], - )), name_func=lambda f, _, p: f'{f.__name__}_{"_".join(str(arg) for arg in p.args)}') - def test_detect_pitch_frequency(self, frequency, sample_rate, n_channels): - waveform = common_utils.get_sinusoid(frequency=frequency, sample_rate=sample_rate, - n_channels=n_channels, duration=5) - self.assert_batch_consistencies(F.detect_pitch_frequency, waveform, sample_rate) - - def test_amplitude_to_DB(self): - torch.manual_seed(0) - spec = torch.rand(2, 100, 100) * 200 - - amplitude_mult = 20. - amin = 1e-10 - ref = 1.0 - db_mult = math.log10(max(amin, ref)) - - # Test with & without a `top_db` clamp - self.assert_batch_consistencies(F.amplitude_to_DB, spec, amplitude_mult, - amin, db_mult, top_db=None) - self.assert_batch_consistencies(F.amplitude_to_DB, spec, amplitude_mult, - amin, db_mult, top_db=40.) - - def test_amplitude_to_DB_itemwise_clamps(self): - """Ensure that the clamps are separate for each spectrogram in a batch. - - The clamp was determined per-batch in a prior implementation, which - meant it was determined by the loudest item, thus items weren't - independent. See: - - https://github.com/pytorch/audio/issues/994 - - """ - amplitude_mult = 20. - amin = 1e-10 - ref = 1.0 - db_mult = math.log10(max(amin, ref)) - top_db = 20. - - # Make a batch of noise - torch.manual_seed(0) - spec = torch.rand([2, 2, 100, 100]) * 200 - # Make one item blow out the other - spec[0] += 50 - - batchwise_dbs = F.amplitude_to_DB(spec, amplitude_mult, amin, - db_mult, top_db=top_db) - itemwise_dbs = torch.stack([ - F.amplitude_to_DB(item, amplitude_mult, amin, - db_mult, top_db=top_db) - for item in spec - ]) - - self.assertEqual(batchwise_dbs, itemwise_dbs) - - def test_amplitude_to_DB_not_channelwise_clamps(self): - """Check that clamps are applied per-item, not per channel.""" - amplitude_mult = 20. - amin = 1e-10 - ref = 1.0 - db_mult = math.log10(max(amin, ref)) - top_db = 40. - - torch.manual_seed(0) - spec = torch.rand([1, 2, 100, 100]) * 200 - # Make one channel blow out the other - spec[:, 0] += 50 - - specwise_dbs = F.amplitude_to_DB(spec, amplitude_mult, amin, - db_mult, top_db=top_db) - channelwise_dbs = torch.stack([ - F.amplitude_to_DB(spec[:, i], amplitude_mult, amin, - db_mult, top_db=top_db) - for i in range(spec.size(-3)) - ]) - - # Just check channelwise gives a different answer. - difference = (specwise_dbs - channelwise_dbs).abs() - assert (difference >= 1e-5).any() - - def test_contrast(self): - waveform = torch.rand(2, 100) - 0.5 - self.assert_batch_consistencies(F.contrast, waveform, enhancement_amount=80.) - - def test_dcshift(self): - waveform = torch.rand(2, 100) - 0.5 - self.assert_batch_consistencies(F.dcshift, waveform, shift=0.5, limiter_gain=0.05) - - def test_overdrive(self): - waveform = torch.rand(2, 100) - 0.5 - self.assert_batch_consistencies(F.overdrive, waveform, gain=45, colour=30) - - def test_phaser(self): - sample_rate = 44100 - waveform = common_utils.get_whitenoise( - sample_rate=sample_rate, duration=5, - ) - self.assert_batch_consistencies(F.phaser, waveform, sample_rate) - - def test_flanger(self): - torch.random.manual_seed(40) - waveform = torch.rand(2, 100) - 0.5 - sample_rate = 44100 - self.assert_batch_consistencies(F.flanger, waveform, sample_rate) - - def test_sliding_window_cmn(self): - waveform = torch.randn(2, 1024) - 0.5 - self.assert_batch_consistencies(F.sliding_window_cmn, waveform, center=True, norm_vars=True) - self.assert_batch_consistencies(F.sliding_window_cmn, waveform, center=True, norm_vars=False) - self.assert_batch_consistencies(F.sliding_window_cmn, waveform, center=False, norm_vars=True) - self.assert_batch_consistencies(F.sliding_window_cmn, waveform, center=False, norm_vars=False) - - def test_vad(self): - common_utils.set_audio_backend('default') - filepath = common_utils.get_asset_path("vad-go-mono-32000.wav") - waveform, sample_rate = torchaudio.load(filepath) - self.assert_batch_consistencies(F.vad, waveform, sample_rate=sample_rate) - - class TestTransforms(common_utils.TorchaudioTestCase): backend = 'default' diff --git a/test/torchaudio_unittest/kaldi_compatibility_cpu_test.py b/test/torchaudio_unittest/transforms/kaldi_compatibility_cpu_test.py similarity index 100% rename from test/torchaudio_unittest/kaldi_compatibility_cpu_test.py rename to test/torchaudio_unittest/transforms/kaldi_compatibility_cpu_test.py diff --git a/test/torchaudio_unittest/kaldi_compatibility_cuda_test.py b/test/torchaudio_unittest/transforms/kaldi_compatibility_cuda_test.py similarity index 100% rename from test/torchaudio_unittest/kaldi_compatibility_cuda_test.py rename to test/torchaudio_unittest/transforms/kaldi_compatibility_cuda_test.py diff --git a/test/torchaudio_unittest/transforms/kaldi_compatibility_impl.py b/test/torchaudio_unittest/transforms/kaldi_compatibility_impl.py new file mode 100644 index 0000000000..9a0e6ab81d --- /dev/null +++ b/test/torchaudio_unittest/transforms/kaldi_compatibility_impl.py @@ -0,0 +1,55 @@ +"""Test suites for checking numerical compatibility against Kaldi""" +import torchaudio.compliance.kaldi +from parameterized import parameterized + +from torchaudio_unittest.common_utils import ( + TestBaseMixin, + TempDirMixin, + load_params, + skipIfNoExec, + get_asset_path, + load_wav, +) +from torchaudio_unittest.common_utils.kaldi_utils import ( + convert_args, + run_kaldi, +) + + +class Kaldi(TempDirMixin, TestBaseMixin): + def assert_equal(self, output, *, expected, rtol=None, atol=None): + expected = expected.to(dtype=self.dtype, device=self.device) + self.assertEqual(output, expected, rtol=rtol, atol=atol) + + @parameterized.expand(load_params('kaldi_test_fbank_args.jsonl')) + @skipIfNoExec('compute-fbank-feats') + def test_fbank(self, kwargs): + """fbank should be numerically compatible with compute-fbank-feats""" + wave_file = get_asset_path('kaldi_file.wav') + waveform = load_wav(wave_file, normalize=False)[0].to(dtype=self.dtype, device=self.device) + result = torchaudio.compliance.kaldi.fbank(waveform, **kwargs) + command = ['compute-fbank-feats'] + convert_args(**kwargs) + ['scp:-', 'ark:-'] + kaldi_result = run_kaldi(command, 'scp', wave_file) + self.assert_equal(result, expected=kaldi_result, rtol=1e-4, atol=1e-8) + + @parameterized.expand(load_params('kaldi_test_spectrogram_args.jsonl')) + @skipIfNoExec('compute-spectrogram-feats') + def test_spectrogram(self, kwargs): + """spectrogram should be numerically compatible with compute-spectrogram-feats""" + wave_file = get_asset_path('kaldi_file.wav') + waveform = load_wav(wave_file, normalize=False)[0].to(dtype=self.dtype, device=self.device) + result = torchaudio.compliance.kaldi.spectrogram(waveform, **kwargs) + command = ['compute-spectrogram-feats'] + convert_args(**kwargs) + ['scp:-', 'ark:-'] + kaldi_result = run_kaldi(command, 'scp', wave_file) + self.assert_equal(result, expected=kaldi_result, rtol=1e-4, atol=1e-8) + + @parameterized.expand(load_params('kaldi_test_mfcc_args.jsonl')) + @skipIfNoExec('compute-mfcc-feats') + def test_mfcc(self, kwargs): + """mfcc should be numerically compatible with compute-mfcc-feats""" + wave_file = get_asset_path('kaldi_file.wav') + waveform = load_wav(wave_file, normalize=False)[0].to(dtype=self.dtype, device=self.device) + result = torchaudio.compliance.kaldi.mfcc(waveform, **kwargs) + command = ['compute-mfcc-feats'] + convert_args(**kwargs) + ['scp:-', 'ark:-'] + kaldi_result = run_kaldi(command, 'scp', wave_file) + self.assert_equal(result, expected=kaldi_result, rtol=1e-4, atol=1e-8) diff --git a/test/torchaudio_unittest/transforms/librosa_compatibility_test.py b/test/torchaudio_unittest/transforms/librosa_compatibility_test.py new file mode 100644 index 0000000000..c954100f35 --- /dev/null +++ b/test/torchaudio_unittest/transforms/librosa_compatibility_test.py @@ -0,0 +1,245 @@ +"""Test suites for numerical compatibility with librosa""" +import os +import unittest + +import torch +import torchaudio +import torchaudio.functional as F +from torchaudio._internal.module_utils import is_module_available +from parameterized import parameterized, param + +LIBROSA_AVAILABLE = is_module_available('librosa') + +if LIBROSA_AVAILABLE: + import librosa + import scipy + +from torchaudio_unittest import common_utils + + +def _load_audio_asset(*asset_paths, **kwargs): + file_path = common_utils.get_asset_path(*asset_paths) + sound, sample_rate = torchaudio.load(file_path, **kwargs) + return sound, sample_rate + + +@unittest.skipIf(not LIBROSA_AVAILABLE, "Librosa not available") +class TestTransforms(common_utils.TorchaudioTestCase): + """Test suite for functions in `transforms` module.""" + + @parameterized.expand([ + param(n_fft=400, hop_length=200, power=2.0), + param(n_fft=600, hop_length=100, power=2.0), + param(n_fft=400, hop_length=200, power=3.0), + param(n_fft=200, hop_length=50, power=2.0), + ]) + def test_spectrogram(self, n_fft, hop_length, power): + sample_rate = 16000 + sound = common_utils.get_sinusoid(n_channels=1, sample_rate=sample_rate) + sound_librosa = sound.cpu().numpy().squeeze() + spect_transform = torchaudio.transforms.Spectrogram( + n_fft=n_fft, hop_length=hop_length, power=power) + out_librosa, _ = librosa.core.spectrum._spectrogram( + y=sound_librosa, n_fft=n_fft, hop_length=hop_length, power=power) + + out_torch = spect_transform(sound).squeeze().cpu() + self.assertEqual(out_torch, torch.from_numpy(out_librosa), atol=1e-5, rtol=1e-5) + + @parameterized.expand([ + param(norm=norm, mel_scale=mel_scale, **p.kwargs) + for p in [ + param(n_fft=400, hop_length=200, n_mels=128), + param(n_fft=600, hop_length=100, n_mels=128), + param(n_fft=200, hop_length=50, n_mels=128), + ] + for norm in [None, 'slaney'] + for mel_scale in ['htk', 'slaney'] + ]) + def test_mel_spectrogram(self, n_fft, hop_length, n_mels, norm, mel_scale): + sample_rate = 16000 + sound = common_utils.get_sinusoid(n_channels=1, sample_rate=sample_rate) + sound_librosa = sound.cpu().numpy().squeeze() + melspect_transform = torchaudio.transforms.MelSpectrogram( + sample_rate=sample_rate, window_fn=torch.hann_window, + hop_length=hop_length, n_mels=n_mels, n_fft=n_fft, norm=norm, mel_scale=mel_scale) + librosa_mel = librosa.feature.melspectrogram( + y=sound_librosa, sr=sample_rate, n_fft=n_fft, + hop_length=hop_length, n_mels=n_mels, htk=mel_scale == "htk", norm=norm) + librosa_mel_tensor = torch.from_numpy(librosa_mel) + torch_mel = melspect_transform(sound).squeeze().cpu() + self.assertEqual( + torch_mel.type(librosa_mel_tensor.dtype), librosa_mel_tensor, atol=5e-3, rtol=1e-5) + + @parameterized.expand([ + param(norm=norm, mel_scale=mel_scale, **p.kwargs) + for p in [ + param(n_fft=400, hop_length=200, power=2.0, n_mels=128), + param(n_fft=600, hop_length=100, power=2.0, n_mels=128), + param(n_fft=400, hop_length=200, power=3.0, n_mels=128), + # NOTE: Test passes offline, but fails on TravisCI (and CircleCI), see #372. + param(n_fft=200, hop_length=50, power=2.0, n_mels=128, skip_ci=True), + ] + for norm in [None, 'slaney'] + for mel_scale in ['htk', 'slaney'] + ]) + def test_s2db(self, n_fft, hop_length, power, n_mels, norm, mel_scale, skip_ci=False): + if skip_ci and 'CI' in os.environ: + self.skipTest('Test is known to fail on CI') + sample_rate = 16000 + sound = common_utils.get_sinusoid(n_channels=1, sample_rate=sample_rate) + sound_librosa = sound.cpu().numpy().squeeze() + spect_transform = torchaudio.transforms.Spectrogram( + n_fft=n_fft, hop_length=hop_length, power=power) + out_librosa, _ = librosa.core.spectrum._spectrogram( + y=sound_librosa, n_fft=n_fft, hop_length=hop_length, power=power) + melspect_transform = torchaudio.transforms.MelSpectrogram( + sample_rate=sample_rate, window_fn=torch.hann_window, + hop_length=hop_length, n_mels=n_mels, n_fft=n_fft, norm=norm, mel_scale=mel_scale) + librosa_mel = librosa.feature.melspectrogram( + y=sound_librosa, sr=sample_rate, n_fft=n_fft, + hop_length=hop_length, n_mels=n_mels, htk=mel_scale == "htk", norm=norm) + + power_to_db_transform = torchaudio.transforms.AmplitudeToDB('power', 80.) + power_to_db_torch = power_to_db_transform(spect_transform(sound)).squeeze().cpu() + power_to_db_librosa = librosa.core.spectrum.power_to_db(out_librosa) + self.assertEqual(power_to_db_torch, torch.from_numpy(power_to_db_librosa), atol=5e-3, rtol=1e-5) + + mag_to_db_transform = torchaudio.transforms.AmplitudeToDB('magnitude', 80.) + mag_to_db_torch = mag_to_db_transform(torch.abs(sound)).squeeze().cpu() + mag_to_db_librosa = librosa.core.spectrum.amplitude_to_db(sound_librosa) + self.assertEqual(mag_to_db_torch, torch.from_numpy(mag_to_db_librosa), atol=5e-3, rtol=1e-5) + + power_to_db_torch = power_to_db_transform(melspect_transform(sound)).squeeze().cpu() + db_librosa = librosa.core.spectrum.power_to_db(librosa_mel) + db_librosa_tensor = torch.from_numpy(db_librosa) + self.assertEqual( + power_to_db_torch.type(db_librosa_tensor.dtype), db_librosa_tensor, atol=5e-3, rtol=1e-5) + + @parameterized.expand([ + param(n_fft=400, hop_length=200, n_mels=128, n_mfcc=40), + param(n_fft=600, hop_length=100, n_mels=128, n_mfcc=20), + param(n_fft=200, hop_length=50, n_mels=128, n_mfcc=50), + ]) + def test_mfcc(self, n_fft, hop_length, n_mels, n_mfcc): + sample_rate = 16000 + sound = common_utils.get_sinusoid(n_channels=1, sample_rate=sample_rate) + sound_librosa = sound.cpu().numpy().squeeze() + librosa_mel = librosa.feature.melspectrogram( + y=sound_librosa, sr=sample_rate, n_fft=n_fft, + hop_length=hop_length, n_mels=n_mels, htk=True, norm=None) + db_librosa = librosa.core.spectrum.power_to_db(librosa_mel) + + # librosa.feature.mfcc doesn't pass kwargs properly since some of the + # kwargs for melspectrogram and mfcc are the same. We just follow the + # function body in + # https://librosa.github.io/librosa/_modules/librosa/feature/spectral.html#melspectrogram + # to mirror this function call with correct args: + # + # librosa_mfcc = librosa.feature.mfcc( + # y=sound_librosa, sr=sample_rate, n_mfcc = n_mfcc, + # hop_length=hop_length, n_fft=n_fft, htk=True, norm=None, n_mels=n_mels) + + librosa_mfcc = scipy.fftpack.dct(db_librosa, axis=0, type=2, norm='ortho')[:n_mfcc] + librosa_mfcc_tensor = torch.from_numpy(librosa_mfcc) + + melkwargs = {'hop_length': hop_length, 'n_fft': n_fft} + mfcc_transform = torchaudio.transforms.MFCC( + sample_rate=sample_rate, n_mfcc=n_mfcc, norm='ortho', melkwargs=melkwargs) + torch_mfcc = mfcc_transform(sound).squeeze().cpu() + + self.assertEqual( + torch_mfcc.type(librosa_mfcc_tensor.dtype), librosa_mfcc_tensor, atol=5e-3, rtol=1e-5) + + @parameterized.expand([ + param(n_fft=400, hop_length=200), + param(n_fft=600, hop_length=100), + param(n_fft=200, hop_length=50), + ]) + def test_spectral_centroid(self, n_fft, hop_length): + sample_rate = 16000 + sound = common_utils.get_sinusoid(n_channels=1, sample_rate=sample_rate) + sound_librosa = sound.cpu().numpy().squeeze() + spect_centroid = torchaudio.transforms.SpectralCentroid( + sample_rate=sample_rate, n_fft=n_fft, hop_length=hop_length) + out_torch = spect_centroid(sound).squeeze().cpu() + + out_librosa = librosa.feature.spectral_centroid( + y=sound_librosa, sr=sample_rate, n_fft=n_fft, hop_length=hop_length) + out_librosa = torch.from_numpy(out_librosa)[0] + + self.assertEqual(out_torch.type(out_librosa.dtype), out_librosa, atol=1e-5, rtol=1e-5) + + def test_MelScale(self): + """MelScale transform is comparable to that of librosa""" + n_fft = 2048 + n_mels = 256 + hop_length = n_fft // 4 + sample_rate = 44100 + sound = common_utils.get_whitenoise(sample_rate=sample_rate, duration=60) + sound = sound.mean(dim=0, keepdim=True) + spec_ta = F.spectrogram( + sound, pad=0, window=torch.hann_window(n_fft), n_fft=n_fft, + hop_length=hop_length, win_length=n_fft, power=2, normalized=False) + spec_lr = spec_ta.cpu().numpy().squeeze() + # Perform MelScale with torchaudio and librosa + melspec_ta = torchaudio.transforms.MelScale(n_mels=n_mels, sample_rate=sample_rate)(spec_ta) + melspec_lr = librosa.feature.melspectrogram( + S=spec_lr, sr=sample_rate, n_fft=n_fft, hop_length=hop_length, + win_length=n_fft, center=True, window='hann', n_mels=n_mels, htk=True, norm=None) + # Note: Using relaxed rtol instead of atol + self.assertEqual(melspec_ta, torch.from_numpy(melspec_lr[None, ...]), atol=1e-8, rtol=1e-3) + + def test_InverseMelScale(self): + """InverseMelScale transform is comparable to that of librosa""" + n_fft = 2048 + n_mels = 256 + n_stft = n_fft // 2 + 1 + hop_length = n_fft // 4 + + # Prepare mel spectrogram input. We use torchaudio to compute one. + path = common_utils.get_asset_path('steam-train-whistle-daniel_simon.wav') + sound, sample_rate = common_utils.load_wav(path) + sound = sound[:, 2**10:2**10 + 2**14] + sound = sound.mean(dim=0, keepdim=True) + spec_orig = F.spectrogram( + sound, pad=0, window=torch.hann_window(n_fft), n_fft=n_fft, + hop_length=hop_length, win_length=n_fft, power=2, normalized=False) + melspec_ta = torchaudio.transforms.MelScale(n_mels=n_mels, sample_rate=sample_rate)(spec_orig) + melspec_lr = melspec_ta.cpu().numpy().squeeze() + # Perform InverseMelScale with torch audio and librosa + spec_ta = torchaudio.transforms.InverseMelScale( + n_stft, n_mels=n_mels, sample_rate=sample_rate)(melspec_ta) + spec_lr = librosa.feature.inverse.mel_to_stft( + melspec_lr, sr=sample_rate, n_fft=n_fft, power=2.0, htk=True, norm=None) + spec_lr = torch.from_numpy(spec_lr[None, ...]) + + # Align dimensions + # librosa does not return power spectrogram while torchaudio returns power spectrogram + spec_orig = spec_orig.sqrt() + spec_ta = spec_ta.sqrt() + + threshold = 2.0 + # This threshold was chosen empirically, based on the following observation + # + # torch.dist(spec_lr, spec_ta, p=float('inf')) + # >>> tensor(1.9666) + # + # The spectrograms reconstructed by librosa and torchaudio are not comparable elementwise. + # This is because they use different approximation algorithms and resulting values can live + # in different magnitude. (although most of them are very close) + # See + # https://github.com/pytorch/audio/pull/366 for the discussion of the choice of algorithm + # https://github.com/pytorch/audio/pull/448/files#r385747021 for the distribution of P-inf + # distance over frequencies. + self.assertEqual(spec_ta, spec_lr, atol=threshold, rtol=1e-5) + + threshold = 1700.0 + # This threshold was chosen empirically, based on the following observations + # + # torch.dist(spec_orig, spec_ta, p=1) + # >>> tensor(1644.3516) + # torch.dist(spec_orig, spec_lr, p=1) + # >>> tensor(1420.7103) + # torch.dist(spec_lr, spec_ta, p=1) + # >>> tensor(943.2759) + assert torch.dist(spec_orig, spec_ta, p=1) < threshold diff --git a/test/torchaudio_unittest/transforms/sox_compatibility_test.py b/test/torchaudio_unittest/transforms/sox_compatibility_test.py new file mode 100644 index 0000000000..4bf6bf7884 --- /dev/null +++ b/test/torchaudio_unittest/transforms/sox_compatibility_test.py @@ -0,0 +1,53 @@ +import torchaudio.transforms as T +from parameterized import parameterized + +from torchaudio_unittest.common_utils import ( + skipIfNoSoxBackend, + skipIfNoExec, + TempDirMixin, + TorchaudioTestCase, + get_asset_path, + sox_utils, + load_wav, +) + + +@skipIfNoSoxBackend +@skipIfNoExec('sox') +class TestFunctionalFiltering(TempDirMixin, TorchaudioTestCase): + def run_sox_effect(self, input_file, effect): + output_file = self.get_temp_path('expected.wav') + sox_utils.run_sox_effect(input_file, output_file, [str(e) for e in effect]) + return load_wav(output_file) + + def assert_sox_effect(self, result, input_path, effects, atol=1e-04, rtol=1e-5): + expected, _ = self.run_sox_effect(input_path, effects) + self.assertEqual(result, expected, atol=atol, rtol=rtol) + + @parameterized.expand([ + ('q', 'quarter_sine'), + ('h', 'half_sine'), + ('t', 'linear'), + ]) + def test_fade(self, fade_shape_sox, fade_shape): + fade_in_len, fade_out_len = 44100, 44100 + data, path = self.get_whitenoise(sample_rate=44100) + result = T.Fade(fade_in_len, fade_out_len, fade_shape)(data) + self.assert_sox_effect(result, path, ['fade', fade_shape_sox, '1', '0', '1']) + + @parameterized.expand([ + ('amplitude', 1.1), + ('db', 2), + ('power', 2), + ]) + def test_vol(self, gain_type, gain): + data, path = self.get_whitenoise() + result = T.Vol(gain, gain_type)(data) + self.assert_sox_effect(result, path, ['vol', f'{gain}', gain_type]) + + @parameterized.expand(['vad-go-stereo-44100.wav', 'vad-go-mono-32000.wav']) + def test_vad(self, filename): + path = get_asset_path(filename) + data, sample_rate = load_wav(path) + result = T.Vad(sample_rate)(data) + self.assert_sox_effect(result, path, ['vad']) diff --git a/test/torchaudio_unittest/torchscript_consistency_cpu_test.py b/test/torchaudio_unittest/transforms/torchscript_consistency_cpu_test.py similarity index 100% rename from test/torchaudio_unittest/torchscript_consistency_cpu_test.py rename to test/torchaudio_unittest/transforms/torchscript_consistency_cpu_test.py diff --git a/test/torchaudio_unittest/torchscript_consistency_cuda_test.py b/test/torchaudio_unittest/transforms/torchscript_consistency_cuda_test.py similarity index 100% rename from test/torchaudio_unittest/torchscript_consistency_cuda_test.py rename to test/torchaudio_unittest/transforms/torchscript_consistency_cuda_test.py diff --git a/test/torchaudio_unittest/torchscript_consistency_impl.py b/test/torchaudio_unittest/transforms/torchscript_consistency_impl.py similarity index 100% rename from test/torchaudio_unittest/torchscript_consistency_impl.py rename to test/torchaudio_unittest/transforms/torchscript_consistency_impl.py diff --git a/test/torchaudio_unittest/transforms_test.py b/test/torchaudio_unittest/transforms/transforms_test.py similarity index 100% rename from test/torchaudio_unittest/transforms_test.py rename to test/torchaudio_unittest/transforms/transforms_test.py diff --git a/test/torchaudio_unittest/utils/sox_utils_test.py b/test/torchaudio_unittest/utils/sox_utils_test.py index 7c206fdc0b..7bd9018437 100644 --- a/test/torchaudio_unittest/utils/sox_utils_test.py +++ b/test/torchaudio_unittest/utils/sox_utils_test.py @@ -2,11 +2,11 @@ from torchaudio_unittest.common_utils import ( PytorchTestCase, - skipIfNoExtension, + skipIfNoSox, ) -@skipIfNoExtension +@skipIfNoSox class TestSoxUtils(PytorchTestCase): """Smoke tests for sox_util module""" def test_set_seed(self): diff --git a/third_party/CMakeLists.txt b/third_party/CMakeLists.txt index 3e1ab962fe..bb3a469055 100644 --- a/third_party/CMakeLists.txt +++ b/third_party/CMakeLists.txt @@ -10,12 +10,16 @@ if (BUILD_SOX) add_subdirectory(sox) target_include_directories(libsox INTERFACE ${SOX_INCLUDE_DIR}) target_link_libraries(libsox INTERFACE ${SOX_LIBRARIES}) -else() - # If not building and linking libsox statically, then we expect that - # sox library and header are found in search path - target_link_libraries(libsox INTERFACE -lsox) + list(APPEND TORCHAUDIO_THIRD_PARTIES libsox) +endif() + +################################################################################ +# kaldi +################################################################################ +if (BUILD_KALDI) + add_subdirectory(kaldi) + list(APPEND TORCHAUDIO_THIRD_PARTIES kaldi) endif() -list(APPEND TORCHAUDIO_THIRD_PARTIES libsox) ################################################################################ # transducer diff --git a/third_party/kaldi/CMakeLists.txt b/third_party/kaldi/CMakeLists.txt new file mode 100644 index 0000000000..6f891f8d1a --- /dev/null +++ b/third_party/kaldi/CMakeLists.txt @@ -0,0 +1,30 @@ +set(KALDI_REPO ${CMAKE_CURRENT_SOURCE_DIR}/submodule) + +# Apply custom patch +execute_process( + WORKING_DIRECTORY ${KALDI_REPO} + COMMAND "git" "checkout" "." + ) +execute_process( + WORKING_DIRECTORY ${KALDI_REPO} + COMMAND git apply ../kaldi.patch + ) +# Update the version string +execute_process( + WORKING_DIRECTORY ${KALDI_REPO}/src/base + COMMAND sh get_version.sh + ) + +set(KALDI_SOURCES + src/matrix/kaldi-vector.cc + src/matrix/kaldi-matrix.cc + submodule/src/base/kaldi-error.cc + submodule/src/base/kaldi-math.cc + submodule/src/feat/feature-functions.cc + submodule/src/feat/pitch-functions.cc + submodule/src/feat/resample.cc + ) + +add_library(kaldi STATIC ${KALDI_SOURCES}) +target_include_directories(kaldi PUBLIC src submodule/src) +target_link_libraries(kaldi ${TORCH_LIBRARIES}) diff --git a/third_party/kaldi/README.md b/third_party/kaldi/README.md new file mode 100644 index 0000000000..58c48747a8 --- /dev/null +++ b/third_party/kaldi/README.md @@ -0,0 +1,6 @@ +# Custom Kaldi build + +This directory contains original Kaldi repository (as submodule), [the custom implementation of Kaldi's vector/matrix](./src) and the build script. + +We use the custom build process so that the resulting library only contains what torchaudio needs. +We use the custom vector/matrix implementation so that we can use the same BLAS library that PyTorch is compiled with, and so that we can (hopefully, in future) take advantage of other PyTorch features (such as differentiability and GPU support). The down side of this approach is that it adds a lot of overhead compared to the original Kaldi (operator dispatch and element-wise processing, which PyTorch is not efficient at). We can improve this gradually, and if you are interested in helping, please let us know by opening an issue. \ No newline at end of file diff --git a/third_party/kaldi/kaldi.patch b/third_party/kaldi/kaldi.patch new file mode 100644 index 0000000000..40667bced8 --- /dev/null +++ b/third_party/kaldi/kaldi.patch @@ -0,0 +1,76 @@ +diff --git a/src/base/kaldi-types.h b/src/base/kaldi-types.h +index 7ebf4f853..c15b288b2 100644 +--- a/src/base/kaldi-types.h ++++ b/src/base/kaldi-types.h +@@ -41,6 +41,7 @@ typedef float BaseFloat; + + // for discussion on what to do if you need compile kaldi + // without OpenFST, see the bottom of this this file ++/* + #include + + namespace kaldi { +@@ -53,10 +54,10 @@ namespace kaldi { + typedef float float32; + typedef double double64; + } // end namespace kaldi ++*/ + + // In a theoretical case you decide compile Kaldi without the OpenFST + // comment the previous namespace statement and uncomment the following +-/* + namespace kaldi { + typedef int8_t int8; + typedef int16_t int16; +@@ -70,6 +71,5 @@ namespace kaldi { + typedef float float32; + typedef double double64; + } // end namespace kaldi +-*/ + + #endif // KALDI_BASE_KALDI_TYPES_H_ +diff --git a/src/matrix/matrix-lib.h b/src/matrix/matrix-lib.h +index b6059b06c..4fb9e1b16 100644 +--- a/src/matrix/matrix-lib.h ++++ b/src/matrix/matrix-lib.h +@@ -25,14 +25,14 @@ + #include "base/kaldi-common.h" + #include "matrix/kaldi-vector.h" + #include "matrix/kaldi-matrix.h" +-#include "matrix/sp-matrix.h" +-#include "matrix/tp-matrix.h" ++// #include "matrix/sp-matrix.h" ++// #include "matrix/tp-matrix.h" + #include "matrix/matrix-functions.h" + #include "matrix/srfft.h" + #include "matrix/compressed-matrix.h" +-#include "matrix/sparse-matrix.h" ++// #include "matrix/sparse-matrix.h" + #include "matrix/optimization.h" +-#include "matrix/numpy-array.h" ++// #include "matrix/numpy-array.h" + + #endif + +diff --git a/src/util/common-utils.h b/src/util/common-utils.h +index cfb0c255c..48d199e97 100644 +--- a/src/util/common-utils.h ++++ b/src/util/common-utils.h +@@ -21,11 +21,11 @@ + + #include "base/kaldi-common.h" + #include "util/parse-options.h" +-#include "util/kaldi-io.h" +-#include "util/simple-io-funcs.h" +-#include "util/kaldi-holder.h" +-#include "util/kaldi-table.h" +-#include "util/table-types.h" +-#include "util/text-utils.h" ++// #include "util/kaldi-io.h" ++// #include "util/simple-io-funcs.h" ++// #include "util/kaldi-holder.h" ++// #include "util/kaldi-table.h" ++// #include "util/table-types.h" ++// #include "util/text-utils.h" + + #endif // KALDI_UTIL_COMMON_UTILS_H_ diff --git a/third_party/kaldi/src/matrix/kaldi-matrix.cc b/third_party/kaldi/src/matrix/kaldi-matrix.cc new file mode 100644 index 0000000000..a89c3809c9 --- /dev/null +++ b/third_party/kaldi/src/matrix/kaldi-matrix.cc @@ -0,0 +1,39 @@ +#include "matrix/kaldi-matrix.h" +#include + +namespace { + +template +void assert_matrix_shape(const torch::Tensor& tensor_); + +template <> +void assert_matrix_shape(const torch::Tensor& tensor_) { + TORCH_INTERNAL_ASSERT(tensor_.ndimension() == 2); + TORCH_INTERNAL_ASSERT(tensor_.dtype() == torch::kFloat32); + TORCH_CHECK(tensor_.device().is_cpu(), "Input tensor has to be on CPU."); +} + +template <> +void assert_matrix_shape(const torch::Tensor& tensor_) { + TORCH_INTERNAL_ASSERT(tensor_.ndimension() == 2); + TORCH_INTERNAL_ASSERT(tensor_.dtype() == torch::kFloat64); + TORCH_CHECK(tensor_.device().is_cpu(), "Input tensor has to be on CPU."); +} + +} // namespace + +namespace kaldi { + +template +MatrixBase::MatrixBase(torch::Tensor tensor) : tensor_(tensor) { + assert_matrix_shape(tensor_); +}; + +template class Matrix; +template class Matrix; +template class MatrixBase; +template class MatrixBase; +template class SubMatrix; +template class SubMatrix; + +} // namespace kaldi diff --git a/third_party/kaldi/src/matrix/kaldi-matrix.h b/third_party/kaldi/src/matrix/kaldi-matrix.h new file mode 100644 index 0000000000..f64828b84f --- /dev/null +++ b/third_party/kaldi/src/matrix/kaldi-matrix.h @@ -0,0 +1,178 @@ +// https://github.com/kaldi-asr/kaldi/blob/7fb716aa0f56480af31514c7e362db5c9f787fd4/src/matrix/kaldi-matrix.h + +#ifndef KALDI_MATRIX_KALDI_MATRIX_H_ +#define KALDI_MATRIX_KALDI_MATRIX_H_ + +#include +#include "matrix/kaldi-vector.h" +#include "matrix/matrix-common.h" + +using namespace torch::indexing; + +namespace kaldi { + +// https://github.com/kaldi-asr/kaldi/blob/7fb716aa0f56480af31514c7e362db5c9f787fd4/src/matrix/kaldi-matrix.h#L44-L48 +template +class MatrixBase { + public: + //////////////////////////////////////////////////////////////////////////////// + // PyTorch-specific items + //////////////////////////////////////////////////////////////////////////////// + torch::Tensor tensor_; + /// Construct VectorBase which is an interface to an existing torch::Tensor + /// object. + MatrixBase(torch::Tensor tensor); + + //////////////////////////////////////////////////////////////////////////////// + // Kaldi-compatible items + //////////////////////////////////////////////////////////////////////////////// + // https://github.com/kaldi-asr/kaldi/blob/7fb716aa0f56480af31514c7e362db5c9f787fd4/src/matrix/kaldi-matrix.h#L62-L63 + inline MatrixIndexT NumRows() const { + return tensor_.size(0); + }; + + // https://github.com/kaldi-asr/kaldi/blob/7fb716aa0f56480af31514c7e362db5c9f787fd4/src/matrix/kaldi-matrix.h#L65-L66 + inline MatrixIndexT NumCols() const { + return tensor_.size(1); + }; + + // https://github.com/kaldi-asr/kaldi/blob/7fb716aa0f56480af31514c7e362db5c9f787fd4/src/matrix/kaldi-matrix.h#L177-L178 + void CopyColFromVec(const VectorBase& v, const MatrixIndexT col) { + tensor_.index_put_({Slice(), col}, v.tensor_); + } + + // https://github.com/kaldi-asr/kaldi/blob/7fb716aa0f56480af31514c7e362db5c9f787fd4/src/matrix/kaldi-matrix.h#L99-L107 + inline Real& operator()(MatrixIndexT r, MatrixIndexT c) { + // CPU only + return tensor_.accessor()[r][c]; + } + + // https://github.com/kaldi-asr/kaldi/blob/7fb716aa0f56480af31514c7e362db5c9f787fd4/src/matrix/kaldi-matrix.h#L112-L120 + inline const Real operator()(MatrixIndexT r, MatrixIndexT c) const { + return tensor_.index({Slice(r), Slice(c)}).item().template to(); + } + + // https://github.com/kaldi-asr/kaldi/blob/7fb716aa0f56480af31514c7e362db5c9f787fd4/src/matrix/kaldi-matrix.h#L138-L141 + // https://github.com/kaldi-asr/kaldi/blob/7fb716aa0f56480af31514c7e362db5c9f787fd4/src/matrix/kaldi-matrix.cc#L859-L898 + template + void CopyFromMat( + const MatrixBase& M, + MatrixTransposeType trans = kNoTrans) { + auto src = M.tensor_; + if (trans == kTrans) + src = src.transpose(1, 0); + tensor_.index_put_({Slice(), Slice()}, src); + } + + // https://github.com/kaldi-asr/kaldi/blob/7fb716aa0f56480af31514c7e362db5c9f787fd4/src/matrix/kaldi-matrix.h#L186-L191 + inline const SubVector Row(MatrixIndexT i) const { + return SubVector(*this, i); + } + + // https://github.com/kaldi-asr/kaldi/blob/7fb716aa0f56480af31514c7e362db5c9f787fd4/src/matrix/kaldi-matrix.h#L208-L211 + inline SubMatrix RowRange( + const MatrixIndexT row_offset, + const MatrixIndexT num_rows) const { + return SubMatrix(*this, row_offset, num_rows, 0, NumCols()); + } + + protected: + // https://github.com/kaldi-asr/kaldi/blob/7fb716aa0f56480af31514c7e362db5c9f787fd4/src/matrix/kaldi-matrix.h#L749-L753 + explicit MatrixBase() : tensor_(torch::empty({0, 0})) { + KALDI_ASSERT_IS_FLOATING_TYPE(Real); + } +}; + +// https://github.com/kaldi-asr/kaldi/blob/7fb716aa0f56480af31514c7e362db5c9f787fd4/src/matrix/kaldi-matrix.h#L781-L784 +template +class Matrix : public MatrixBase { + public: + // https://github.com/kaldi-asr/kaldi/blob/7fb716aa0f56480af31514c7e362db5c9f787fd4/src/matrix/kaldi-matrix.h#L786-L787 + Matrix() : MatrixBase() {} + + // https://github.com/kaldi-asr/kaldi/blob/7fb716aa0f56480af31514c7e362db5c9f787fd4/src/matrix/kaldi-matrix.h#L789-L793 + Matrix( + const MatrixIndexT r, + const MatrixIndexT c, + MatrixResizeType resize_type = kSetZero, + MatrixStrideType stride_type = kDefaultStride) + : MatrixBase() { + Resize(r, c, resize_type, stride_type); + } + + // https://github.com/kaldi-asr/kaldi/blob/7fb716aa0f56480af31514c7e362db5c9f787fd4/src/matrix/kaldi-matrix.h#L808-L811 + explicit Matrix( + const MatrixBase& M, + MatrixTransposeType trans = kNoTrans) + : MatrixBase( + trans == kNoTrans ? M.tensor_ : M.tensor_.transpose(1, 0)) {} + + // https://github.com/kaldi-asr/kaldi/blob/7fb716aa0f56480af31514c7e362db5c9f787fd4/src/matrix/kaldi-matrix.h#L816-L819 + template + explicit Matrix( + const MatrixBase& M, + MatrixTransposeType trans = kNoTrans) + : MatrixBase( + trans == kNoTrans ? M.tensor_ : M.tensor_.transpose(1, 0)) {} + + // https://github.com/kaldi-asr/kaldi/blob/7fb716aa0f56480af31514c7e362db5c9f787fd4/src/matrix/kaldi-matrix.h#L859-L874 + // https://github.com/kaldi-asr/kaldi/blob/7fb716aa0f56480af31514c7e362db5c9f787fd4/src/matrix/kaldi-matrix.cc#L817-L857 + void Resize( + const MatrixIndexT r, + const MatrixIndexT c, + MatrixResizeType resize_type = kSetZero, + MatrixStrideType stride_type = kDefaultStride) { + auto& tensor_ = MatrixBase::tensor_; + switch (resize_type) { + case kSetZero: + tensor_.resize_({r, c}).zero_(); + break; + case kUndefined: + tensor_.resize_({r, c}); + break; + case kCopyData: + auto tmp = tensor_; + auto tmp_rows = tmp.size(0); + auto tmp_cols = tmp.size(1); + tensor_.resize_({r, c}).zero_(); + auto rows = Slice(None, r < tmp_rows ? r : tmp_rows); + auto cols = Slice(None, c < tmp_cols ? c : tmp_cols); + tensor_.index_put_({rows, cols}, tmp.index({rows, cols})); + break; + } + } + + // https://github.com/kaldi-asr/kaldi/blob/7fb716aa0f56480af31514c7e362db5c9f787fd4/src/matrix/kaldi-matrix.h#L876-L883 + Matrix& operator=(const MatrixBase& other) { + if (MatrixBase::NumRows() != other.NumRows() || + MatrixBase::NumCols() != other.NumCols()) + Resize(other.NumRows(), other.NumCols(), kUndefined); + MatrixBase::CopyFromMat(other); + return *this; + } +}; + +// https://github.com/kaldi-asr/kaldi/blob/7fb716aa0f56480af31514c7e362db5c9f787fd4/src/matrix/kaldi-matrix.h#L940-L948 +template +class SubMatrix : public MatrixBase { + public: + SubMatrix( + const MatrixBase& T, + const MatrixIndexT ro, // row offset, 0 < ro < NumRows() + const MatrixIndexT r, // number of rows, r > 0 + const MatrixIndexT co, // column offset, 0 < co < NumCols() + const MatrixIndexT c) // number of columns, c > 0 + : MatrixBase( + T.tensor_.index({Slice(ro, ro + r), Slice(co, co + c)})) {} +}; + +// https://github.com/kaldi-asr/kaldi/blob/7fb716aa0f56480af31514c7e362db5c9f787fd4/src/matrix/kaldi-matrix.h#L1059-L1060 +template +std::ostream& operator<<(std::ostream& Out, const MatrixBase& M) { + Out << M.tensor_; + return Out; +} + +} // namespace kaldi + +#endif diff --git a/third_party/kaldi/src/matrix/kaldi-vector.cc b/third_party/kaldi/src/matrix/kaldi-vector.cc new file mode 100644 index 0000000000..df59f13a36 --- /dev/null +++ b/third_party/kaldi/src/matrix/kaldi-vector.cc @@ -0,0 +1,42 @@ +#include "matrix/kaldi-vector.h" +#include +#include "matrix/kaldi-matrix.h" + +namespace { + +template +void assert_vector_shape(const torch::Tensor& tensor_); + +template <> +void assert_vector_shape(const torch::Tensor& tensor_) { + TORCH_INTERNAL_ASSERT(tensor_.ndimension() == 1); + TORCH_INTERNAL_ASSERT(tensor_.dtype() == torch::kFloat32); + TORCH_CHECK(tensor_.device().is_cpu(), "Input tensor has to be on CPU."); +} + +template <> +void assert_vector_shape(const torch::Tensor& tensor_) { + TORCH_INTERNAL_ASSERT(tensor_.ndimension() == 1); + TORCH_INTERNAL_ASSERT(tensor_.dtype() == torch::kFloat64); + TORCH_CHECK(tensor_.device().is_cpu(), "Input tensor has to be on CPU."); +} + +} // namespace + +namespace kaldi { + +template +VectorBase::VectorBase(torch::Tensor tensor) + : tensor_(tensor), data_(tensor.data_ptr()) { + assert_vector_shape(tensor_); +}; + +template +VectorBase::VectorBase() : VectorBase(torch::empty({0})) {} + +template class Vector; +template class Vector; +template class VectorBase; +template class VectorBase; + +} // namespace kaldi diff --git a/third_party/kaldi/src/matrix/kaldi-vector.h b/third_party/kaldi/src/matrix/kaldi-vector.h new file mode 100644 index 0000000000..620f3676d3 --- /dev/null +++ b/third_party/kaldi/src/matrix/kaldi-vector.h @@ -0,0 +1,313 @@ +// https://github.com/kaldi-asr/kaldi/blob/7fb716aa0f56480af31514c7e362db5c9f787fd4/src/matrix/kaldi-vector.h + +#ifndef KALDI_MATRIX_KALDI_VECTOR_H_ +#define KALDI_MATRIX_KALDI_VECTOR_H_ + +#include +#include "matrix/matrix-common.h" + +using namespace torch::indexing; + +namespace kaldi { + +// https://github.com/kaldi-asr/kaldi/blob/7fb716aa0f56480af31514c7e362db5c9f787fd4/src/matrix/kaldi-vector.h#L36-L40 +template +class VectorBase { + public: + //////////////////////////////////////////////////////////////////////////////// + // PyTorch-specific things + //////////////////////////////////////////////////////////////////////////////// + torch::Tensor tensor_; + + /// Construct VectorBase which is an interface to an existing torch::Tensor + /// object. + VectorBase(torch::Tensor tensor); + + //////////////////////////////////////////////////////////////////////////////// + // Kaldi-compatible methods + //////////////////////////////////////////////////////////////////////////////// + // https://github.com/kaldi-asr/kaldi/blob/7fb716aa0f56480af31514c7e362db5c9f787fd4/src/matrix/kaldi-vector.h#L42-L43 + void SetZero() { + Set(0); + } + + // https://github.com/kaldi-asr/kaldi/blob/7fb716aa0f56480af31514c7e362db5c9f787fd4/src/matrix/kaldi-vector.h#L48-L49 + void Set(Real f) { + tensor_.index_put_({"..."}, f); + } + + // https://github.com/kaldi-asr/kaldi/blob/7fb716aa0f56480af31514c7e362db5c9f787fd4/src/matrix/kaldi-vector.h#L62-L63 + inline MatrixIndexT Dim() const { + return tensor_.numel(); + }; + + // https://github.com/kaldi-asr/kaldi/blob/7fb716aa0f56480af31514c7e362db5c9f787fd4/src/matrix/kaldi-vector.h#L68-L69 + inline Real* Data() { + return data_; + } + + // https://github.com/kaldi-asr/kaldi/blob/7fb716aa0f56480af31514c7e362db5c9f787fd4/src/matrix/kaldi-vector.h#L71-L72 + inline const Real* Data() const { + return data_; + } + + // https://github.com/kaldi-asr/kaldi/blob/7fb716aa0f56480af31514c7e362db5c9f787fd4/src/matrix/kaldi-vector.h#L74-L79 + inline Real operator()(MatrixIndexT i) const { + return data_[i]; + }; + + // https://github.com/kaldi-asr/kaldi/blob/7fb716aa0f56480af31514c7e362db5c9f787fd4/src/matrix/kaldi-vector.h#L81-L86 + inline Real& operator()(MatrixIndexT i) { + return tensor_.accessor()[i]; + }; + + // https://github.com/kaldi-asr/kaldi/blob/7fb716aa0f56480af31514c7e362db5c9f787fd4/src/matrix/kaldi-vector.h#L88-L95 + SubVector Range(const MatrixIndexT o, const MatrixIndexT l) { + return SubVector(*this, o, l); + } + + // https://github.com/kaldi-asr/kaldi/blob/7fb716aa0f56480af31514c7e362db5c9f787fd4/src/matrix/kaldi-vector.h#L97-L105 + const SubVector Range(const MatrixIndexT o, const MatrixIndexT l) + const { + return SubVector(*this, o, l); + } + + // https://github.com/kaldi-asr/kaldi/blob/7fb716aa0f56480af31514c7e362db5c9f787fd4/src/matrix/kaldi-vector.h#L107-L108 + // https://github.com/kaldi-asr/kaldi/blob/7fb716aa0f56480af31514c7e362db5c9f787fd4/src/matrix/kaldi-vector.cc#L226-L233 + void CopyFromVec(const VectorBase& v) { + TORCH_INTERNAL_ASSERT(tensor_.sizes() == v.tensor_.sizes()); + tensor_.copy_(v.tensor_); + } + + // https://github.com/kaldi-asr/kaldi/blob/7fb716aa0f56480af31514c7e362db5c9f787fd4/src/matrix/kaldi-vector.h#L137-L139 + // https://github.com/kaldi-asr/kaldi/blob/7fb716aa0f56480af31514c7e362db5c9f787fd4/src/matrix/kaldi-vector.cc#L816-L832 + void ApplyFloor(Real floor_val, MatrixIndexT* floored_count = nullptr) { + auto index = tensor_ < floor_val; + auto tmp = tensor_.index_put_({index}, floor_val); + if (floored_count) { + *floored_count = index.sum().item().template to(); + } + } + + // https://github.com/kaldi-asr/kaldi/blob/7fb716aa0f56480af31514c7e362db5c9f787fd4/src/matrix/kaldi-vector.h#L164-L165 + // https://github.com/kaldi-asr/kaldi/blob/7fb716aa0f56480af31514c7e362db5c9f787fd4/src/matrix/kaldi-vector.cc#L449-L479 + void ApplyPow(Real power) { + tensor_.pow_(power); + TORCH_INTERNAL_ASSERT(!tensor_.isnan().sum().item().template to()); + } + + // https://github.com/kaldi-asr/kaldi/blob/7fb716aa0f56480af31514c7e362db5c9f787fd4/src/matrix/kaldi-vector.h#L181-L184 + template + void AddVec(const Real alpha, const VectorBase& v) { + tensor_ += alpha * v.tensor_; + } + + // https://github.com/kaldi-asr/kaldi/blob/7fb716aa0f56480af31514c7e362db5c9f787fd4/src/matrix/kaldi-vector.h#L186-L187 + void AddVec2(const Real alpha, const VectorBase& v) { + tensor_ += alpha * (v.tensor_.square()); + } + + // https://github.com/kaldi-asr/kaldi/blob/7fb716aa0f56480af31514c7e362db5c9f787fd4/src/matrix/kaldi-vector.h#L196-L198 + void AddMatVec( + const Real alpha, + const MatrixBase& M, + const MatrixTransposeType trans, + const VectorBase& v, + const Real beta) { // **beta previously defaulted to 0.0** + auto mat = M.tensor_; + if (trans == kTrans) { + mat = mat.transpose(1, 0); + } + tensor_.addmv_(mat, v.tensor_, beta, alpha); + } + + // https://github.com/kaldi-asr/kaldi/blob/7fb716aa0f56480af31514c7e362db5c9f787fd4/src/matrix/kaldi-vector.h#L221-L222 + void MulElements(const VectorBase& v) { + tensor_ *= v.tensor_; + } + + // https://github.com/kaldi-asr/kaldi/blob/7fb716aa0f56480af31514c7e362db5c9f787fd4/src/matrix/kaldi-vector.h#L233-L234 + void Add(Real c) { + tensor_ += c; + } + + // https://github.com/kaldi-asr/kaldi/blob/7fb716aa0f56480af31514c7e362db5c9f787fd4/src/matrix/kaldi-vector.h#L236-L239 + void AddVecVec( + Real alpha, + const VectorBase& v, + const VectorBase& r, + Real beta) { + tensor_ = beta * tensor_ + alpha * v.tensor_ * r.tensor_; + } + + // https://github.com/kaldi-asr/kaldi/blob/7fb716aa0f56480af31514c7e362db5c9f787fd4/src/matrix/kaldi-vector.h#L246-L247 + void Scale(Real alpha) { + tensor_ *= alpha; + } + + // https://github.com/kaldi-asr/kaldi/blob/7fb716aa0f56480af31514c7e362db5c9f787fd4/src/matrix/kaldi-vector.h#L305-L306 + Real Min() const { + if (tensor_.numel()) { + return tensor_.min().item().template to(); + } + return std::numeric_limits::infinity(); + } + + // https://github.com/kaldi-asr/kaldi/blob/7fb716aa0f56480af31514c7e362db5c9f787fd4/src/matrix/kaldi-vector.h#L308-L310 + Real Min(MatrixIndexT* index) const { + TORCH_INTERNAL_ASSERT(tensor_.numel()); + torch::Tensor value, ind; + std::tie(value, ind) = tensor_.min(0); + *index = ind.item().to(); + return value.item().to(); + } + + // https://github.com/kaldi-asr/kaldi/blob/7fb716aa0f56480af31514c7e362db5c9f787fd4/src/matrix/kaldi-vector.h#L312-L313 + Real Sum() const { + return tensor_.sum().item().template to(); + }; + + // https://github.com/kaldi-asr/kaldi/blob/7fb716aa0f56480af31514c7e362db5c9f787fd4/src/matrix/kaldi-vector.h#L320-L321 + // https://github.com/kaldi-asr/kaldi/blob/7fb716aa0f56480af31514c7e362db5c9f787fd4/src/matrix/kaldi-vector.cc#L718-L736 + void AddRowSumMat(Real alpha, const MatrixBase& M, Real beta = 1.0) { + Vector ones(M.NumRows()); + ones.Set(1.0); + this->AddMatVec(alpha, M, kTrans, ones, beta); + } + + // https://github.com/kaldi-asr/kaldi/blob/7fb716aa0f56480af31514c7e362db5c9f787fd4/src/matrix/kaldi-vector.h#L323-L324 + // https://github.com/kaldi-asr/kaldi/blob/7fb716aa0f56480af31514c7e362db5c9f787fd4/src/matrix/kaldi-vector.cc#L738-L757 + void AddColSumMat(Real alpha, const MatrixBase& M, Real beta = 1.0) { + Vector ones(M.NumCols()); + ones.Set(1.0); + this->AddMatVec(alpha, M, kNoTrans, ones, beta); + } + + // https://github.com/kaldi-asr/kaldi/blob/7fb716aa0f56480af31514c7e362db5c9f787fd4/src/matrix/kaldi-vector.h#L326-L330 + void AddDiagMat2( + Real alpha, + const MatrixBase& M, + MatrixTransposeType trans = kNoTrans, + Real beta = 1.0) { + auto mat = M.tensor_; + if (trans == kNoTrans) { + tensor_ = + beta * tensor_ + torch::diag(torch::mm(mat, mat.transpose(1, 0))); + } else { + tensor_ = + beta * tensor_ + torch::diag(torch::mm(mat.transpose(1, 0), mat)); + } + } + + protected: + // https://github.com/kaldi-asr/kaldi/blob/7fb716aa0f56480af31514c7e362db5c9f787fd4/src/matrix/kaldi-vector.h#L362-L365 + explicit VectorBase(); + + // https://github.com/kaldi-asr/kaldi/blob/7fb716aa0f56480af31514c7e362db5c9f787fd4/src/matrix/kaldi-vector.h#L378-L379 + Real* data_; + // https://github.com/kaldi-asr/kaldi/blob/7fb716aa0f56480af31514c7e362db5c9f787fd4/src/matrix/kaldi-vector.h#L382 + KALDI_DISALLOW_COPY_AND_ASSIGN(VectorBase); +}; + +// https://github.com/kaldi-asr/kaldi/blob/7fb716aa0f56480af31514c7e362db5c9f787fd4/src/matrix/kaldi-vector.h#L385-L390 +template +class Vector : public VectorBase { + public: + //////////////////////////////////////////////////////////////////////////////// + // PyTorch-compatibility things + //////////////////////////////////////////////////////////////////////////////// + /// Construct VectorBase which is an interface to an existing torch::Tensor + /// object. + Vector(torch::Tensor tensor) : VectorBase(tensor){}; + + //////////////////////////////////////////////////////////////////////////////// + // Kaldi-compatible methods + //////////////////////////////////////////////////////////////////////////////// + // https://github.com/kaldi-asr/kaldi/blob/7fb716aa0f56480af31514c7e362db5c9f787fd4/src/matrix/kaldi-vector.h#L392-L393 + Vector() : VectorBase(){}; + + // https://github.com/kaldi-asr/kaldi/blob/7fb716aa0f56480af31514c7e362db5c9f787fd4/src/matrix/kaldi-vector.h#L395-L399 + explicit Vector(const MatrixIndexT s, MatrixResizeType resize_type = kSetZero) + : VectorBase() { + Resize(s, resize_type); + } + + // https://github.com/kaldi-asr/kaldi/blob/7fb716aa0f56480af31514c7e362db5c9f787fd4/src/matrix/kaldi-vector.h#L406-L410 + // Note: unlike the original implementation, this is "explicit". + explicit Vector(const Vector& v) + : VectorBase(v.tensor_.clone()) {} + + // https://github.com/kaldi-asr/kaldi/blob/7fb716aa0f56480af31514c7e362db5c9f787fd4/src/matrix/kaldi-vector.h#L412-L416 + explicit Vector(const VectorBase& v) + : VectorBase(v.tensor_.clone()) {} + + // https://github.com/kaldi-asr/kaldi/blob/7fb716aa0f56480af31514c7e362db5c9f787fd4/src/matrix/kaldi-vector.h#L434-L435 + void Swap(Vector* other) { + auto tmp = VectorBase::tensor_; + this->tensor_ = other->tensor_; + other->tensor_ = tmp; + } + + // https://github.com/kaldi-asr/kaldi/blob/7fb716aa0f56480af31514c7e362db5c9f787fd4/src/matrix/kaldi-vector.h#L444-L451 + // https://github.com/kaldi-asr/kaldi/blob/7fb716aa0f56480af31514c7e362db5c9f787fd4/src/matrix/kaldi-vector.cc#L189-L223 + void Resize(MatrixIndexT length, MatrixResizeType resize_type = kSetZero) { + auto& tensor_ = this->tensor_; + switch (resize_type) { + case kSetZero: + tensor_.resize_({length}).zero_(); + break; + case kUndefined: + tensor_.resize_({length}); + break; + case kCopyData: + auto tmp = tensor_; + auto tmp_numel = tensor_.numel(); + tensor_.resize_({length}).zero_(); + auto numel = Slice(length < tmp_numel ? length : tmp_numel); + tensor_.index_put_({numel}, tmp.index({numel})); + break; + } + // data_ptr() causes compiler error + this->data_ = static_cast(tensor_.data_ptr()); + } + + // https://github.com/kaldi-asr/kaldi/blob/7fb716aa0f56480af31514c7e362db5c9f787fd4/src/matrix/kaldi-vector.h#L463-L468 + Vector& operator=(const VectorBase& other) { + Resize(other.Dim(), kUndefined); + this->CopyFromVec(other); + return *this; + } +}; + +// https://github.com/kaldi-asr/kaldi/blob/7fb716aa0f56480af31514c7e362db5c9f787fd4/src/matrix/kaldi-vector.h#L482-L485 +template +class SubVector : public VectorBase { + public: + // https://github.com/kaldi-asr/kaldi/blob/7fb716aa0f56480af31514c7e362db5c9f787fd4/src/matrix/kaldi-vector.h#L487-L499 + SubVector( + const VectorBase& t, + const MatrixIndexT origin, + const MatrixIndexT length) + : VectorBase(t.tensor_.index({Slice(origin, origin + length)})) {} + + // https://github.com/kaldi-asr/kaldi/blob/7fb716aa0f56480af31514c7e362db5c9f787fd4/src/matrix/kaldi-vector.h#L524-L528 + SubVector(const MatrixBase& matrix, MatrixIndexT row) + : VectorBase(matrix.tensor_.index({row})) {} +}; + +// https://github.com/kaldi-asr/kaldi/blob/7fb716aa0f56480af31514c7e362db5c9f787fd4/src/matrix/kaldi-vector.h#L540-L543 +template +std::ostream& operator<<(std::ostream& out, const VectorBase& v) { + out << v.tensor_; + return out; +} + +// https://github.com/kaldi-asr/kaldi/blob/7fb716aa0f56480af31514c7e362db5c9f787fd4/src/matrix/kaldi-vector.h#L573-L575 +template +Real VecVec(const VectorBase& v1, const VectorBase& v2) { + return torch::dot(v1.tensor_, v2.tensor_).item().template to(); +} + +} // namespace kaldi + +#endif diff --git a/third_party/sox/CMakeLists.txt b/third_party/sox/CMakeLists.txt index 840130f055..7bbad0e99e 100644 --- a/third_party/sox/CMakeLists.txt +++ b/third_party/sox/CMakeLists.txt @@ -197,6 +197,7 @@ ExternalProject_Add(sox URL https://downloads.sourceforge.net/project/sox/sox/14.4.2/sox-14.4.2.tar.bz2 URL_HASH SHA256=81a6956d4330e75b5827316e44ae381e6f1e8928003c6aa45896da9041ea149c CONFIGURE_COMMAND ${CMAKE_COMMAND} -E env ${envs} ${CMAKE_CURRENT_BINARY_DIR}/src/sox/configure ${COMMON_ARGS} ${SOX_OPTIONS} + PATCH_COMMAND patch -p1 < ${CMAKE_CURRENT_SOURCE_DIR}/patch/sox.patch BUILD_BYPRODUCTS ${SOX_LIBRARIES} DOWNLOAD_NO_PROGRESS ON LOG_DOWNLOAD ON diff --git a/third_party/sox/patch/sox.patch b/third_party/sox/patch/sox.patch new file mode 100644 index 0000000000..fe8df945c0 --- /dev/null +++ b/third_party/sox/patch/sox.patch @@ -0,0 +1,16 @@ +See https://github.com/pytorch/audio/pull/1297 +diff -ru sox/src/formats.c sox/src/formats.c +--- sox/src/formats.c 2014-10-26 19:55:50.000000000 -0700 ++++ sox/src/formats.c 2021-02-22 16:01:02.833144070 -0800 +@@ -333,6 +333,10 @@ + assert(ft); + if (!ft->fp) + return sox_false; +- fstat(fileno((FILE*)ft->fp), &st); ++ int fd = fileno((FILE*)ft->fp); ++ if (fd < 0) ++ return sox_false; ++ if (fstat(fd, &st) < 0) ++ return sox_false; + return ((st.st_mode & S_IFMT) == S_IFREG); + } diff --git a/torchaudio/__init__.py b/torchaudio/__init__.py index 35f5fd41d5..e72ecac4cb 100644 --- a/torchaudio/__init__.py +++ b/torchaudio/__init__.py @@ -10,20 +10,10 @@ transforms, ) -USE_SOUNDFILE_LEGACY_INTERFACE = None - from torchaudio.backend import ( list_audio_backends, get_audio_backend, set_audio_backend, - save_encinfo, - sox_signalinfo_t, - sox_encodinginfo_t, - get_sox_option_t, - get_sox_encoding_t, - get_sox_bool, - SignalInfo, - EncodingInfo, ) try: diff --git a/torchaudio/_internal/module_utils.py b/torchaudio/_internal/module_utils.py index 31bc2f1a31..67e11e6c5f 100644 --- a/torchaudio/_internal/module_utils.py +++ b/torchaudio/_internal/module_utils.py @@ -3,6 +3,8 @@ from typing import Optional from functools import wraps +import torch + def is_module_available(*modules: str) -> bool: r"""Returns if a top-level module with :attr:`name` exists *without** @@ -41,9 +43,11 @@ def deprecated(direction: str, version: Optional[str] = None): """Decorator to add deprecation message Args: - direction: Migration steps to be given to users. + direction (str): Migration steps to be given to users. + version (str or int): The version when the object will be removed """ def decorator(func): + @wraps(func) def wrapped(*args, **kwargs): message = ( @@ -54,3 +58,37 @@ def wrapped(*args, **kwargs): return func(*args, **kwargs) return wrapped return decorator + + +def is_kaldi_available(): + return is_module_available('torchaudio._torchaudio') and torch.ops.torchaudio.is_kaldi_available() + + +def requires_kaldi(): + if is_kaldi_available(): + def decorator(func): + return func + else: + def decorator(func): + @wraps(func) + def wrapped(*args, **kwargs): + raise RuntimeError(f'{func.__module__}.{func.__name__} requires kaldi') + return wrapped + return decorator + + +def is_sox_available(): + return is_module_available('torchaudio._torchaudio') and torch.ops.torchaudio.is_sox_available() + + +def requires_sox(): + if is_sox_available(): + def decorator(func): + return func + else: + def decorator(func): + @wraps(func) + def wrapped(*args, **kwargs): + raise RuntimeError(f'{func.__module__}.{func.__name__} requires sox') + return wrapped + return decorator diff --git a/torchaudio/backend/__init__.py b/torchaudio/backend/__init__.py index 361935229f..c3fdf0b439 100644 --- a/torchaudio/backend/__init__.py +++ b/torchaudio/backend/__init__.py @@ -5,18 +5,6 @@ get_audio_backend, set_audio_backend, ) -from .sox_backend import ( - save_encinfo, - sox_signalinfo_t, - sox_encodinginfo_t, - get_sox_option_t, - get_sox_encoding_t, - get_sox_bool, -) -from .common import ( - SignalInfo, - EncodingInfo, -) utils._init_audio_backend() diff --git a/torchaudio/backend/_soundfile_backend.py b/torchaudio/backend/_soundfile_backend.py deleted file mode 100644 index e3c992b6fd..0000000000 --- a/torchaudio/backend/_soundfile_backend.py +++ /dev/null @@ -1,316 +0,0 @@ -"""The new soundfile backend which will become default in 0.8.0 onward""" -from typing import Tuple, Optional -import warnings - -import torch -from torchaudio._internal import module_utils as _mod_utils -from .common import AudioMetaData - - -if _mod_utils.is_module_available("soundfile"): - import soundfile - - -# Mapping from soundfile subtype to number of bits per sample. -# This is mostly heuristical and the value is set to 0 when it is irrelevant -# (lossy formats) or when it can't be inferred. -# For ADPCM (and G72X) subtypes, it's hard to infer the bit depth because it's not part of the standard: -# According to https://en.wikipedia.org/wiki/Adaptive_differential_pulse-code_modulation#In_telephony, -# the default seems to be 8 bits but it can be compressed further to 4 bits. -# The dict is inspired from -# https://github.com/bastibe/python-soundfile/blob/744efb4b01abc72498a96b09115b42a4cabd85e4/soundfile.py#L66-L94 -_SUBTYPE_TO_BITS_PER_SAMPLE = { - 'PCM_S8': 8, # Signed 8 bit data - 'PCM_16': 16, # Signed 16 bit data - 'PCM_24': 24, # Signed 24 bit data - 'PCM_32': 32, # Signed 32 bit data - 'PCM_U8': 8, # Unsigned 8 bit data (WAV and RAW only) - 'FLOAT': 32, # 32 bit float data - 'DOUBLE': 64, # 64 bit float data - 'ULAW': 8, # U-Law encoded. See https://en.wikipedia.org/wiki/G.711#Types - 'ALAW': 8, # A-Law encoded. See https://en.wikipedia.org/wiki/G.711#Types - 'IMA_ADPCM': 0, # IMA ADPCM. - 'MS_ADPCM': 0, # Microsoft ADPCM. - 'GSM610': 0, # GSM 6.10 encoding. (Wikipedia says 1.625 bit depth?? https://en.wikipedia.org/wiki/Full_Rate) - 'VOX_ADPCM': 0, # OKI / Dialogix ADPCM - 'G721_32': 0, # 32kbs G721 ADPCM encoding. - 'G723_24': 0, # 24kbs G723 ADPCM encoding. - 'G723_40': 0, # 40kbs G723 ADPCM encoding. - 'DWVW_12': 12, # 12 bit Delta Width Variable Word encoding. - 'DWVW_16': 16, # 16 bit Delta Width Variable Word encoding. - 'DWVW_24': 24, # 24 bit Delta Width Variable Word encoding. - 'DWVW_N': 0, # N bit Delta Width Variable Word encoding. - 'DPCM_8': 8, # 8 bit differential PCM (XI only) - 'DPCM_16': 16, # 16 bit differential PCM (XI only) - 'VORBIS': 0, # Xiph Vorbis encoding. (lossy) - 'ALAC_16': 16, # Apple Lossless Audio Codec (16 bit). - 'ALAC_20': 20, # Apple Lossless Audio Codec (20 bit). - 'ALAC_24': 24, # Apple Lossless Audio Codec (24 bit). - 'ALAC_32': 32, # Apple Lossless Audio Codec (32 bit). -} - - -def _get_bit_depth(subtype): - if subtype not in _SUBTYPE_TO_BITS_PER_SAMPLE: - warnings.warn( - f"The {subtype} subtype is unknown to TorchAudio. As a result, the bits_per_sample " - "attribute will be set to 0. If you are seeing this warning, please " - "report by opening an issue on github (after checking for existing/closed ones). " - "You may otherwise ignore this warning." - ) - return _SUBTYPE_TO_BITS_PER_SAMPLE.get(subtype, 0) - - -_SUBTYPE_TO_ENCODING = { - 'PCM_S8': 'PCM_S', - 'PCM_16': 'PCM_S', - 'PCM_24': 'PCM_S', - 'PCM_32': 'PCM_S', - 'PCM_U8': 'PCM_U', - 'FLOAT': 'PCM_F', - 'DOUBLE': 'PCM_F', - 'ULAW': 'ULAW', - 'ALAW': 'ALAW', - 'VORBIS': 'VORBIS', -} - - -def _get_encoding(format: str, subtype: str): - if format == 'FLAC': - return 'FLAC' - return _SUBTYPE_TO_ENCODING.get(subtype, 'UNKNOWN') - - -@_mod_utils.requires_module("soundfile") -def info(filepath: str, format: Optional[str] = None) -> AudioMetaData: - """Get signal information of an audio file. - - Args: - filepath (path-like object or file-like object): - Source of audio data. - Note: - * This argument is intentionally annotated as ``str`` only, - for the consistency with "sox_io" backend, which has a restriction - on type annotation due to TorchScript compiler compatiblity. - format (str, optional): - Not used. PySoundFile does not accept format hint. - - Returns: - AudioMetaData: meta data of the given audio. - """ - sinfo = soundfile.info(filepath) - return AudioMetaData( - sinfo.samplerate, - sinfo.frames, - sinfo.channels, - bits_per_sample=_get_bit_depth(sinfo.subtype), - encoding=_get_encoding(sinfo.format, sinfo.subtype), - ) - - -_SUBTYPE2DTYPE = { - "PCM_S8": "int8", - "PCM_U8": "uint8", - "PCM_16": "int16", - "PCM_32": "int32", - "FLOAT": "float32", - "DOUBLE": "float64", -} - - -@_mod_utils.requires_module("soundfile") -def load( - filepath: str, - frame_offset: int = 0, - num_frames: int = -1, - normalize: bool = True, - channels_first: bool = True, - format: Optional[str] = None, -) -> Tuple[torch.Tensor, int]: - """Load audio data from file. - - Note: - The formats this function can handle depend on the soundfile installation. - This function is tested on the following formats; - - * WAV - - * 32-bit floating-point - * 32-bit signed integer - * 16-bit signed integer - * 8-bit unsigned integer - - * FLAC - * OGG/VORBIS - * SPHERE - - By default (``normalize=True``, ``channels_first=True``), this function returns Tensor with - ``float32`` dtype and the shape of ``[channel, time]``. - The samples are normalized to fit in the range of ``[-1.0, 1.0]``. - - When the input format is WAV with integer type, such as 32-bit signed integer, 16-bit - signed integer and 8-bit unsigned integer (24-bit signed integer is not supported), - by providing ``normalize=False``, this function can return integer Tensor, where the samples - are expressed within the whole range of the corresponding dtype, that is, ``int32`` tensor - for 32-bit signed PCM, ``int16`` for 16-bit signed PCM and ``uint8`` for 8-bit unsigned PCM. - - ``normalize`` parameter has no effect on 32-bit floating-point WAV and other formats, such as - ``flac`` and ``mp3``. - For these formats, this function always returns ``float32`` Tensor with values normalized to - ``[-1.0, 1.0]``. - - Args: - filepath (path-like object or file-like object): - Source of audio data. - Note: - * This argument is intentionally annotated as ``str`` only, - for the consistency with "sox_io" backend, which has a restriction - on type annotation due to TorchScript compiler compatiblity. - frame_offset (int): - Number of frames to skip before start reading data. - num_frames (int): - Maximum number of frames to read. ``-1`` reads all the remaining samples, - starting from ``frame_offset``. - This function may return the less number of frames if there is not enough - frames in the given file. - normalize (bool): - When ``True``, this function always return ``float32``, and sample values are - normalized to ``[-1.0, 1.0]``. - If input file is integer WAV, giving ``False`` will change the resulting Tensor type to - integer type. - This argument has no effect for formats other than integer WAV type. - channels_first (bool): - When True, the returned Tensor has dimension ``[channel, time]``. - Otherwise, the returned Tensor's dimension is ``[time, channel]``. - format (str, optional): - Not used. PySoundFile does not accept format hint. - - Returns: - Tuple[torch.Tensor, int]: Resulting Tensor and sample rate. - If the input file has integer wav format and normalization is off, then it has - integer type, else ``float32`` type. If ``channels_first=True``, it has - ``[channel, time]`` else ``[time, channel]``. - """ - with soundfile.SoundFile(filepath, "r") as file_: - if file_.format != "WAV" or normalize: - dtype = "float32" - elif file_.subtype not in _SUBTYPE2DTYPE: - raise ValueError(f"Unsupported subtype: {file_.subtype}") - else: - dtype = _SUBTYPE2DTYPE[file_.subtype] - - frames = file_._prepare_read(frame_offset, None, num_frames) - waveform = file_.read(frames, dtype, always_2d=True) - sample_rate = file_.samplerate - - waveform = torch.from_numpy(waveform) - if channels_first: - waveform = waveform.t() - return waveform, sample_rate - - -@_mod_utils.requires_module("soundfile") -def save( - filepath: str, - src: torch.Tensor, - sample_rate: int, - channels_first: bool = True, - compression: Optional[float] = None, - format: Optional[str] = None, -): - """Save audio data to file. - - Note: - The formats this function can handle depend on the soundfile installation. - This function is tested on the following formats; - - * WAV - - * 32-bit floating-point - * 32-bit signed integer - * 16-bit signed integer - * 8-bit unsigned integer - - * FLAC - * OGG/VORBIS - * SPHERE - - Args: - filepath (str or pathlib.Path): Path to audio file. - This functionalso handles ``pathlib.Path`` objects, but is annotated as ``str`` - for the consistency with "sox_io" backend, which has a restriction on type annotation - for TorchScript compiler compatiblity. - tensor (torch.Tensor): Audio data to save. must be 2D tensor. - sample_rate (int): sampling rate - channels_first (bool): - If ``True``, the given tensor is interpreted as ``[channel, time]``, - otherwise ``[time, channel]``. - compression (Optional[float]): - Not used. It is here only for interface compatibility reson with "sox_io" backend. - format (str, optional): - Output audio format. This is required when the output audio format cannot be infered from - ``filepath``, (such as file extension or ``name`` attribute of the given file object). - """ - if src.ndim != 2: - raise ValueError(f"Expected 2D Tensor, got {src.ndim}D.") - if compression is not None: - warnings.warn( - '`save` function of "soundfile" backend does not support "compression" parameter. ' - "The argument is silently ignored." - ) - if hasattr(filepath, 'write'): - if format is None: - raise RuntimeError('`format` is required when saving to file object.') - ext = format - else: - ext = str(filepath).split(".")[-1].lower() - - if ext != "wav": - subtype = None - elif src.dtype == torch.uint8: - subtype = "PCM_U8" - elif src.dtype == torch.int16: - subtype = "PCM_16" - elif src.dtype == torch.int32: - subtype = "PCM_32" - elif src.dtype == torch.float32: - subtype = "FLOAT" - elif src.dtype == torch.float64: - subtype = "DOUBLE" - else: - raise ValueError(f"Unsupported dtype for WAV: {src.dtype}") - - # sph is a extension used in TED-LIUM but soundfile does not recognize it as NIST format, - # so we extend the extensions manually here - if ext in ["nis", "nist", "sph"] and format is None: - format = "NIST" - - if channels_first: - src = src.t() - - soundfile.write( - file=filepath, data=src, samplerate=sample_rate, subtype=subtype, format=format - ) - - -@_mod_utils.requires_module("soundfile") -@_mod_utils.deprecated('Please use "torchaudio.load".', "0.9.0") -def load_wav( - filepath: str, - frame_offset: int = 0, - num_frames: int = -1, - channels_first: bool = True, -) -> Tuple[torch.Tensor, int]: - """Load wave file. - - This function is defined only for the purpose of compatibility against other backend - for simple usecases, such as ``torchaudio.load_wav(filepath)``. - The implementation is same as :py:func:`load`. - """ - return load( - filepath, - frame_offset, - num_frames, - normalize=False, - channels_first=channels_first, - ) diff --git a/torchaudio/backend/common.py b/torchaudio/backend/common.py index c0eb90c994..f944b23d74 100644 --- a/torchaudio/backend/common.py +++ b/torchaudio/backend/common.py @@ -1,8 +1,3 @@ -from typing import Any, Optional - -from torchaudio._internal import module_utils as _mod_utils - - class AudioMetaData: """Return type of ``torchaudio.info`` function. @@ -14,7 +9,21 @@ class AudioMetaData: :ivar int num_channels: The number of channels :ivar int bits_per_sample: The number of bits per sample. This is 0 for lossy formats, or when it cannot be accurately inferred. - :ivar str encoding: Audio encoding. + :ivar str encoding: Audio encoding + The values encoding can take are one of the following: + + * ``PCM_S``: Signed integer linear PCM + * ``PCM_U``: Unsigned integer linear PCM + * ``PCM_F``: Floating point linear PCM + * ``FLAC``: Flac, Free Lossless Audio Codec + * ``ULAW``: Mu-law + * ``ALAW``: A-law + * ``MP3`` : MP3, MPEG-1 Audio Layer III + * ``VORBIS``: OGG Vorbis + * ``AMR_WB``: Adaptive Multi-Rate + * ``AMR_NB``: Adaptive Multi-Rate Wideband + * ``OPUS``: Opus + * ``UNKNOWN`` : None of above """ def __init__( self, @@ -30,174 +39,13 @@ def __init__( self.bits_per_sample = bits_per_sample self.encoding = encoding - -@_mod_utils.deprecated('Please migrate to `AudioMetaData`.', '0.9.0') -class SignalInfo: - """One of return types of ``torchaudio.info`` functions. - - This class is used by :ref:`"sox" backend (deprecated)` and - :ref:`"soundfile" backend with the legacy interface (deprecated)`. - - See https://fossies.org/dox/sox-14.4.2/structsox__signalinfo__t.html - - :ivar Optional[int] channels: The number of channels - :ivar Optional[float] rate: Sampleing rate - :ivar Optional[int] precision: Bit depth - :ivar Optional[int] length: For :ref:`sox backend`, the number of samples. - (frames * channels). For :ref:`soundfile backend`, the number of frames. - """ - def __init__(self, - channels: Optional[int] = None, - rate: Optional[float] = None, - precision: Optional[int] = None, - length: Optional[int] = None) -> None: - self.channels = channels - self.rate = rate - self.precision = precision - self.length = length - - -@_mod_utils.deprecated('Please migrate to `AudioMetaData`.', '0.9.0') -class EncodingInfo: - """One of return types of ``torchaudio.info`` functions. - - This class is used by :ref:`"sox" backend (deprecated)` and - :ref:`"soundfile" backend with the legacy interface (deprecated)`. - - See https://fossies.org/dox/sox-14.4.2/structsox__encodinginfo__t.html - - :ivar Optional[int] encoding: sox_encoding_t - :ivar Optional[int] bits_per_sample: bit depth - :ivar Optional[float] compression: Compression option - :ivar Any reverse_bytes: - :ivar Any reverse_nibbles: - :ivar Any reverse_bits: - :ivar Optional[bool] opposite_endian: - """ - def __init__(self, - encoding: Any = None, - bits_per_sample: Optional[int] = None, - compression: Optional[float] = None, - reverse_bytes: Any = None, - reverse_nibbles: Any = None, - reverse_bits: Any = None, - opposite_endian: Optional[bool] = None) -> None: - self.encoding = encoding - self.bits_per_sample = bits_per_sample - self.compression = compression - self.reverse_bytes = reverse_bytes - self.reverse_nibbles = reverse_nibbles - self.reverse_bits = reverse_bits - self.opposite_endian = opposite_endian - - -_LOAD_DOCSTRING = r"""Loads an audio file from disk into a tensor - -Args: - filepath: Path to audio file - - out: An optional output tensor to use instead of creating one. (Default: ``None``) - - normalization: Optional normalization. - If boolean `True`, then output is divided by `1 << 31`. - Assuming the input is signed 32-bit audio, this normalizes to `[-1, 1]`. - If `float`, then output is divided by that number. - If `Callable`, then the output is passed as a paramete to the given function, - then the output is divided by the result. (Default: ``True``) - - channels_first: Set channels first or length first in result. (Default: ``True``) - - num_frames: Number of frames to load. 0 to load everything after the offset. - (Default: ``0``) - - offset: Number of frames from the start of the file to begin data loading. - (Default: ``0``) - - signalinfo: A sox_signalinfo_t type, which could be helpful if the - audio type cannot be automatically determined. (Default: ``None``) - - encodinginfo: A sox_encodinginfo_t type, which could be set if the - audio type cannot be automatically determined. (Default: ``None``) - - filetype: A filetype or extension to be set if sox cannot determine it - automatically. (Default: ``None``) - -Returns: - (Tensor, int): An output tensor of size `[C x L]` or `[L x C]` where - L is the number of audio frames and - C is the number of channels. - An integer which is the sample rate of the audio (as listed in the metadata of the file) - -Example - >>> data, sample_rate = torchaudio.load('foo.mp3') - >>> print(data.size()) - torch.Size([2, 278756]) - >>> print(sample_rate) - 44100 - >>> data_vol_normalized, _ = torchaudio.load('foo.mp3', normalization=lambda x: torch.abs(x).max()) - >>> print(data_vol_normalized.abs().max()) - 1. -""" - - -_LOAD_WAV_DOCSTRING = r""" Loads a wave file. - -It assumes that the wav file uses 16 bit per sample that needs normalization by -shifting the input right by 16 bits. - -Args: - filepath: Path to audio file - -Returns: - (Tensor, int): An output tensor of size `[C x L]` or `[L x C]` where L is the number - of audio frames and C is the number of channels. An integer which is the sample rate of the - audio (as listed in the metadata of the file) -""" - -_SAVE_DOCSTRING = r"""Saves a Tensor on file as an audio file - -Args: - filepath: Path to audio file - src: An input 2D tensor of shape `[C x L]` or `[L x C]` where L is - the number of audio frames, C is the number of channels - sample_rate: An integer which is the sample rate of the - audio (as listed in the metadata of the file) - precision Bit precision (Default: ``16``) - channels_first (bool, optional): Set channels first or length first in result. ( - Default: ``True``) -""" - - -_INFO_DOCSTRING = r"""Gets metadata from an audio file without loading the signal. - -Args: - filepath: Path to audio file - -Returns: - (sox_signalinfo_t, sox_encodinginfo_t): A si (sox_signalinfo_t) signal - info as a python object. An ei (sox_encodinginfo_t) encoding info - -Example - >>> si, ei = torchaudio.info('foo.wav') - >>> rate, channels, encoding = si.rate, si.channels, ei.encoding -""" - - -def _impl_load(func): - setattr(func, '__doc__', _LOAD_DOCSTRING) - return func - - -def _impl_load_wav(func): - setattr(func, '__doc__', _LOAD_WAV_DOCSTRING) - return func - - -def _impl_save(func): - setattr(func, '__doc__', _SAVE_DOCSTRING) - return func - - -def _impl_info(func): - setattr(func, '__doc__', _INFO_DOCSTRING) - return func + def __str__(self): + return ( + f"AudioMetaData(" + f"sample_rate={self.sample_rate}, " + f"num_frames={self.num_frames}, " + f"num_channels={self.num_channels}, " + f"bits_per_sample={self.bits_per_sample}, " + f"encoding={self.encoding}" + f")" + ) diff --git a/torchaudio/backend/no_backend.py b/torchaudio/backend/no_backend.py index 60571c34a9..7160c89f69 100644 --- a/torchaudio/backend/no_backend.py +++ b/torchaudio/backend/no_backend.py @@ -1,35 +1,22 @@ from pathlib import Path -from typing import Any, Callable, Optional, Tuple, Union +from typing import Callable, Optional, Tuple, Union from torch import Tensor -from . import common -from .common import SignalInfo, EncodingInfo - -@common._impl_load def load(filepath: Union[str, Path], out: Optional[Tensor] = None, normalization: Union[bool, float, Callable] = True, channels_first: bool = True, num_frames: int = 0, offset: int = 0, - signalinfo: Optional[SignalInfo] = None, - encodinginfo: Optional[EncodingInfo] = None, filetype: Optional[str] = None) -> Tuple[Tensor, int]: raise RuntimeError('No audio I/O backend is available.') -@common._impl_load_wav -def load_wav(filepath: Union[str, Path], **kwargs: Any) -> Tuple[Tensor, int]: - raise RuntimeError('No audio I/O backend is available.') - - -@common._impl_save def save(filepath: str, src: Tensor, sample_rate: int, precision: int = 16, channels_first: bool = True) -> None: raise RuntimeError('No audio I/O backend is available.') -@common._impl_info -def info(filepath: str) -> Tuple[SignalInfo, EncodingInfo]: +def info(filepath: str) -> None: raise RuntimeError('No audio I/O backend is available.') diff --git a/torchaudio/backend/soundfile_backend.py b/torchaudio/backend/soundfile_backend.py index 49cada21b0..8ad28a6fcf 100644 --- a/torchaudio/backend/soundfile_backend.py +++ b/torchaudio/backend/soundfile_backend.py @@ -1,127 +1,426 @@ -import os -from typing import Optional, Tuple +"""The new soundfile backend which will become default in 0.8.0 onward""" +from typing import Tuple, Optional +import warnings import torch -from torch import Tensor +from torchaudio._internal import module_utils as _mod_utils +from .common import AudioMetaData -from torchaudio._internal import ( - module_utils as _mod_utils, - misc_ops as _misc_ops, -) -from . import common -from .common import SignalInfo, EncodingInfo -if _mod_utils.is_module_available('soundfile'): +if _mod_utils.is_module_available("soundfile"): import soundfile -_subtype_to_precision = { - 'PCM_S8': 8, - 'PCM_16': 16, - 'PCM_24': 24, - 'PCM_32': 32, - 'PCM_U8': 8 +# Mapping from soundfile subtype to number of bits per sample. +# This is mostly heuristical and the value is set to 0 when it is irrelevant +# (lossy formats) or when it can't be inferred. +# For ADPCM (and G72X) subtypes, it's hard to infer the bit depth because it's not part of the standard: +# According to https://en.wikipedia.org/wiki/Adaptive_differential_pulse-code_modulation#In_telephony, +# the default seems to be 8 bits but it can be compressed further to 4 bits. +# The dict is inspired from +# https://github.com/bastibe/python-soundfile/blob/744efb4b01abc72498a96b09115b42a4cabd85e4/soundfile.py#L66-L94 +_SUBTYPE_TO_BITS_PER_SAMPLE = { + 'PCM_S8': 8, # Signed 8 bit data + 'PCM_16': 16, # Signed 16 bit data + 'PCM_24': 24, # Signed 24 bit data + 'PCM_32': 32, # Signed 32 bit data + 'PCM_U8': 8, # Unsigned 8 bit data (WAV and RAW only) + 'FLOAT': 32, # 32 bit float data + 'DOUBLE': 64, # 64 bit float data + 'ULAW': 8, # U-Law encoded. See https://en.wikipedia.org/wiki/G.711#Types + 'ALAW': 8, # A-Law encoded. See https://en.wikipedia.org/wiki/G.711#Types + 'IMA_ADPCM': 0, # IMA ADPCM. + 'MS_ADPCM': 0, # Microsoft ADPCM. + 'GSM610': 0, # GSM 6.10 encoding. (Wikipedia says 1.625 bit depth?? https://en.wikipedia.org/wiki/Full_Rate) + 'VOX_ADPCM': 0, # OKI / Dialogix ADPCM + 'G721_32': 0, # 32kbs G721 ADPCM encoding. + 'G723_24': 0, # 24kbs G723 ADPCM encoding. + 'G723_40': 0, # 40kbs G723 ADPCM encoding. + 'DWVW_12': 12, # 12 bit Delta Width Variable Word encoding. + 'DWVW_16': 16, # 16 bit Delta Width Variable Word encoding. + 'DWVW_24': 24, # 24 bit Delta Width Variable Word encoding. + 'DWVW_N': 0, # N bit Delta Width Variable Word encoding. + 'DPCM_8': 8, # 8 bit differential PCM (XI only) + 'DPCM_16': 16, # 16 bit differential PCM (XI only) + 'VORBIS': 0, # Xiph Vorbis encoding. (lossy) + 'ALAC_16': 16, # Apple Lossless Audio Codec (16 bit). + 'ALAC_20': 20, # Apple Lossless Audio Codec (20 bit). + 'ALAC_24': 24, # Apple Lossless Audio Codec (24 bit). + 'ALAC_32': 32, # Apple Lossless Audio Codec (32 bit). } -@_mod_utils.requires_module('soundfile') -@common._impl_load -def load(filepath: str, - out: Optional[Tensor] = None, - normalization: Optional[bool] = True, - channels_first: Optional[bool] = True, - num_frames: int = 0, - offset: int = 0, - signalinfo: SignalInfo = None, - encodinginfo: EncodingInfo = None, - filetype: Optional[str] = None) -> Tuple[Tensor, int]: - r"""See torchaudio.load""" - - assert out is None - assert normalization - assert signalinfo is None - assert encodinginfo is None - - # stringify if `pathlib.Path` (noop if already `str`) - filepath = str(filepath) - - # check if valid file - if not os.path.isfile(filepath): - raise OSError("{} not found or is a directory".format(filepath)) - - if num_frames < -1: - raise ValueError("Expected value for num_samples -1 (entire file) or >=0") - if num_frames == 0: - num_frames = -1 - if offset < 0: - raise ValueError("Expected positive offset value") - - # initialize output tensor - # TODO call libsoundfile directly to avoid numpy - out, sample_rate = soundfile.read( - filepath, frames=num_frames, start=offset, dtype="float32", always_2d=True +def _get_bit_depth(subtype): + if subtype not in _SUBTYPE_TO_BITS_PER_SAMPLE: + warnings.warn( + f"The {subtype} subtype is unknown to TorchAudio. As a result, the bits_per_sample " + "attribute will be set to 0. If you are seeing this warning, please " + "report by opening an issue on github (after checking for existing/closed ones). " + "You may otherwise ignore this warning." + ) + return _SUBTYPE_TO_BITS_PER_SAMPLE.get(subtype, 0) + + +_SUBTYPE_TO_ENCODING = { + 'PCM_S8': 'PCM_S', + 'PCM_16': 'PCM_S', + 'PCM_24': 'PCM_S', + 'PCM_32': 'PCM_S', + 'PCM_U8': 'PCM_U', + 'FLOAT': 'PCM_F', + 'DOUBLE': 'PCM_F', + 'ULAW': 'ULAW', + 'ALAW': 'ALAW', + 'VORBIS': 'VORBIS', +} + + +def _get_encoding(format: str, subtype: str): + if format == 'FLAC': + return 'FLAC' + return _SUBTYPE_TO_ENCODING.get(subtype, 'UNKNOWN') + + +@_mod_utils.requires_module("soundfile") +def info(filepath: str, format: Optional[str] = None) -> AudioMetaData: + """Get signal information of an audio file. + + Args: + filepath (path-like object or file-like object): + Source of audio data. + Note: + * This argument is intentionally annotated as ``str`` only, + for the consistency with "sox_io" backend, which has a restriction + on type annotation due to TorchScript compiler compatiblity. + format (str, optional): + Not used. PySoundFile does not accept format hint. + + Returns: + AudioMetaData: meta data of the given audio. + """ + sinfo = soundfile.info(filepath) + return AudioMetaData( + sinfo.samplerate, + sinfo.frames, + sinfo.channels, + bits_per_sample=_get_bit_depth(sinfo.subtype), + encoding=_get_encoding(sinfo.format, sinfo.subtype), ) - out = torch.from_numpy(out).t() - if not channels_first: - out = out.t() - # normalize if needed - # _audio_normalization(out, normalization) +_SUBTYPE2DTYPE = { + "PCM_S8": "int8", + "PCM_U8": "uint8", + "PCM_16": "int16", + "PCM_32": "int32", + "FLOAT": "float32", + "DOUBLE": "float64", +} + + +@_mod_utils.requires_module("soundfile") +def load( + filepath: str, + frame_offset: int = 0, + num_frames: int = -1, + normalize: bool = True, + channels_first: bool = True, + format: Optional[str] = None, +) -> Tuple[torch.Tensor, int]: + """Load audio data from file. + + Note: + The formats this function can handle depend on the soundfile installation. + This function is tested on the following formats; + + * WAV + + * 32-bit floating-point + * 32-bit signed integer + * 16-bit signed integer + * 8-bit unsigned integer - return out, sample_rate + * FLAC + * OGG/VORBIS + * SPHERE + By default (``normalize=True``, ``channels_first=True``), this function returns Tensor with + ``float32`` dtype and the shape of ``[channel, time]``. + The samples are normalized to fit in the range of ``[-1.0, 1.0]``. -@_mod_utils.requires_module('soundfile') -@_mod_utils.deprecated('Please use "torchaudio.load".', '0.9.0') -@common._impl_load_wav -def load_wav(filepath, **kwargs): - kwargs['normalization'] = 1 << 16 - return load(filepath, **kwargs) + When the input format is WAV with integer type, such as 32-bit signed integer, 16-bit + signed integer and 8-bit unsigned integer (24-bit signed integer is not supported), + by providing ``normalize=False``, this function can return integer Tensor, where the samples + are expressed within the whole range of the corresponding dtype, that is, ``int32`` tensor + for 32-bit signed PCM, ``int16`` for 16-bit signed PCM and ``uint8`` for 8-bit unsigned PCM. + ``normalize`` parameter has no effect on 32-bit floating-point WAV and other formats, such as + ``flac`` and ``mp3``. + For these formats, this function always returns ``float32`` Tensor with values normalized to + ``[-1.0, 1.0]``. -@_mod_utils.requires_module('soundfile') -@common._impl_save -def save(filepath: str, src: Tensor, sample_rate: int, precision: int = 16, channels_first: bool = True) -> None: - r"""See torchaudio.save""" + Args: + filepath (path-like object or file-like object): + Source of audio data. + Note: + * This argument is intentionally annotated as ``str`` only, + for the consistency with "sox_io" backend, which has a restriction + on type annotation due to TorchScript compiler compatiblity. + frame_offset (int): + Number of frames to skip before start reading data. + num_frames (int): + Maximum number of frames to read. ``-1`` reads all the remaining samples, + starting from ``frame_offset``. + This function may return the less number of frames if there is not enough + frames in the given file. + normalize (bool): + When ``True``, this function always return ``float32``, and sample values are + normalized to ``[-1.0, 1.0]``. + If input file is integer WAV, giving ``False`` will change the resulting Tensor type to + integer type. + This argument has no effect for formats other than integer WAV type. + channels_first (bool): + When True, the returned Tensor has dimension ``[channel, time]``. + Otherwise, the returned Tensor's dimension is ``[time, channel]``. + format (str, optional): + Not used. PySoundFile does not accept format hint. - ch_idx, len_idx = (0, 1) if channels_first else (1, 0) + Returns: + Tuple[torch.Tensor, int]: Resulting Tensor and sample rate. + If the input file has integer wav format and normalization is off, then it has + integer type, else ``float32`` type. If ``channels_first=True``, it has + ``[channel, time]`` else ``[time, channel]``. + """ + with soundfile.SoundFile(filepath, "r") as file_: + if file_.format != "WAV" or normalize: + dtype = "float32" + elif file_.subtype not in _SUBTYPE2DTYPE: + raise ValueError(f"Unsupported subtype: {file_.subtype}") + else: + dtype = _SUBTYPE2DTYPE[file_.subtype] - # check if save directory exists - abs_dirpath = os.path.dirname(os.path.abspath(filepath)) - if not os.path.isdir(abs_dirpath): - raise OSError("Directory does not exist: {}".format(abs_dirpath)) - # check that src is a CPU tensor - _misc_ops.check_input(src) - # Check/Fix shape of source data - if src.dim() == 1: - # 1d tensors as assumed to be mono signals - src.unsqueeze_(ch_idx) - elif src.dim() > 2 or src.size(ch_idx) > 16: - # assumes num_channels < 16 - raise ValueError( - "Expected format where C < 16, but found {}".format(src.size())) + frames = file_._prepare_read(frame_offset, None, num_frames) + waveform = file_.read(frames, dtype, always_2d=True) + sample_rate = file_.samplerate + waveform = torch.from_numpy(waveform) if channels_first: - src = src.t() + waveform = waveform.t() + return waveform, sample_rate + + +def _get_subtype_for_wav( + dtype: torch.dtype, + encoding: str, + bits_per_sample: int): + if not encoding: + if not bits_per_sample: + subtype = { + torch.uint8: "PCM_U8", + torch.int16: "PCM_16", + torch.int32: "PCM_32", + torch.float32: "FLOAT", + torch.float64: "DOUBLE", + }.get(dtype) + if not subtype: + raise ValueError(f"Unsupported dtype for wav: {dtype}") + return subtype + if bits_per_sample == 8: + return "PCM_U8" + return f"PCM_{bits_per_sample}" + if encoding == "PCM_S": + if not bits_per_sample: + return "PCM_32" + if bits_per_sample == 8: + raise ValueError("wav does not support 8-bit signed PCM encoding.") + return f"PCM_{bits_per_sample}" + if encoding == "PCM_U": + if bits_per_sample in (None, 8): + return "PCM_U8" + raise ValueError("wav only supports 8-bit unsigned PCM encoding.") + if encoding == "PCM_F": + if bits_per_sample in (None, 32): + return "FLOAT" + if bits_per_sample == 64: + return "DOUBLE" + raise ValueError("wav only supports 32/64-bit float PCM encoding.") + if encoding == "ULAW": + if bits_per_sample in (None, 8): + return "ULAW" + raise ValueError("wav only supports 8-bit mu-law encoding.") + if encoding == "ALAW": + if bits_per_sample in (None, 8): + return "ALAW" + raise ValueError("wav only supports 8-bit a-law encoding.") + raise ValueError(f"wav does not support {encoding}.") + + +def _get_subtype_for_sphere(encoding: str, bits_per_sample: int): + if encoding in (None, "PCM_S"): + return f"PCM_{bits_per_sample}" if bits_per_sample else "PCM_32" + if encoding in ("PCM_U", "PCM_F"): + raise ValueError(f"sph does not support {encoding} encoding.") + if encoding == "ULAW": + if bits_per_sample in (None, 8): + return "ULAW" + raise ValueError("sph only supports 8-bit for mu-law encoding.") + if encoding == "ALAW": + return "ALAW" + raise ValueError(f"sph does not support {encoding}.") - if src.dtype == torch.int64: - # Soundfile doesn't support int64 - src = src.type(torch.int32) - precision = "PCM_S8" if precision == 8 else "PCM_" + str(precision) +def _get_subtype( + dtype: torch.dtype, + format: str, + encoding: str, + bits_per_sample: int): + if format == "wav": + return _get_subtype_for_wav(dtype, encoding, bits_per_sample) + if format == "flac": + if encoding: + raise ValueError("flac does not support encoding.") + if not bits_per_sample: + return "PCM_24" + if bits_per_sample > 24: + raise ValueError("flac does not support bits_per_sample > 24.") + return "PCM_S8" if bits_per_sample == 8 else f"PCM_{bits_per_sample}" + if format in ("ogg", "vorbis"): + if encoding or bits_per_sample: + raise ValueError( + "ogg/vorbis does not support encoding/bits_per_sample.") + return "VORBIS" + if format == "sph": + return _get_subtype_for_sphere(encoding, bits_per_sample) + if format in ("nis", "nist"): + return "PCM_16" + raise ValueError(f"Unsupported format: {format}") - return soundfile.write(filepath, src, sample_rate, precision) +@_mod_utils.requires_module("soundfile") +def save( + filepath: str, + src: torch.Tensor, + sample_rate: int, + channels_first: bool = True, + compression: Optional[float] = None, + format: Optional[str] = None, + encoding: Optional[str] = None, + bits_per_sample: Optional[int] = None, +): + """Save audio data to file. -@_mod_utils.requires_module('soundfile') -@common._impl_info -def info(filepath: str) -> Tuple[SignalInfo, EncodingInfo]: - r"""See torchaudio.info""" + Note: + The formats this function can handle depend on the soundfile installation. + This function is tested on the following formats; - sfi = soundfile.info(filepath) + * WAV - precision = _subtype_to_precision[sfi.subtype] - si = SignalInfo(sfi.channels, sfi.samplerate, precision, sfi.frames) - ei = EncodingInfo(bits_per_sample=precision) - return si, ei + * 32-bit floating-point + * 32-bit signed integer + * 16-bit signed integer + * 8-bit unsigned integer + + * FLAC + * OGG/VORBIS + * SPHERE + + Args: + filepath (str or pathlib.Path): Path to audio file. + This functionalso handles ``pathlib.Path`` objects, but is annotated as ``str`` + for the consistency with "sox_io" backend, which has a restriction on type annotation + for TorchScript compiler compatiblity. + src (torch.Tensor): Audio data to save. must be 2D tensor. + sample_rate (int): sampling rate + channels_first (bool): If ``True``, the given tensor is interpreted as ``[channel, time]``, + otherwise ``[time, channel]``. + compression (Optional[float]): Not used. + It is here only for interface compatibility reson with "sox_io" backend. + format (str, optional): Override the audio format. + When ``filepath`` argument is path-like object, audio format is + inferred from file extension. If the file extension is missing or + different, you can specify the correct format with this argument. + + When ``filepath`` argument is file-like object, + this argument is required. + + Valid values are ``"wav"``, ``"ogg"``, ``"vorbis"``, + ``"flac"`` and ``"sph"``. + encoding (str, optional): Changes the encoding for supported formats. + This argument is effective only for supported formats, sush as + ``"wav"``, ``""flac"`` and ``"sph"``. Valid values are; + + - ``"PCM_S"`` (signed integer Linear PCM) + - ``"PCM_U"`` (unsigned integer Linear PCM) + - ``"PCM_F"`` (floating point PCM) + - ``"ULAW"`` (mu-law) + - ``"ALAW"`` (a-law) + + bits_per_sample (int, optional): Changes the bit depth for the + supported formats. + When ``format`` is one of ``"wav"``, ``"flac"`` or ``"sph"``, + you can change the bit depth. + Valid values are ``8``, ``16``, ``24``, ``32`` and ``64``. + + Supported formats/encodings/bit depth/compression are: + + ``"wav"`` + - 32-bit floating-point PCM + - 32-bit signed integer PCM + - 24-bit signed integer PCM + - 16-bit signed integer PCM + - 8-bit unsigned integer PCM + - 8-bit mu-law + - 8-bit a-law + + Note: Default encoding/bit depth is determined by the dtype of + the input Tensor. + + ``"flac"`` + - 8-bit + - 16-bit + - 24-bit (default) + + ``"ogg"``, ``"vorbis"`` + - Doesn't accept changing configuration. + + ``"sph"`` + - 8-bit signed integer PCM + - 16-bit signed integer PCM + - 24-bit signed integer PCM + - 32-bit signed integer PCM (default) + - 8-bit mu-law + - 8-bit a-law + - 16-bit a-law + - 24-bit a-law + - 32-bit a-law + + """ + if src.ndim != 2: + raise ValueError(f"Expected 2D Tensor, got {src.ndim}D.") + if compression is not None: + warnings.warn( + '`save` function of "soundfile" backend does not support "compression" parameter. ' + "The argument is silently ignored." + ) + if hasattr(filepath, 'write'): + if format is None: + raise RuntimeError('`format` is required when saving to file object.') + ext = format.lower() + else: + ext = str(filepath).split(".")[-1].lower() + + if bits_per_sample not in (None, 8, 16, 24, 32, 64): + raise ValueError("Invalid bits_per_sample.") + subtype = _get_subtype(src.dtype, ext, encoding, bits_per_sample) + + # sph is a extension used in TED-LIUM but soundfile does not recognize it as NIST format, + # so we extend the extensions manually here + if ext in ["nis", "nist", "sph"] and format is None: + format = "NIST" + + if channels_first: + src = src.t() + + soundfile.write( + file=filepath, data=src, samplerate=sample_rate, subtype=subtype, format=format + ) diff --git a/torchaudio/backend/sox_backend.py b/torchaudio/backend/sox_backend.py deleted file mode 100644 index bf167dd195..0000000000 --- a/torchaudio/backend/sox_backend.py +++ /dev/null @@ -1,294 +0,0 @@ -import os.path -from typing import Any, Optional, Tuple - -import torch -from torch import Tensor - -from torchaudio._internal import ( - module_utils as _mod_utils, - misc_ops as _misc_ops, -) -from . import common -from .common import SignalInfo, EncodingInfo - -if _mod_utils.is_module_available('torchaudio._torchaudio'): - from torchaudio import _torchaudio - - -@_mod_utils.requires_module('torchaudio._torchaudio') -@common._impl_load -def load(filepath: str, - out: Optional[Tensor] = None, - normalization: bool = True, - channels_first: bool = True, - num_frames: int = 0, - offset: int = 0, - signalinfo: SignalInfo = None, - encodinginfo: EncodingInfo = None, - filetype: Optional[str] = None) -> Tuple[Tensor, int]: - r"""See torchaudio.load""" - - # stringify if `pathlib.Path` (noop if already `str`) - filepath = str(filepath) - # check if valid file - if not os.path.isfile(filepath): - raise OSError("{} not found or is a directory".format(filepath)) - - # initialize output tensor - if out is not None: - _misc_ops.check_input(out) - else: - out = torch.FloatTensor() - - if num_frames < -1: - raise ValueError("Expected value for num_samples -1 (entire file) or >=0") - if offset < 0: - raise ValueError("Expected positive offset value") - - sample_rate = _torchaudio.read_audio_file( - filepath, - out, - channels_first, - num_frames, - offset, - signalinfo, - encodinginfo, - filetype - ) - - # normalize if needed - _misc_ops.normalize_audio(out, normalization) - - return out, sample_rate - - -@_mod_utils.requires_module('torchaudio._torchaudio') -@_mod_utils.deprecated('Please use "torchaudio.load".', '0.9.0') -@common._impl_load_wav -def load_wav(filepath, **kwargs): - kwargs['normalization'] = 1 << 16 - return load(filepath, **kwargs) - - -@_mod_utils.requires_module('torchaudio._torchaudio') -@common._impl_save -def save(filepath: str, src: Tensor, sample_rate: int, precision: int = 16, channels_first: bool = True) -> None: - r"""See torchaudio.save""" - - si = sox_signalinfo_t() - ch_idx = 0 if channels_first else 1 - si.rate = sample_rate - si.channels = 1 if src.dim() == 1 else src.size(ch_idx) - si.length = src.numel() - si.precision = precision - return save_encinfo(filepath, src, channels_first, si) - - -@_mod_utils.requires_module('torchaudio._torchaudio') -@common._impl_info -def info(filepath: str) -> Tuple[SignalInfo, EncodingInfo]: - r"""See torchaudio.info""" - return _torchaudio.get_info(filepath) - - -@_mod_utils.requires_module('torchaudio._torchaudio') -@_mod_utils.deprecated( - 'Please migrate to "sox_io" backend. See https://github.com/pytorch/audio/issues/903 for the detail', - '0.9.0') -def save_encinfo(filepath: str, - src: Tensor, - channels_first: bool = True, - signalinfo: Optional[SignalInfo] = None, - encodinginfo: Optional[EncodingInfo] = None, - filetype: Optional[str] = None) -> None: - r"""Saves a tensor of an audio signal to disk as a standard format like mp3, wav, etc. - - Args: - filepath (str): Path to audio file - src (Tensor): An input 2D tensor of shape `[C x L]` or `[L x C]` where L is - the number of audio frames, C is the number of channels - channels_first (bool, optional): Set channels first or length first in result. (Default: ``True``) - signalinfo (sox_signalinfo_t, optional): A sox_signalinfo_t type, which could be helpful if the - audio type cannot be automatically determined (Default: ``None``). - encodinginfo (sox_encodinginfo_t, optional): A sox_encodinginfo_t type, which could be set if the - audio type cannot be automatically determined (Default: ``None``). - filetype (str, optional): A filetype or extension to be set if sox cannot determine it - automatically. (Default: ``None``) - - Example - >>> data, sample_rate = torchaudio.load('foo.mp3') - >>> torchaudio.save('foo.wav', data, sample_rate) - - """ - ch_idx, len_idx = (0, 1) if channels_first else (1, 0) - - # check if save directory exists - abs_dirpath = os.path.dirname(os.path.abspath(filepath)) - if not os.path.isdir(abs_dirpath): - raise OSError("Directory does not exist: {}".format(abs_dirpath)) - # check that src is a CPU tensor - _misc_ops.check_input(src) - # Check/Fix shape of source data - if src.dim() == 1: - # 1d tensors as assumed to be mono signals - src.unsqueeze_(ch_idx) - elif src.dim() > 2 or src.size(ch_idx) > 16: - # assumes num_channels < 16 - raise ValueError( - "Expected format where C < 16, but found {}".format(src.size())) - # sox stores the sample rate as a float, though practically sample rates are almost always integers - # convert integers to floats - if signalinfo: - if signalinfo.rate and not isinstance(signalinfo.rate, float): - if float(signalinfo.rate) == signalinfo.rate: - signalinfo.rate = float(signalinfo.rate) - else: - raise TypeError('Sample rate should be a float or int') - # check if the bit precision (i.e. bits per sample) is an integer - if signalinfo.precision and not isinstance(signalinfo.precision, int): - if int(signalinfo.precision) == signalinfo.precision: - signalinfo.precision = int(signalinfo.precision) - else: - raise TypeError('Bit precision should be an integer') - # programs such as librosa normalize the signal, unnormalize if detected - if src.min() >= -1.0 and src.max() <= 1.0: - src = src * (1 << 31) - src = src.long() - # set filetype and allow for files with no extensions - extension = os.path.splitext(filepath)[1] - filetype = extension[1:] if len(extension) > 0 else filetype - # transpose from C x L -> L x C - if channels_first: - src = src.transpose(1, 0) - # save data to file - src = src.contiguous() - _torchaudio.write_audio_file(filepath, src, signalinfo, encodinginfo, filetype) - - -@_mod_utils.requires_module('torchaudio._torchaudio') -@_mod_utils.deprecated( - 'Please migrate to "sox_io" backend. See https://github.com/pytorch/audio/issues/903 for the detail', - '0.9.0') -def sox_signalinfo_t() -> SignalInfo: - r"""Create a sox_signalinfo_t object. This object can be used to set the sample - rate, number of channels, length, bit precision and headroom multiplier - primarily for effects - - Returns: sox_signalinfo_t(object) - - rate (float), sample rate as a float, practically will likely be an integer float - - channel (int), number of audio channels - - precision (int), bit precision - - length (int), length of audio in samples * channels, 0 for unspecified and -1 for unknown - - mult (float, optional), headroom multiplier for effects and ``None`` for no multiplier - - Example - >>> si = torchaudio.sox_signalinfo_t() - >>> si.channels = 1 - >>> si.rate = 16000. - >>> si.precision = 16 - >>> si.length = 0 - """ - return _torchaudio.sox_signalinfo_t() - - -@_mod_utils.requires_module('torchaudio._torchaudio') -@_mod_utils.deprecated( - 'Please migrate to "sox_io" backend. See https://github.com/pytorch/audio/issues/903 for the detail', - '0.9.0') -def sox_encodinginfo_t() -> EncodingInfo: - r"""Create a sox_encodinginfo_t object. This object can be used to set the encoding - type, bit precision, compression factor, reverse bytes, reverse nibbles, - reverse bits and endianness. This can be used in an effects chain to encode the - final output or to save a file with a specific encoding. For example, one could - use the sox ulaw encoding to do 8-bit ulaw encoding. Note in a tensor output - the result will be a 32-bit number, but number of unique values will be determined by - the bit precision. - - Returns: sox_encodinginfo_t(object) - - encoding (sox_encoding_t), output encoding - - bits_per_sample (int), bit precision, same as `precision` in sox_signalinfo_t - - compression (float), compression for lossy formats, 0.0 for default compression - - reverse_bytes (sox_option_t), reverse bytes, use sox_option_default - - reverse_nibbles (sox_option_t), reverse nibbles, use sox_option_default - - reverse_bits (sox_option_t), reverse bytes, use sox_option_default - - opposite_endian (sox_bool), change endianness, use sox_false - - Example - >>> ei = torchaudio.sox_encodinginfo_t() - >>> ei.encoding = torchaudio.get_sox_encoding_t(1) - >>> ei.bits_per_sample = 16 - >>> ei.compression = 0 - >>> ei.reverse_bytes = torchaudio.get_sox_option_t(2) - >>> ei.reverse_nibbles = torchaudio.get_sox_option_t(2) - >>> ei.reverse_bits = torchaudio.get_sox_option_t(2) - >>> ei.opposite_endian = torchaudio.get_sox_bool(0) - - """ - ei = _torchaudio.sox_encodinginfo_t() - sdo = get_sox_option_t(2) # sox_default_option - ei.reverse_bytes = sdo - ei.reverse_nibbles = sdo - ei.reverse_bits = sdo - return ei - - -@_mod_utils.requires_module('torchaudio._torchaudio') -@_mod_utils.deprecated( - 'Please migrate to "sox_io" backend. See https://github.com/pytorch/audio/issues/903 for the detail', - '0.9.0') -def get_sox_encoding_t(i: int = None) -> EncodingInfo: - r"""Get enum of sox_encoding_t for sox encodings. - - Args: - i (int, optional): Choose type or get a dict with all possible options - use ``__members__`` to see all options when not specified. (Default: ``None``) - - Returns: - sox_encoding_t: A sox_encoding_t type for output encoding - """ - if i is None: - # one can see all possible values using the .__members__ attribute - return _torchaudio.sox_encoding_t - else: - return _torchaudio.sox_encoding_t(i) - - -@_mod_utils.requires_module('torchaudio._torchaudio') -@_mod_utils.deprecated( - 'Please migrate to "sox_io" backend. See https://github.com/pytorch/audio/issues/903 for the detail', - '0.9.0') -def get_sox_option_t(i: int = 2) -> Any: - r"""Get enum of sox_option_t for sox encodinginfo options. - - Args: - i (int, optional): Choose type or get a dict with all possible options - use ``__members__`` to see all options when not specified. - (Default: ``sox_option_default`` or ``2``) - Returns: - sox_option_t: A sox_option_t type - """ - if i is None: - return _torchaudio.sox_option_t - else: - return _torchaudio.sox_option_t(i) - - -@_mod_utils.requires_module('torchaudio._torchaudio') -@_mod_utils.deprecated( - 'Please migrate to "sox_io" backend. See https://github.com/pytorch/audio/issues/903 for the detail', - '0.9.0') -def get_sox_bool(i: int = 0) -> Any: - r"""Get enum of sox_bool for sox encodinginfo options. - - Args: - i (int, optional): Choose type or get a dict with all possible options - use ``__members__`` to see all options when not specified. (Default: - ``sox_false`` or ``0``) - - Returns: - sox_bool: A sox_bool type - """ - if i is None: - return _torchaudio.sox_bool - else: - return _torchaudio.sox_bool(i) diff --git a/torchaudio/backend/sox_io_backend.py b/torchaudio/backend/sox_io_backend.py index 0eaf02118a..65b3e8bd50 100644 --- a/torchaudio/backend/sox_io_backend.py +++ b/torchaudio/backend/sox_io_backend.py @@ -1,5 +1,4 @@ import os -import warnings from typing import Tuple, Optional import torch @@ -11,7 +10,7 @@ from .common import AudioMetaData -@_mod_utils.requires_module('torchaudio._torchaudio') +@_mod_utils.requires_sox() def info( filepath: str, format: Optional[str] = None, @@ -22,18 +21,22 @@ def info( filepath (path-like object or file-like object): Source of audio data. When the function is not compiled by TorchScript, (e.g. ``torch.jit.script``), the following types are accepted; + * ``path-like``: file path * ``file-like``: Object with ``read(size: int) -> bytes`` method, which returns byte string of at most ``size`` length. + When the function is compiled by TorchScript, only ``str`` type is allowed. Note: + * When the input type is file-like object, this function cannot get the correct length (``num_samples``) for certain formats, such as ``mp3`` and ``vorbis``. In this case, the value of ``num_samples`` is ``0``. * This argument is intentionally annotated as ``str`` only due to TorchScript compiler compatibility. + format (str, optional): Override the format detection with the given format. Providing the argument might help when libsox can not infer the format @@ -51,7 +54,7 @@ def info( return AudioMetaData(*sinfo) -@_mod_utils.requires_module('torchaudio._torchaudio') +@_mod_utils.requires_sox() def load( filepath: str, frame_offset: int = 0, @@ -70,6 +73,7 @@ def load( * 32-bit floating-point * 32-bit signed integer + * 24-bit signed integer * 16-bit signed integer * 8-bit unsigned integer (WAV only) @@ -89,10 +93,11 @@ def load( The samples are normalized to fit in the range of ``[-1.0, 1.0]``. When the input format is WAV with integer type, such as 32-bit signed integer, 16-bit - signed integer and 8-bit unsigned integer (24-bit signed integer is not supported), - by providing ``normalize=False``, this function can return integer Tensor, where the samples - are expressed within the whole range of the corresponding dtype, that is, ``int32`` tensor - for 32-bit signed PCM, ``int16`` for 16-bit signed PCM and ``uint8`` for 8-bit unsigned PCM. + signed integer, 24-bit signed integer, and 8-bit unsigned integer, by providing ``normalize=False``, + this function can return integer Tensor, where the samples are expressed within the whole range + of the corresponding dtype, that is, ``int32`` tensor for 32-bit signed PCM, + ``int16`` for 16-bit signed PCM and ``uint8`` for 8-bit unsigned PCM. Since torch does not + support ``int24`` dtype, 24-bit signed PCM are converted to ``int32`` tensors. ``normalize`` parameter has no effect on 32-bit floating-point WAV and other formats, such as ``flac`` and ``mp3``. @@ -103,14 +108,15 @@ def load( filepath (path-like object or file-like object): Source of audio data. When the function is not compiled by TorchScript, (e.g. ``torch.jit.script``), the following types are accepted; + * ``path-like``: file path * ``file-like``: Object with ``read(size: int) -> bytes`` method, which returns byte string of at most ``size`` length. + When the function is compiled by TorchScript, only ``str`` type is allowed. - Note: - * This argument is intentionally annotated as ``str`` only due to - TorchScript compiler compatibility. + Note: This argument is intentionally annotated as ``str`` only due to + TorchScript compiler compatibility. frame_offset (int): Number of frames to skip before start reading data. num_frames (int): @@ -147,27 +153,7 @@ def load( filepath, frame_offset, num_frames, normalize, channels_first, format) -@torch.jit.unused -def _save( - filepath: str, - src: torch.Tensor, - sample_rate: int, - channels_first: bool = True, - compression: Optional[float] = None, - format: Optional[str] = None, - dtype: Optional[str] = None, -): - if hasattr(filepath, 'write'): - if format is None: - raise RuntimeError('`format` is required when saving to file object.') - torchaudio._torchaudio.save_audio_fileobj( - filepath, src, sample_rate, channels_first, compression, format, dtype) - else: - torch.ops.torchaudio.sox_io_save_audio_file( - os.fspath(filepath), src, sample_rate, channels_first, compression, format, dtype) - - -@_mod_utils.requires_module('torchaudio._torchaudio') +@_mod_utils.requires_sox() def save( filepath: str, src: torch.Tensor, @@ -175,83 +161,157 @@ def save( channels_first: bool = True, compression: Optional[float] = None, format: Optional[str] = None, - dtype: Optional[str] = None, + encoding: Optional[str] = None, + bits_per_sample: Optional[int] = None, ): """Save audio data to file. - Note: - Supported formats are; - - * WAV, AMB - - * 32-bit floating-point - * 32-bit signed integer - * 16-bit signed integer - * 8-bit unsigned integer - - * MP3 - * FLAC - * OGG/VORBIS - * SPHERE - * AMR-NB - - To save ``MP3``, ``FLAC``, ``OGG/VORBIS``, and other codecs ``libsox`` does not - handle natively, your installation of ``torchaudio`` has to be linked to ``libsox`` - and corresponding codec libraries such as ``libmad`` or ``libmp3lame`` etc. - Args: - filepath (str or pathlib.Path): - Path to save file. This function also handles ``pathlib.Path`` objects, but is annotated + filepath (str or pathlib.Path): Path to save file. + This function also handles ``pathlib.Path`` objects, but is annotated as ``str`` for TorchScript compiler compatibility. - tensor (torch.Tensor): Audio data to save. must be 2D tensor. + src (torch.Tensor): Audio data to save. must be 2D tensor. sample_rate (int): sampling rate - channels_first (bool): - If ``True``, the given tensor is interpreted as ``[channel, time]``, + channels_first (bool): If ``True``, the given tensor is interpreted as ``[channel, time]``, otherwise ``[time, channel]``. - compression (Optional[float]): - Used for formats other than WAV. This corresponds to ``-C`` option of ``sox`` command. + compression (Optional[float]): Used for formats other than WAV. + This corresponds to ``-C`` option of ``sox`` command. - * | ``MP3``: Either bitrate (in ``kbps``) with quality factor, such as ``128.2``, or - | VBR encoding with quality factor such as ``-4.2``. Default: ``-4.5``. - * | ``FLAC``: compression level. Whole number from ``0`` to ``8``. - | ``8`` is default and highest compression. - * | ``OGG/VORBIS``: number from ``-1`` to ``10``; ``-1`` is the highest compression - | and lowest quality. Default: ``3``. + ``"mp3"`` + Either bitrate (in ``kbps``) with quality factor, such as ``128.2``, or + VBR encoding with quality factor such as ``-4.2``. Default: ``-4.5``. - See the detail at http://sox.sourceforge.net/soxformat.html. - format (str, optional): - Output audio format. This is required when the output audio format cannot be infered from - ``filepath``, (such as file extension or ``name`` attribute of the given file object). - dtype (str, optional) - Output tensor dtype. - Valid values: ``"uint8", "int16", "int32", "float32", "float64", None`` - ``dtype=None`` means no conversion is performed. - ``dtype`` parameter is only effective for ``float32`` Tensor. - """ - if src.dtype == torch.float32 and dtype is None: - warnings.warn( - '`dtype` default value will be changed to `int16` in 0.9 release.' - 'Specify `dtype` to suppress this warning.' - ) - if not torch.jit.is_scripting(): - _save(filepath, src, sample_rate, channels_first, compression, format, dtype) - return - torch.ops.torchaudio.sox_io_save_audio_file( - filepath, src, sample_rate, channels_first, compression, format, dtype) + ``"flac"`` + Whole number from ``0`` to ``8``. ``8`` is default and highest compression. + ``"ogg"``, ``"vorbis"`` + Number from ``-1`` to ``10``; ``-1`` is the highest compression + and lowest quality. Default: ``3``. -@_mod_utils.requires_module('torchaudio._torchaudio') -@_mod_utils.deprecated('Please use "torchaudio.load".', '0.9.0') -def load_wav( - filepath: str, - frame_offset: int = 0, - num_frames: int = -1, - channels_first: bool = True, -) -> Tuple[torch.Tensor, int]: - """Load wave file. + See the detail at http://sox.sourceforge.net/soxformat.html. + format (str, optional): Override the audio format. + When ``filepath`` argument is path-like object, audio format is infered from + file extension. If file extension is missing or different, you can specify the + correct format with this argument. + + When ``filepath`` argument is file-like object, this argument is required. + + Valid values are ``"wav"``, ``"mp3"``, ``"ogg"``, ``"vorbis"``, ``"amr-nb"``, + ``"amb"``, ``"flac"``, ``"sph"``, ``"gsm"``, and ``"htk"``. + + encoding (str, optional): Changes the encoding for the supported formats. + This argument is effective only for supported formats, such as ``"wav"``, ``""amb"`` + and ``"sph"``. Valid values are; + + - ``"PCM_S"`` (signed integer Linear PCM) + - ``"PCM_U"`` (unsigned integer Linear PCM) + - ``"PCM_F"`` (floating point PCM) + - ``"ULAW"`` (mu-law) + - ``"ALAW"`` (a-law) + + Default values + If not provided, the default value is picked based on ``format`` and ``bits_per_sample``. + + ``"wav"``, ``"amb"`` + - | If both ``encoding`` and ``bits_per_sample`` are not provided, the ``dtype`` of the + | Tensor is used to determine the default value. + - ``"PCM_U"`` if dtype is ``uint8`` + - ``"PCM_S"`` if dtype is ``int16`` or ``int32` + - ``"PCM_F"`` if dtype is ``float32`` + + - ``"PCM_U"`` if ``bits_per_sample=8`` + - ``"PCM_S"`` otherwise + + ``"sph"`` format; + - the default value is ``"PCM_S"`` + + bits_per_sample (int, optional): Changes the bit depth for the supported formats. + When ``format`` is one of ``"wav"``, ``"flac"``, ``"sph"``, or ``"amb"``, you can change the + bit depth. Valid values are ``8``, ``16``, ``32`` and ``64``. + + Default Value; + If not provided, the default values are picked based on ``format`` and ``"encoding"``; + + ``"wav"``, ``"amb"``; + - | If both ``encoding`` and ``bits_per_sample`` are not provided, the ``dtype`` of the + | Tensor is used. + - ``8`` if dtype is ``uint8`` + - ``16`` if dtype is ``int16`` + - ``32`` if dtype is ``int32`` or ``float32`` + + - ``8`` if ``encoding`` is ``"PCM_U"``, ``"ULAW"`` or ``"ALAW"`` + - ``16`` if ``encoding`` is ``"PCM_S"`` + - ``32`` if ``encoding`` is ``"PCM_F"`` + + ``"flac"`` format; + - the default value is ``24`` + + ``"sph"`` format; + - ``16`` if ``encoding`` is ``"PCM_U"``, ``"PCM_S"``, ``"PCM_F"`` or not provided. + - ``8`` if ``encoding`` is ``"ULAW"`` or ``"ALAW"`` + + ``"amb"`` format; + - ``8`` if ``encoding`` is ``"PCM_U"``, ``"ULAW"`` or ``"ALAW"`` + - ``16`` if ``encoding`` is ``"PCM_S"`` or not provided. + - ``32`` if ``encoding`` is ``"PCM_F"`` + + Supported formats/encodings/bit depth/compression are; + + ``"wav"``, ``"amb"`` + - 32-bit floating-point PCM + - 32-bit signed integer PCM + - 24-bit signed integer PCM + - 16-bit signed integer PCM + - 8-bit unsigned integer PCM + - 8-bit mu-law + - 8-bit a-law + + Note: Default encoding/bit depth is determined by the dtype of the input Tensor. + + ``"mp3"`` + Fixed bit rate (such as 128kHz) and variable bit rate compression. + Default: VBR with high quality. + + ``"flac"`` + - 8-bit + - 16-bit + - 24-bit (default) + + ``"ogg"``, ``"vorbis"`` + - Different quality level. Default: approx. 112kbps + + ``"sph"`` + - 8-bit signed integer PCM + - 16-bit signed integer PCM + - 24-bit signed integer PCM + - 32-bit signed integer PCM (default) + - 8-bit mu-law + - 8-bit a-law + - 16-bit a-law + - 24-bit a-law + - 32-bit a-law + + ``"amr-nb"`` + Bitrate ranging from 4.75 kbit/s to 12.2 kbit/s. Default: 4.75 kbit/s + + ``"gsm"`` + Lossy Speech Compression, CPU intensive. + + ``"htk"`` + Uses a default single-channel 16-bit PCM format. - This function is defined only for the purpose of compatibility against other backend - for simple usecases, such as ``torchaudio.load_wav(filepath)``. - The implementation is same as :py:func:`load`. + Note: + To save into formats that ``libsox`` does not handle natively, (such as ``"mp3"``, + ``"flac"``, ``"ogg"`` and ``"vorbis"``), your installation of ``torchaudio`` has + to be linked to ``libsox`` and corresponding codec libraries such as ``libmad`` + or ``libmp3lame`` etc. """ - return load(filepath, frame_offset, num_frames, normalize=False, channels_first=channels_first) + if not torch.jit.is_scripting(): + if hasattr(filepath, 'write'): + torchaudio._torchaudio.save_audio_fileobj( + filepath, src, sample_rate, channels_first, compression, + format, encoding, bits_per_sample) + return + filepath = os.fspath(filepath) + torch.ops.torchaudio.sox_io_save_audio_file( + filepath, src, sample_rate, channels_first, compression, format, encoding, bits_per_sample) diff --git a/torchaudio/backend/utils.py b/torchaudio/backend/utils.py index b888c04c48..8aa3612dfc 100644 --- a/torchaudio/backend/utils.py +++ b/torchaudio/backend/utils.py @@ -3,13 +3,11 @@ from typing import Optional, List import torchaudio -from torchaudio._internal.module_utils import is_module_available +from torchaudio._internal import module_utils as _mod_utils from . import ( no_backend, - sox_backend, sox_io_backend, soundfile_backend, - _soundfile_backend, ) __all__ = [ @@ -26,10 +24,9 @@ def list_audio_backends() -> List[str]: List[str]: The list of available backends. """ backends = [] - if is_module_available('soundfile'): + if _mod_utils.is_module_available('soundfile'): backends.append('soundfile') - if is_module_available('torchaudio._torchaudio'): - backends.append('sox') + if _mod_utils.is_sox_available(): backends.append('sox_io') return backends @@ -39,15 +36,9 @@ def set_audio_backend(backend: Optional[str]): Args: backend (Optional[str]): Name of the backend. - One of ``"sox"``, ``"sox_io"`` or ``"soundfile"`` based on availability + One of ``"sox_io"`` or ``"soundfile"`` based on availability of the system. If ``None`` is provided the current backend is unassigned. """ - if torchaudio.USE_SOUNDFILE_LEGACY_INTERFACE is not None: - warnings.warn( - '"torchaudio.USE_SOUNDFILE_LEGACY_INTERFACE" flag is depredated and will be removed in 0.9.0. ' - 'Please remove the use of flag.' - ) - if backend is not None and backend not in list_audio_backends(): raise RuntimeError( f'Backend "{backend}" is not one of ' @@ -55,33 +46,20 @@ def set_audio_backend(backend: Optional[str]): if backend is None: module = no_backend - elif backend == 'sox': - warnings.warn( - '"sox" backend is depredated and will be removed in 0.9.0. ' - 'Please use "sox_io" backend.' - ) - module = sox_backend elif backend == 'sox_io': module = sox_io_backend elif backend == 'soundfile': - if torchaudio.USE_SOUNDFILE_LEGACY_INTERFACE: - warnings.warn( - 'The legacy interface of "soundfile" backend is depredated and will be removed in 0.9.0. ' - 'Please migrate to the new interface.' - ) - module = soundfile_backend - else: - module = _soundfile_backend + module = soundfile_backend else: raise NotImplementedError(f'Unexpected backend "{backend}"') - for func in ['save', 'load', 'load_wav', 'info']: + for func in ['save', 'load', 'info']: setattr(torchaudio, func, getattr(module, func)) def _init_audio_backend(): backends = list_audio_backends() - if 'sox' in backends: + if 'sox_io' in backends: set_audio_backend('sox_io') elif 'soundfile' in backends: set_audio_backend('soundfile') @@ -98,10 +76,8 @@ def get_audio_backend() -> Optional[str]: """ if torchaudio.load == no_backend.load: return None - if torchaudio.load == sox_backend.load: - return 'sox' if torchaudio.load == sox_io_backend.load: return 'sox_io' - if torchaudio.load in [soundfile_backend.load, _soundfile_backend.load]: + if torchaudio.load == soundfile_backend.load: return 'soundfile' raise ValueError('Unknown backend.') diff --git a/torchaudio/compliance/kaldi.py b/torchaudio/compliance/kaldi.py index 5b47ef3350..f1e1ddf5b5 100644 --- a/torchaudio/compliance/kaldi.py +++ b/torchaudio/compliance/kaldi.py @@ -793,7 +793,7 @@ def _get_sinc_resample_kernel(orig_freq: int, new_freq: int, lowpass_filter_widt t = t.clamp_(-lowpass_filter_width, lowpass_filter_width) t *= math.pi # we do not use torch.hann_window here as we need to evaluate the window - # at spectifics positions, not over a regular grid. + # at specific positions, not over a regular grid. window = torch.cos(t / lowpass_filter_width / 2)**2 kernel = torch.where(t == 0, torch.tensor(1.).to(t), torch.sin(t) / t) kernel.mul_(window) diff --git a/torchaudio/csrc/CMakeLists.txt b/torchaudio/csrc/CMakeLists.txt index f9c3a4d08f..fc033699b2 100644 --- a/torchaudio/csrc/CMakeLists.txt +++ b/torchaudio/csrc/CMakeLists.txt @@ -5,16 +5,31 @@ get_property(TORCHAUDIO_THIRD_PARTIES GLOBAL PROPERTY TORCHAUDIO_THIRD_PARTIES) ################################################################################ set( LIBTORCHAUDIO_SOURCES - sox/io.cpp - sox/utils.cpp - sox/effects.cpp - sox/effects_chain.cpp + lfilter.cpp + overdrive.cpp + utils.cpp ) if(BUILD_TRANSDUCER) list(APPEND LIBTORCHAUDIO_SOURCES transducer.cpp) endif() +if(BUILD_KALDI) + list(APPEND LIBTORCHAUDIO_SOURCES kaldi.cpp) +endif() + +if(BUILD_SOX) + set( + SOX_SOURCES + sox/io.cpp + sox/utils.cpp + sox/effects.cpp + sox/effects_chain.cpp + sox/types.cpp + ) + list(APPEND LIBTORCHAUDIO_SOURCES ${SOX_SOURCES}) +endif() + ################################################################################ # libtorchaudio.so ################################################################################ @@ -34,6 +49,7 @@ if(BUILD_LIBTORCHAUDIO) target_link_libraries( libtorchaudio + ${TORCH_LIBRARIES} ${TORCHAUDIO_THIRD_PARTIES} ) @@ -54,11 +70,13 @@ if (BUILD_TORCHAUDIO_PYTHON_EXTENSION) _torchaudio SHARED pybind.cpp - sox/legacy.cpp ${LIBTORCHAUDIO_SOURCES} ) set_target_properties(_torchaudio PROPERTIES PREFIX "") + if (MSVC) + set_target_properties(_torchaudio PROPERTIES SUFFIX ".pyd") + endif(MSVC) if (APPLE) # https://github.com/facebookarchive/caffe2/issues/854#issuecomment-364538485 @@ -70,6 +88,14 @@ if (BUILD_TORCHAUDIO_PYTHON_EXTENSION) _torchaudio PRIVATE TORCH_API_INCLUDE_EXTENSION_H ) + if (BUILD_SOX) + target_compile_definitions(_torchaudio PRIVATE INCLUDE_SOX) + endif() + + if (BUILD_KALDI) + target_compile_definitions(_torchaudio PRIVATE INCLUDE_KALDI) + endif() + target_include_directories( _torchaudio PRIVATE @@ -80,12 +106,22 @@ if (BUILD_TORCHAUDIO_PYTHON_EXTENSION) # See https://github.com/pytorch/pytorch/issues/38122 find_library(TORCH_PYTHON_LIBRARY torch_python PATHS "${TORCH_INSTALL_PREFIX}/lib") + if (WIN32) + find_package(Python3 ${PYTHON_VERSION} EXACT COMPONENTS Development) + set(ADDITIONAL_ITEMS Python3::Python) + endif() + target_link_libraries( _torchaudio ${TORCH_LIBRARIES} ${TORCH_PYTHON_LIBRARY} ${TORCHAUDIO_THIRD_PARTIES} + ${ADDITIONAL_ITEMS} ) - install(TARGETS _torchaudio LIBRARY DESTINATION ${CMAKE_INSTALL_PREFIX}) + install( + TARGETS _torchaudio + LIBRARY DESTINATION . + RUNTIME DESTINATION . # For Windows + ) endif() diff --git a/torchaudio/csrc/kaldi.cpp b/torchaudio/csrc/kaldi.cpp new file mode 100644 index 0000000000..6f2b36c28f --- /dev/null +++ b/torchaudio/csrc/kaldi.cpp @@ -0,0 +1,93 @@ +#include +#include "feat/pitch-functions.h" + +namespace torchaudio { +namespace kaldi { + +namespace { + +torch::Tensor denormalize(const torch::Tensor& t) { + auto ret = t; + auto pos = t > 0, neg = t < 0; + ret.index_put({pos}, t.index({pos}) * 32767); + ret.index_put({neg}, t.index({neg}) * 32768); + return ret; +} + +torch::Tensor compute_kaldi_pitch( + const torch::Tensor& wave, + const ::kaldi::PitchExtractionOptions& opts) { + ::kaldi::VectorBase<::kaldi::BaseFloat> input(wave); + ::kaldi::Matrix<::kaldi::BaseFloat> output; + ::kaldi::ComputeKaldiPitch(opts, input, &output); + return output.tensor_; +} + +} // namespace + +torch::Tensor ComputeKaldiPitch( + const torch::Tensor& wave, + double sample_frequency, + double frame_length, + double frame_shift, + double min_f0, + double max_f0, + double soft_min_f0, + double penalty_factor, + double lowpass_cutoff, + double resample_frequency, + double delta_pitch, + double nccf_ballast, + int64_t lowpass_filter_width, + int64_t upsample_filter_width, + int64_t max_frames_latency, + int64_t frames_per_chunk, + bool simulate_first_pass_online, + int64_t recompute_frame, + bool snip_edges) { + TORCH_CHECK(wave.ndimension() == 2, "Input tensor must be 2 dimentional."); + TORCH_CHECK(wave.device().is_cpu(), "Input tensor must be on CPU."); + TORCH_CHECK( + wave.dtype() == torch::kFloat32, "Input tensor must be float32 type."); + + ::kaldi::PitchExtractionOptions opts; + opts.samp_freq = static_cast<::kaldi::BaseFloat>(sample_frequency); + opts.frame_shift_ms = static_cast<::kaldi::BaseFloat>(frame_shift); + opts.frame_length_ms = static_cast<::kaldi::BaseFloat>(frame_length); + opts.min_f0 = static_cast<::kaldi::BaseFloat>(min_f0); + opts.max_f0 = static_cast<::kaldi::BaseFloat>(max_f0); + opts.soft_min_f0 = static_cast<::kaldi::BaseFloat>(soft_min_f0); + opts.penalty_factor = static_cast<::kaldi::BaseFloat>(penalty_factor); + opts.lowpass_cutoff = static_cast<::kaldi::BaseFloat>(lowpass_cutoff); + opts.resample_freq = static_cast<::kaldi::BaseFloat>(resample_frequency); + opts.delta_pitch = static_cast<::kaldi::BaseFloat>(delta_pitch); + opts.lowpass_filter_width = static_cast<::kaldi::int32>(lowpass_filter_width); + opts.upsample_filter_width = + static_cast<::kaldi::int32>(upsample_filter_width); + opts.max_frames_latency = static_cast<::kaldi::int32>(max_frames_latency); + opts.frames_per_chunk = static_cast<::kaldi::int32>(frames_per_chunk); + opts.simulate_first_pass_online = simulate_first_pass_online; + opts.recompute_frame = static_cast<::kaldi::int32>(recompute_frame); + opts.snip_edges = snip_edges; + + // Kaldi's float type expects value range of int16 expressed as float + torch::Tensor wave_ = denormalize(wave); + + auto batch_size = wave_.size(0); + std::vector results(batch_size); + at::parallel_for(0, batch_size, 1, [&](int64_t begin, int64_t end) { + for (auto i = begin; i < end; ++i) { + results[i] = compute_kaldi_pitch(wave_.index({i}), opts); + } + }); + return torch::stack(results, 0); +} + +TORCH_LIBRARY_FRAGMENT(torchaudio, m) { + m.def( + "torchaudio::kaldi_ComputeKaldiPitch", + &torchaudio::kaldi::ComputeKaldiPitch); +} + +} // namespace kaldi +} // namespace torchaudio diff --git a/torchaudio/csrc/lfilter.cpp b/torchaudio/csrc/lfilter.cpp new file mode 100644 index 0000000000..56540c33f6 --- /dev/null +++ b/torchaudio/csrc/lfilter.cpp @@ -0,0 +1,268 @@ +#include +#include + +namespace { + +template +void host_lfilter_core_loop( + const torch::Tensor& input_signal_windows, + const torch::Tensor& a_coeff_flipped, + torch::Tensor& padded_output_waveform) { + int64_t n_channel = input_signal_windows.size(0); + int64_t n_samples_input = input_signal_windows.size(1); + int64_t n_samples_output = padded_output_waveform.size(1); + int64_t n_order = a_coeff_flipped.size(0); + scalar_t* output_data = padded_output_waveform.data_ptr(); + const scalar_t* input_data = input_signal_windows.data_ptr(); + const scalar_t* a_coeff_flipped_data = a_coeff_flipped.data_ptr(); + for (int64_t i_channel = 0; i_channel < n_channel; i_channel++) { + for (int64_t i_sample = 0; i_sample < n_samples_input; i_sample++) { + int64_t offset_input = i_channel * n_samples_input; + int64_t offset_output = i_channel * n_samples_output; + scalar_t a0 = input_data[offset_input + i_sample]; + for (int64_t i_coeff = 0; i_coeff < n_order; i_coeff++) { + a0 -= output_data[offset_output + i_sample + i_coeff] * + a_coeff_flipped_data[i_coeff]; + } + output_data[offset_output + i_sample + n_order - 1] = a0; + } + } +} + +void cpu_lfilter_core_loop( + const torch::Tensor& input_signal_windows, + const torch::Tensor& a_coeff_flipped, + torch::Tensor& padded_output_waveform) { + TORCH_CHECK( + input_signal_windows.device().is_cpu() && + a_coeff_flipped.device().is_cpu() && + padded_output_waveform.device().is_cpu()); + + TORCH_CHECK( + input_signal_windows.is_contiguous() && a_coeff_flipped.is_contiguous() && + padded_output_waveform.is_contiguous()); + + TORCH_CHECK( + (input_signal_windows.dtype() == torch::kFloat32 || + input_signal_windows.dtype() == torch::kFloat64) && + (a_coeff_flipped.dtype() == torch::kFloat32 || + a_coeff_flipped.dtype() == torch::kFloat64) && + (padded_output_waveform.dtype() == torch::kFloat32 || + padded_output_waveform.dtype() == torch::kFloat64)); + + TORCH_CHECK(input_signal_windows.size(0) == padded_output_waveform.size(0)); + + TORCH_CHECK( + input_signal_windows.size(1) + a_coeff_flipped.size(0) - 1 == + padded_output_waveform.size(1)); + + AT_DISPATCH_FLOATING_TYPES( + input_signal_windows.scalar_type(), "lfilter_core_loop", [&] { + host_lfilter_core_loop( + input_signal_windows, a_coeff_flipped, padded_output_waveform); + }); +} + +void lfilter_core_generic_loop( + const torch::Tensor& input_signal_windows, + const torch::Tensor& a_coeff_flipped, + torch::Tensor& padded_output_waveform) { + int64_t n_samples_input = input_signal_windows.size(1); + int64_t n_order = a_coeff_flipped.size(0); + for (int64_t i_sample = 0; i_sample < n_samples_input; i_sample++) { + auto windowed_output_signal = padded_output_waveform.index( + {torch::indexing::Slice(), + torch::indexing::Slice(i_sample, i_sample + n_order)}); + auto o0 = input_signal_windows.index({torch::indexing::Slice(), i_sample}) + .addmv(windowed_output_signal, a_coeff_flipped, 1, -1); + padded_output_waveform.index_put_( + {torch::indexing::Slice(), i_sample + n_order - 1}, o0); + } +} + +std::tuple lfilter_core( + const torch::Tensor& waveform, + const torch::Tensor& a_coeffs, + const torch::Tensor& b_coeffs) { + TORCH_CHECK(waveform.device() == a_coeffs.device()); + TORCH_CHECK(b_coeffs.device() == a_coeffs.device()); + TORCH_CHECK(a_coeffs.size(0) == b_coeffs.size(0)); + + TORCH_INTERNAL_ASSERT(waveform.sizes().size() == 2); + + auto device = waveform.device(); + int64_t n_order = a_coeffs.size(0); + + TORCH_INTERNAL_ASSERT(n_order > 0); + + namespace F = torch::nn::functional; + + auto padded_waveform = F::pad(waveform, F::PadFuncOptions({n_order - 1, 0})); + auto padded_output_waveform = torch::zeros_like(padded_waveform); + + auto a_coeff_flipped = a_coeffs.flip(0).contiguous(); + auto b_coeff_flipped = b_coeffs.flip(0).contiguous(); + + auto input_signal_windows = + F::conv1d( + padded_waveform.unsqueeze(1), b_coeff_flipped.view({1, 1, n_order})) + .squeeze(1); + + input_signal_windows.div_(a_coeffs[0]); + a_coeff_flipped.div_(a_coeffs[0]); + + if (device.is_cpu()) { + cpu_lfilter_core_loop( + input_signal_windows, a_coeff_flipped, padded_output_waveform); + } else { + lfilter_core_generic_loop( + input_signal_windows, a_coeff_flipped, padded_output_waveform); + } + + auto output = padded_output_waveform.index( + {torch::indexing::Slice(), + torch::indexing::Slice(n_order - 1, torch::indexing::None)}); + + return {output, input_signal_windows}; +} + +torch::Tensor lfilter_simple( + const torch::Tensor& waveform, + const torch::Tensor& a_coeffs, + const torch::Tensor& b_coeffs) { + return std::get<0>(lfilter_core(waveform, a_coeffs, b_coeffs)); +} + +class DifferentiableLfilter + : public torch::autograd::Function { + public: + static torch::Tensor forward( + torch::autograd::AutogradContext* ctx, + const torch::Tensor& waveform, + const torch::Tensor& a_coeffs, + const torch::Tensor& b_coeffs) { + at::AutoNonVariableTypeMode g; + auto result = lfilter_core(waveform, a_coeffs, b_coeffs); + ctx->save_for_backward( + {waveform, + a_coeffs, + b_coeffs, + std::get<0>(result), + std::get<1>(result)}); + return std::get<0>(result); + } + + static torch::autograd::tensor_list backward( + torch::autograd::AutogradContext* ctx, + torch::autograd::tensor_list grad_outputs) { + auto saved = ctx->get_saved_variables(); + auto waveform = saved[0]; + auto a_coeffs = saved[1]; + auto b_coeffs = saved[2]; + auto y = saved[3]; + auto xh = saved[4]; + + auto device = waveform.device(); + auto dtype = waveform.dtype(); + int64_t n_channel = waveform.size(0); + int64_t n_sample = waveform.size(1); + int64_t n_order = a_coeffs.size(0); + int64_t n_sample_padded = n_sample + n_order - 1; + + auto a_coeff_flipped = a_coeffs.flip(0).contiguous(); + auto b_coeff_flipped = b_coeffs.flip(0).contiguous(); + b_coeff_flipped.div_(a_coeffs[0]); + a_coeff_flipped.div_(a_coeffs[0]); + + auto dx = torch::Tensor(); + auto da = torch::Tensor(); + auto db = torch::Tensor(); + auto dy = grad_outputs[0]; + + at::AutoNonVariableTypeMode g; + namespace F = torch::nn::functional; + auto options = torch::TensorOptions().dtype(dtype).device(device); + + if (a_coeffs.requires_grad()) { + auto dyda = torch::zeros({n_channel, n_sample_padded}, options); + if (device.is_cpu()) { + cpu_lfilter_core_loop(-y, a_coeff_flipped, dyda); + } else { + lfilter_core_generic_loop(-y, a_coeff_flipped, dyda); + } + + da = F::conv1d( + dyda.unsqueeze(0), + dy.unsqueeze(1), + F::Conv1dFuncOptions().groups(n_channel)) + .sum(1) + .squeeze(0) + .flip(0); + da.div_(a_coeffs[0]); + } + + if (b_coeffs.requires_grad() || waveform.requires_grad()) { + auto dxh = torch::zeros({n_channel, n_sample_padded}, options); + if (device.is_cpu()) { + cpu_lfilter_core_loop(dy.flip(1), a_coeff_flipped, dxh); + } else { + lfilter_core_generic_loop(dy.flip(1), a_coeff_flipped, dxh); + } + + dxh = dxh.index( + {torch::indexing::Slice(), + torch::indexing::Slice(n_order - 1, torch::indexing::None)}) + .flip(1); + + if (waveform.requires_grad()) { + dx = F::conv1d( + F::pad(dxh.unsqueeze(1), F::PadFuncOptions({0, n_order - 1})), + b_coeffs.view({1, 1, n_order})) + .squeeze(1); + dx.div_(a_coeffs[0]); + } + if (b_coeffs.requires_grad()) { + db = + F::conv1d( + F::pad( + waveform.unsqueeze(0), F::PadFuncOptions({n_order - 1, 0})), + dxh.unsqueeze(1), + F::Conv1dFuncOptions().groups(n_channel)) + .sum(1) + .squeeze(0) + .flip(0); + db.div_(a_coeffs[0]); + } + } + + return {dx, da, db}; + } +}; + +torch::Tensor lfilter_autograd( + const torch::Tensor& waveform, + const torch::Tensor& a_coeffs, + const torch::Tensor& b_coeffs) { + return DifferentiableLfilter::apply(waveform, a_coeffs, b_coeffs); +} + +} // namespace + +// Note: We want to avoid using "catch-all" kernel. +// The following registration should be replaced with CPU specific registration. +TORCH_LIBRARY_FRAGMENT(torchaudio, m) { + m.def("torchaudio::_lfilter_core_loop", &cpu_lfilter_core_loop); +} + +TORCH_LIBRARY(torchaudio, m) { + m.def( + "torchaudio::_lfilter(Tensor waveform, Tensor a_coeffs, Tensor b_coeffs) -> Tensor"); +} + +TORCH_LIBRARY_IMPL(torchaudio, DefaultBackend, m) { + m.impl("torchaudio::_lfilter", lfilter_simple); +} + +TORCH_LIBRARY_IMPL(torchaudio, Autograd, m) { + m.impl("torchaudio::_lfilter", lfilter_autograd); +} diff --git a/torchaudio/csrc/overdrive.cpp b/torchaudio/csrc/overdrive.cpp new file mode 100644 index 0000000000..4954271e41 --- /dev/null +++ b/torchaudio/csrc/overdrive.cpp @@ -0,0 +1,52 @@ +#include +#include + +namespace { + +template +void overdrive_cpu_kernel( + at::TensorAccessor waveform_accessor, + at::TensorAccessor temp_accessor, + at::TensorAccessor last_in_accessor, + at::TensorAccessor last_out_accessor, + at::TensorAccessor output_waveform_accessor) { + int64_t n_frames = waveform_accessor.size(1); + int64_t n_channels = waveform_accessor.size(0); + + at::parallel_for(0, n_channels, 1, [&](int64_t begin, int64_t end) { + for (int64_t i_channel = begin; i_channel < end; ++i_channel) { + for (int64_t i_frame = 0; i_frame < n_frames; ++i_frame) { + last_out_accessor[i_channel] = temp_accessor[i_channel][i_frame] - + last_in_accessor[i_channel] + 0.995 * last_out_accessor[i_channel]; + last_in_accessor[i_channel] = temp_accessor[i_channel][i_frame]; + output_waveform_accessor[i_channel][i_frame] = + waveform_accessor[i_channel][i_frame] * 0.5 + + last_out_accessor[i_channel] * 0.75; + } + } + }); +} + +void overdrive_core_loop_cpu( + at::Tensor& waveform, + at::Tensor& temp, + at::Tensor& last_in, + at::Tensor& last_out, + at::Tensor& output_waveform) { + AT_DISPATCH_FLOATING_TYPES(waveform.scalar_type(), "overdrive_cpu", ([&] { + overdrive_cpu_kernel( + waveform.accessor(), + temp.accessor(), + last_in.accessor(), + last_out.accessor(), + output_waveform.accessor()); + })); +} + +} // namespace + +// Note: We want to avoid using "catch-all" kernel. +// The following registration should be replaced with CPU specific registration. +TORCH_LIBRARY_FRAGMENT(torchaudio, m) { + m.def("torchaudio::_overdrive_core_loop", &overdrive_core_loop_cpu); +} diff --git a/torchaudio/csrc/pybind.cpp b/torchaudio/csrc/pybind.cpp index 373b9d0d96..81ccf459b1 100644 --- a/torchaudio/csrc/pybind.cpp +++ b/torchaudio/csrc/pybind.cpp @@ -1,106 +1,12 @@ #include + +#ifdef INCLUDE_SOX #include #include -#include +#endif PYBIND11_MODULE(_torchaudio, m) { - py::class_(m, "sox_signalinfo_t") - .def(py::init<>()) - .def( - "__repr__", - [](const sox_signalinfo_t& self) { - std::stringstream ss; - ss << "sox_signalinfo_t {\n" - << " rate-> " << self.rate << "\n" - << " channels-> " << self.channels << "\n" - << " precision-> " << self.precision << "\n" - << " length-> " << self.length << "\n" - << " mult-> " << self.mult << "\n" - << "}\n"; - return ss.str(); - }) - .def_readwrite("rate", &sox_signalinfo_t::rate) - .def_readwrite("channels", &sox_signalinfo_t::channels) - .def_readwrite("precision", &sox_signalinfo_t::precision) - .def_readwrite("length", &sox_signalinfo_t::length) - .def_readwrite("mult", &sox_signalinfo_t::mult); - py::class_(m, "sox_encodinginfo_t") - .def(py::init<>()) - .def( - "__repr__", - [](const sox_encodinginfo_t& self) { - std::stringstream ss; - ss << "sox_encodinginfo_t {\n" - << " encoding-> " << self.encoding << "\n" - << " bits_per_sample-> " << self.bits_per_sample << "\n" - << " compression-> " << self.compression << "\n" - << " reverse_bytes-> " << self.reverse_bytes << "\n" - << " reverse_nibbles-> " << self.reverse_nibbles << "\n" - << " reverse_bits-> " << self.reverse_bits << "\n" - << " opposite_endian-> " << self.opposite_endian << "\n" - << "}\n"; - return ss.str(); - }) - .def_readwrite("encoding", &sox_encodinginfo_t::encoding) - .def_readwrite("bits_per_sample", &sox_encodinginfo_t::bits_per_sample) - .def_readwrite("compression", &sox_encodinginfo_t::compression) - .def_readwrite("reverse_bytes", &sox_encodinginfo_t::reverse_bytes) - .def_readwrite("reverse_nibbles", &sox_encodinginfo_t::reverse_nibbles) - .def_readwrite("reverse_bits", &sox_encodinginfo_t::reverse_bits) - .def_readwrite("opposite_endian", &sox_encodinginfo_t::opposite_endian); - py::enum_(m, "sox_encoding_t") - .value("SOX_ENCODING_UNKNOWN", sox_encoding_t::SOX_ENCODING_UNKNOWN) - .value("SOX_ENCODING_SIGN2", sox_encoding_t::SOX_ENCODING_SIGN2) - .value("SOX_ENCODING_UNSIGNED", sox_encoding_t::SOX_ENCODING_UNSIGNED) - .value("SOX_ENCODING_FLOAT", sox_encoding_t::SOX_ENCODING_FLOAT) - .value("SOX_ENCODING_FLOAT_TEXT", sox_encoding_t::SOX_ENCODING_FLOAT_TEXT) - .value("SOX_ENCODING_FLAC", sox_encoding_t::SOX_ENCODING_FLAC) - .value("SOX_ENCODING_HCOM", sox_encoding_t::SOX_ENCODING_HCOM) - .value("SOX_ENCODING_WAVPACK", sox_encoding_t::SOX_ENCODING_WAVPACK) - .value("SOX_ENCODING_WAVPACKF", sox_encoding_t::SOX_ENCODING_WAVPACKF) - .value("SOX_ENCODING_ULAW", sox_encoding_t::SOX_ENCODING_ULAW) - .value("SOX_ENCODING_ALAW", sox_encoding_t::SOX_ENCODING_ALAW) - .value("SOX_ENCODING_G721", sox_encoding_t::SOX_ENCODING_G721) - .value("SOX_ENCODING_G723", sox_encoding_t::SOX_ENCODING_G723) - .value("SOX_ENCODING_CL_ADPCM", sox_encoding_t::SOX_ENCODING_CL_ADPCM) - .value("SOX_ENCODING_CL_ADPCM16", sox_encoding_t::SOX_ENCODING_CL_ADPCM16) - .value("SOX_ENCODING_MS_ADPCM", sox_encoding_t::SOX_ENCODING_MS_ADPCM) - .value("SOX_ENCODING_IMA_ADPCM", sox_encoding_t::SOX_ENCODING_IMA_ADPCM) - .value("SOX_ENCODING_OKI_ADPCM", sox_encoding_t::SOX_ENCODING_OKI_ADPCM) - .value("SOX_ENCODING_DPCM", sox_encoding_t::SOX_ENCODING_DPCM) - .value("SOX_ENCODING_DWVW", sox_encoding_t::SOX_ENCODING_DWVW) - .value("SOX_ENCODING_DWVWN", sox_encoding_t::SOX_ENCODING_DWVWN) - .value("SOX_ENCODING_GSM", sox_encoding_t::SOX_ENCODING_GSM) - .value("SOX_ENCODING_MP3", sox_encoding_t::SOX_ENCODING_MP3) - .value("SOX_ENCODING_VORBIS", sox_encoding_t::SOX_ENCODING_VORBIS) - .value("SOX_ENCODING_AMR_WB", sox_encoding_t::SOX_ENCODING_AMR_WB) - .value("SOX_ENCODING_AMR_NB", sox_encoding_t::SOX_ENCODING_AMR_NB) - .value("SOX_ENCODING_LPC10", sox_encoding_t::SOX_ENCODING_LPC10) - //.value("SOX_ENCODING_OPUS", sox_encoding_t::SOX_ENCODING_OPUS) // - // creates a compile error - .value("SOX_ENCODINGS", sox_encoding_t::SOX_ENCODINGS) - .export_values(); - py::enum_(m, "sox_option_t") - .value("sox_option_no", sox_option_t::sox_option_no) - .value("sox_option_yes", sox_option_t::sox_option_yes) - .value("sox_option_default", sox_option_t::sox_option_default) - .export_values(); - py::enum_(m, "sox_bool") - .value("sox_false", sox_bool::sox_false) - .value("sox_true", sox_bool::sox_true) - .export_values(); - m.def( - "read_audio_file", - &torch::audio::read_audio_file, - "Reads an audio file into a tensor"); - m.def( - "write_audio_file", - &torch::audio::write_audio_file, - "Writes data from a tensor into an audio file"); - m.def( - "get_info", - &torch::audio::get_info, - "Gets information about an audio file"); +#ifdef INCLUDE_SOX m.def( "get_info_fileobj", &torchaudio::sox_io::get_info_fileobj, @@ -117,4 +23,5 @@ PYBIND11_MODULE(_torchaudio, m) { "apply_effects_fileobj", &torchaudio::sox_effects::apply_effects_fileobj, "Decode audio data from file-like obj and apply effects."); +#endif } diff --git a/torchaudio/csrc/sox/effects.cpp b/torchaudio/csrc/sox/effects.cpp index d2d2a0f5ad..8ffc6327ac 100644 --- a/torchaudio/csrc/sox/effects.cpp +++ b/torchaudio/csrc/sox/effects.cpp @@ -161,9 +161,9 @@ std::tuple apply_effects_file( std::tuple apply_effects_fileobj( py::object fileobj, std::vector> effects, - c10::optional& normalize, - c10::optional& channels_first, - c10::optional& format) { + c10::optional normalize, + c10::optional channels_first, + c10::optional format) { // Prepare the buffer used throughout the lifecycle of SoxEffectChain. // // For certain format (such as FLAC), libsox keeps reading the content at @@ -204,7 +204,7 @@ std::tuple apply_effects_fileobj( /*filetype=*/format.has_value() ? format.value().c_str() : nullptr)); // In case of streamed data, length can be 0 - validate_input_file(sf, /*check_length=*/false); + validate_input_file(sf); // Prepare output buffer std::vector out_buffer; diff --git a/torchaudio/csrc/sox/effects.h b/torchaudio/csrc/sox/effects.h index efec06971c..fef8847214 100644 --- a/torchaudio/csrc/sox/effects.h +++ b/torchaudio/csrc/sox/effects.h @@ -33,9 +33,9 @@ std::tuple apply_effects_file( std::tuple apply_effects_fileobj( py::object fileobj, std::vector> effects, - c10::optional& normalize, - c10::optional& channels_first, - c10::optional& format); + c10::optional normalize, + c10::optional channels_first, + c10::optional format); #endif // TORCH_API_INCLUDE_EXTENSION_H diff --git a/torchaudio/csrc/sox/effects_chain.cpp b/torchaudio/csrc/sox/effects_chain.cpp index b98010f67b..3028220c3f 100644 --- a/torchaudio/csrc/sox/effects_chain.cpp +++ b/torchaudio/csrc/sox/effects_chain.cpp @@ -68,21 +68,48 @@ int tensor_input_drain(sox_effect_t* effp, sox_sample_t* obuf, size_t* osamp) { // Ensure that it's a multiple of the number of channels *osamp -= *osamp % num_channels; - // Slice the input Tensor and unnormalize the values - const auto tensor_ = [&]() { + // Slice the input Tensor + auto chunk = [&]() { auto i_frame = index / num_channels; auto num_frames = *osamp / num_channels; auto t = (priv->channels_first) ? tensor.index({Slice(), Slice(i_frame, i_frame + num_frames)}).t() : tensor.index({Slice(i_frame, i_frame + num_frames), Slice()}); - return unnormalize_wav(t.reshape({-1})).contiguous(); + return t.reshape({-1}); }(); - priv->index += *osamp; - - // Write data to SoxEffectsChain buffer. - auto ptr = tensor_.data_ptr(); - std::copy(ptr, ptr + *osamp, obuf); + // Convert to sox_sample_t (int32_t) + switch (chunk.dtype().toScalarType()) { + case c10::ScalarType::Float: { + // Need to convert to 64-bit precision so that + // values around INT32_MIN/MAX are handled correctly. + chunk = chunk.to(c10::ScalarType::Double); + chunk *= 2147483648.; + chunk.clamp_(INT32_MIN, INT32_MAX); + chunk = chunk.to(c10::ScalarType::Int); + break; + } + case c10::ScalarType::Int: { + break; + } + case c10::ScalarType::Short: { + chunk = chunk.to(c10::ScalarType::Int); + chunk *= 65536; + break; + } + case c10::ScalarType::Byte: { + chunk = chunk.to(c10::ScalarType::Int); + chunk -= 128; + chunk *= 16777216; + break; + } + default: + throw std::runtime_error("Unexpected dtype."); + } + // Write to buffer + chunk = chunk.contiguous(); + memcpy(obuf, chunk.data_ptr(), *osamp * 4); + priv->index += *osamp; return (priv->index == num_samples) ? SOX_EOF : SOX_SUCCESS; } @@ -430,7 +457,7 @@ int fileobj_output_flow( fflush(fp); // Copy the encoded chunk to python object. - fileobj->attr("write")(py::bytes(*buffer, *buffer_size)); + fileobj->attr("write")(py::bytes(*buffer, ftell(fp))); // Reset FILE* sf->tell_off = 0; diff --git a/torchaudio/csrc/sox/io.cpp b/torchaudio/csrc/sox/io.cpp index 90532dd3ad..8e2ebce4e2 100644 --- a/torchaudio/csrc/sox/io.cpp +++ b/torchaudio/csrc/sox/io.cpp @@ -1,7 +1,7 @@ -#include #include #include #include +#include #include using namespace torch::indexing; @@ -10,41 +10,6 @@ using namespace torchaudio::sox_utils; namespace torchaudio { namespace sox_io { -namespace { - -std::string get_encoding(sox_encoding_t encoding) { - switch (encoding) { - case SOX_ENCODING_UNKNOWN: - return "UNKNOWN"; - case SOX_ENCODING_SIGN2: - return "PCM_S"; - case SOX_ENCODING_UNSIGNED: - return "PCM_U"; - case SOX_ENCODING_FLOAT: - return "PCM_F"; - case SOX_ENCODING_FLAC: - return "FLAC"; - case SOX_ENCODING_ULAW: - return "ULAW"; - case SOX_ENCODING_ALAW: - return "ALAW"; - case SOX_ENCODING_MP3: - return "MP3"; - case SOX_ENCODING_VORBIS: - return "VORBIS"; - case SOX_ENCODING_AMR_WB: - return "AMR_WB"; - case SOX_ENCODING_AMR_NB: - return "AMR_NB"; - case SOX_ENCODING_OPUS: - return "OPUS"; - default: - return "UNKNOWN"; - } -} - -} // namespace - std::tuple get_info_file( const std::string& path, const c10::optional& format) { @@ -118,33 +83,36 @@ void save_audio_file( bool channels_first, c10::optional compression, c10::optional format, - c10::optional dtype) { + c10::optional encoding, + c10::optional bits_per_sample) { validate_input_tensor(tensor); - if (tensor.dtype() != torch::kFloat32 && dtype.has_value()) { - throw std::runtime_error( - "dtype conversion only supported for float32 tensors"); - } - const auto tgt_dtype = - (tensor.dtype() == torch::kFloat32 && dtype.has_value()) - ? get_dtype_from_str(dtype.value()) - : tensor.dtype(); - const auto filetype = [&]() { if (format.has_value()) return format.value(); return get_filetype(path); }(); + if (filetype == "amr-nb") { const auto num_channels = tensor.size(channels_first ? 0 : 1); TORCH_CHECK( num_channels == 1, "amr-nb format only supports single channel audio."); - tensor = (unnormalize_wav(tensor) / 65536).to(torch::kInt16); + } else if (filetype == "htk") { + const auto num_channels = tensor.size(channels_first ? 0 : 1); + TORCH_CHECK( + num_channels == 1, "htk format only supports single channel audio."); + } else if (filetype == "gsm") { + const auto num_channels = tensor.size(channels_first ? 0 : 1); + TORCH_CHECK( + num_channels == 1, "gsm format only supports single channel audio."); + TORCH_CHECK( + sample_rate == 8000, + "gsm format only supports a sampling rate of 8kHz."); } const auto signal_info = get_signalinfo(&tensor, sample_rate, filetype, channels_first); - const auto encoding_info = - get_encodinginfo_for_save(filetype, tgt_dtype, compression); + const auto encoding_info = get_encodinginfo_for_save( + filetype, tensor.dtype(), compression, encoding, bits_per_sample); SoxFormat sf(sox_open_write( path.c_str(), @@ -170,7 +138,7 @@ void save_audio_file( std::tuple get_info_fileobj( py::object fileobj, - c10::optional& format) { + c10::optional format) { // Prepare in-memory file object // When libsox opens a file, it also reads the header. // When opening a file there are two functions that might touch FILE* (and the @@ -209,7 +177,7 @@ std::tuple get_info_fileobj( /*filetype=*/format.has_value() ? format.value().c_str() : nullptr)); // In case of streamed data, length can be 0 - validate_input_file(sf, /*check_length=*/false); + validate_input_file(sf); return std::make_tuple( static_cast(sf->signal.rate), @@ -221,11 +189,11 @@ std::tuple get_info_fileobj( std::tuple load_audio_fileobj( py::object fileobj, - c10::optional& frame_offset, - c10::optional& num_frames, - c10::optional& normalize, - c10::optional& channels_first, - c10::optional& format) { + c10::optional frame_offset, + c10::optional num_frames, + c10::optional normalize, + c10::optional channels_first, + c10::optional format) { auto effects = get_effects(frame_offset, num_frames); return torchaudio::sox_effects::apply_effects_fileobj( fileobj, effects, normalize, channels_first, format); @@ -259,18 +227,16 @@ void save_audio_fileobj( int64_t sample_rate, bool channels_first, c10::optional compression, - std::string filetype, - c10::optional dtype) { + c10::optional format, + c10::optional encoding, + c10::optional bits_per_sample) { validate_input_tensor(tensor); - if (tensor.dtype() != torch::kFloat32 && dtype.has_value()) { + if (!format.has_value()) { throw std::runtime_error( - "dtype conversion only supported for float32 tensors"); + "`format` is required when saving to file object."); } - const auto tgt_dtype = - (tensor.dtype() == torch::kFloat32 && dtype.has_value()) - ? get_dtype_from_str(dtype.value()) - : tensor.dtype(); + const auto filetype = format.value(); if (filetype == "amr-nb") { const auto num_channels = tensor.size(channels_first ? 0 : 1); @@ -278,12 +244,27 @@ void save_audio_fileobj( throw std::runtime_error( "amr-nb format only supports single channel audio."); } - tensor = (unnormalize_wav(tensor) / 65536).to(torch::kInt16); + } else if (filetype == "htk") { + const auto num_channels = tensor.size(channels_first ? 0 : 1); + if (num_channels != 1) { + throw std::runtime_error( + "htk format only supports single channel audio."); + } + } else if (filetype == "gsm") { + const auto num_channels = tensor.size(channels_first ? 0 : 1); + if (num_channels != 1) { + throw std::runtime_error( + "gsm format only supports single channel audio."); + } + if (sample_rate != 8000) { + throw std::runtime_error( + "gsm format only supports a sampling rate of 8kHz."); + } } const auto signal_info = get_signalinfo(&tensor, sample_rate, filetype, channels_first); - const auto encoding_info = - get_encodinginfo_for_save(filetype, tgt_dtype, compression); + const auto encoding_info = get_encodinginfo_for_save( + filetype, tensor.dtype(), compression, encoding, bits_per_sample); AutoReleaseBuffer buffer; diff --git a/torchaudio/csrc/sox/io.h b/torchaudio/csrc/sox/io.h index cd203e9c5c..8c18a64dd1 100644 --- a/torchaudio/csrc/sox/io.h +++ b/torchaudio/csrc/sox/io.h @@ -30,21 +30,22 @@ void save_audio_file( bool channels_first, c10::optional compression, c10::optional format, - c10::optional dtype); + c10::optional encoding, + c10::optional bits_per_sample); #ifdef TORCH_API_INCLUDE_EXTENSION_H std::tuple get_info_fileobj( py::object fileobj, - c10::optional& format); + c10::optional format); std::tuple load_audio_fileobj( py::object fileobj, - c10::optional& frame_offset, - c10::optional& num_frames, - c10::optional& normalize, - c10::optional& channels_first, - c10::optional& format); + c10::optional frame_offset, + c10::optional num_frames, + c10::optional normalize, + c10::optional channels_first, + c10::optional format); void save_audio_fileobj( py::object fileobj, @@ -52,8 +53,9 @@ void save_audio_fileobj( int64_t sample_rate, bool channels_first, c10::optional compression, - std::string filetype, - c10::optional dtype); + c10::optional format, + c10::optional encoding, + c10::optional bits_per_sample); #endif // TORCH_API_INCLUDE_EXTENSION_H diff --git a/torchaudio/csrc/sox/legacy.cpp b/torchaudio/csrc/sox/legacy.cpp deleted file mode 100644 index 858ad15149..0000000000 --- a/torchaudio/csrc/sox/legacy.cpp +++ /dev/null @@ -1,170 +0,0 @@ -#include - -namespace torch { -namespace audio { -namespace { -/// Helper struct to safely close the sox_format_t descriptor. -struct SoxDescriptor { - explicit SoxDescriptor(sox_format_t* fd) noexcept : fd_(fd) {} - SoxDescriptor(const SoxDescriptor& other) = delete; - SoxDescriptor(SoxDescriptor&& other) = delete; - SoxDescriptor& operator=(const SoxDescriptor& other) = delete; - SoxDescriptor& operator=(SoxDescriptor&& other) = delete; - ~SoxDescriptor() { - if (fd_ != nullptr) { - sox_close(fd_); - } - } - sox_format_t* operator->() noexcept { - return fd_; - } - sox_format_t* get() noexcept { - return fd_; - } - - private: - sox_format_t* fd_; -}; - -int64_t write_audio(SoxDescriptor& fd, at::Tensor tensor) { - std::vector buffer(tensor.numel()); - - AT_DISPATCH_ALL_TYPES(tensor.scalar_type(), "write_audio_buffer", [&] { - auto* data = tensor.data_ptr(); - std::copy(data, data + tensor.numel(), buffer.begin()); - }); - - const auto samples_written = - sox_write(fd.get(), buffer.data(), buffer.size()); - - return samples_written; -} - -void read_audio(SoxDescriptor& fd, at::Tensor output, int64_t buffer_length) { - std::vector buffer(buffer_length); - - int number_of_channels = fd->signal.channels; - const int64_t samples_read = sox_read(fd.get(), buffer.data(), buffer_length); - if (samples_read == 0) { - throw std::runtime_error( - "Error reading audio file: empty file or read failed in sox_read"); - } - - output.resize_({samples_read / number_of_channels, number_of_channels}); - output = output.contiguous(); - - AT_DISPATCH_ALL_TYPES(output.scalar_type(), "read_audio_buffer", [&] { - auto* data = output.data_ptr(); - std::copy(buffer.begin(), buffer.begin() + samples_read, data); - }); -} -} // namespace - -std::tuple get_info( - const std::string& file_name) { - SoxDescriptor fd(sox_open_read( - file_name.c_str(), - /*signal=*/nullptr, - /*encoding=*/nullptr, - /*filetype=*/nullptr)); - if (fd.get() == nullptr) { - throw std::runtime_error("Error opening audio file"); - } - return std::make_tuple(fd->signal, fd->encoding); -} - -int read_audio_file( - const std::string& file_name, - at::Tensor output, - bool ch_first, - int64_t nframes, - int64_t offset, - sox_signalinfo_t* si, - sox_encodinginfo_t* ei, - const char* ft) { - SoxDescriptor fd(sox_open_read(file_name.c_str(), si, ei, ft)); - if (fd.get() == nullptr) { - throw std::runtime_error("Error opening audio file"); - } - - // signal info - - const int number_of_channels = fd->signal.channels; - const int sample_rate = fd->signal.rate; - const int64_t total_length = fd->signal.length; - - // multiply offset and number of frames by number of channels - offset *= number_of_channels; - nframes *= number_of_channels; - - if (total_length == 0) { - throw std::runtime_error("Error reading audio file: unknown length"); - } - if (offset > total_length) { - throw std::runtime_error("Offset past EOF"); - } - - // calculate buffer length - int64_t buffer_length = total_length; - if (offset > 0) { - buffer_length -= offset; - } - if (nframes > 0 && buffer_length > nframes) { - buffer_length = nframes; - } - - // seek to offset point before reading data - if (sox_seek(fd.get(), offset, 0) == SOX_EOF) { - throw std::runtime_error( - "sox_seek reached EOF, try reducing offset or num_samples"); - } - - // read data and fill output tensor - read_audio(fd, output, buffer_length); - - // L x C -> C x L, if desired - if (ch_first) { - output.transpose_(1, 0); - } - - return sample_rate; -} - -void write_audio_file( - const std::string& file_name, - const at::Tensor& tensor, - sox_signalinfo_t* si, - sox_encodinginfo_t* ei, - const char* file_type) { - if (!tensor.is_contiguous()) { - throw std::runtime_error( - "Error writing audio file: input tensor must be contiguous"); - } - -#if SOX_LIB_VERSION_CODE >= 918272 // >= 14.3.0 - si->mult = nullptr; -#endif - - SoxDescriptor fd(sox_open_write( - file_name.c_str(), - si, - ei, - file_type, - /*oob=*/nullptr, - /*overwrite=*/nullptr)); - - if (fd.get() == nullptr) { - throw std::runtime_error( - "Error writing audio file: could not open file for writing"); - } - - const auto samples_written = write_audio(fd, tensor); - - if (samples_written != tensor.numel()) { - throw std::runtime_error( - "Error writing audio file: could not write entire buffer"); - } -} - -} // namespace audio -} // namespace torch diff --git a/torchaudio/csrc/sox/legacy.h b/torchaudio/csrc/sox/legacy.h deleted file mode 100644 index 5869695bfe..0000000000 --- a/torchaudio/csrc/sox/legacy.h +++ /dev/null @@ -1,40 +0,0 @@ -#include -#include - -namespace torch { -namespace audio { - -/// Reads an audio file from the given `path` into the `output` `Tensor` and -/// returns the sample rate of the audio file. -/// Throws `std::runtime_error` if the audio file could not be opened, or an -/// error occurred during reading of the audio data. -int read_audio_file( - const std::string& file_name, - at::Tensor output, - bool ch_first, - int64_t nframes, - int64_t offset, - sox_signalinfo_t* si, - sox_encodinginfo_t* ei, - const char* ft); - -/// Writes the data of a `Tensor` into an audio file at the given `path`, with -/// a certain extension (e.g. `wav`or `mp3`) and sample rate. -/// Throws `std::runtime_error` when the audio file could not be opened for -/// writing, or an error occurred during writing of the audio data. -void write_audio_file( - const std::string& file_name, - const at::Tensor& tensor, - sox_signalinfo_t* si, - sox_encodinginfo_t* ei, - const char* file_type); - -/// Reads an audio file from the given `path` and returns a tuple of -/// sox_signalinfo_t and sox_encodinginfo_t, which contain information about -/// the audio file such as sample rate, length, bit precision, encoding and -/// more. Throws `std::runtime_error` if the audio file could not be opened, or -/// an error occurred during reading of the audio data. -std::tuple get_info( - const std::string& file_name); -} // namespace audio -} // namespace torch diff --git a/torchaudio/csrc/sox/types.cpp b/torchaudio/csrc/sox/types.cpp new file mode 100644 index 0000000000..b4bbf710f6 --- /dev/null +++ b/torchaudio/csrc/sox/types.cpp @@ -0,0 +1,139 @@ +#include + +namespace torchaudio { +namespace sox_utils { + +Format get_format_from_string(const std::string& format) { + if (format == "wav") + return Format::WAV; + if (format == "mp3") + return Format::MP3; + if (format == "flac") + return Format::FLAC; + if (format == "ogg" || format == "vorbis") + return Format::VORBIS; + if (format == "amr-nb") + return Format::AMR_NB; + if (format == "amr-wb") + return Format::AMR_WB; + if (format == "amb") + return Format::AMB; + if (format == "sph") + return Format::SPHERE; + if (format == "htk") + return Format::HTK; + if (format == "gsm") + return Format::GSM; + std::ostringstream stream; + stream << "Internal Error: unexpected format value: " << format; + throw std::runtime_error(stream.str()); +} + +std::string to_string(Encoding v) { + switch (v) { + case Encoding::UNKNOWN: + return "UNKNOWN"; + case Encoding::PCM_SIGNED: + return "PCM_S"; + case Encoding::PCM_UNSIGNED: + return "PCM_U"; + case Encoding::PCM_FLOAT: + return "PCM_F"; + case Encoding::FLAC: + return "FLAC"; + case Encoding::ULAW: + return "ULAW"; + case Encoding::ALAW: + return "ALAW"; + case Encoding::MP3: + return "MP3"; + case Encoding::VORBIS: + return "VORBIS"; + case Encoding::AMR_WB: + return "AMR_WB"; + case Encoding::AMR_NB: + return "AMR_NB"; + case Encoding::OPUS: + return "OPUS"; + default: + throw std::runtime_error("Internal Error: unexpected encoding."); + } +} + +Encoding get_encoding_from_option(const c10::optional encoding) { + if (!encoding.has_value()) + return Encoding::NOT_PROVIDED; + std::string v = encoding.value(); + if (v == "PCM_S") + return Encoding::PCM_SIGNED; + if (v == "PCM_U") + return Encoding::PCM_UNSIGNED; + if (v == "PCM_F") + return Encoding::PCM_FLOAT; + if (v == "ULAW") + return Encoding::ULAW; + if (v == "ALAW") + return Encoding::ALAW; + std::ostringstream stream; + stream << "Internal Error: unexpected encoding value: " << v; + throw std::runtime_error(stream.str()); +} + +BitDepth get_bit_depth_from_option(const c10::optional bit_depth) { + if (!bit_depth.has_value()) + return BitDepth::NOT_PROVIDED; + int64_t v = bit_depth.value(); + switch (v) { + case 8: + return BitDepth::B8; + case 16: + return BitDepth::B16; + case 24: + return BitDepth::B24; + case 32: + return BitDepth::B32; + case 64: + return BitDepth::B64; + default: { + std::ostringstream s; + s << "Internal Error: unexpected bit depth value: " << v; + throw std::runtime_error(s.str()); + } + } +} + +std::string get_encoding(sox_encoding_t encoding) { + switch (encoding) { + case SOX_ENCODING_UNKNOWN: + return "UNKNOWN"; + case SOX_ENCODING_SIGN2: + return "PCM_S"; + case SOX_ENCODING_UNSIGNED: + return "PCM_U"; + case SOX_ENCODING_FLOAT: + return "PCM_F"; + case SOX_ENCODING_FLAC: + return "FLAC"; + case SOX_ENCODING_ULAW: + return "ULAW"; + case SOX_ENCODING_ALAW: + return "ALAW"; + case SOX_ENCODING_MP3: + return "MP3"; + case SOX_ENCODING_VORBIS: + return "VORBIS"; + case SOX_ENCODING_AMR_WB: + return "AMR_WB"; + case SOX_ENCODING_AMR_NB: + return "AMR_NB"; + case SOX_ENCODING_OPUS: + return "OPUS"; + case SOX_ENCODING_GSM: + return "GSM"; + default: + return "UNKNOWN"; + } +} + +} // namespace sox_utils +} // namespace torchaudio diff --git a/torchaudio/csrc/sox/types.h b/torchaudio/csrc/sox/types.h new file mode 100644 index 0000000000..afd84791a6 --- /dev/null +++ b/torchaudio/csrc/sox/types.h @@ -0,0 +1,60 @@ +#ifndef TORCHAUDIO_SOX_TYPES_H +#define TORCHAUDIO_SOX_TYPES_H + +#include +#include + +namespace torchaudio { +namespace sox_utils { + +enum class Format { + WAV, + MP3, + FLAC, + VORBIS, + AMR_NB, + AMR_WB, + AMB, + SPHERE, + GSM, + HTK, +}; + +Format get_format_from_string(const std::string& format); + +enum class Encoding { + NOT_PROVIDED, + UNKNOWN, + PCM_SIGNED, + PCM_UNSIGNED, + PCM_FLOAT, + FLAC, + ULAW, + ALAW, + MP3, + VORBIS, + AMR_WB, + AMR_NB, + OPUS, +}; + +std::string to_string(Encoding v); +Encoding get_encoding_from_option(const c10::optional encoding); + +enum class BitDepth : unsigned { + NOT_PROVIDED = 0, + B8 = 8, + B16 = 16, + B24 = 24, + B32 = 32, + B64 = 64, +}; + +BitDepth get_bit_depth_from_option(const c10::optional bit_depth); + +std::string get_encoding(sox_encoding_t encoding); + +} // namespace sox_utils +} // namespace torchaudio + +#endif diff --git a/torchaudio/csrc/sox/utils.cpp b/torchaudio/csrc/sox/utils.cpp index 983b7829fe..b46067626c 100644 --- a/torchaudio/csrc/sox/utils.cpp +++ b/torchaudio/csrc/sox/utils.cpp @@ -1,5 +1,6 @@ #include #include +#include #include namespace torchaudio { @@ -80,16 +81,13 @@ void SoxFormat::close() { } } -void validate_input_file(const SoxFormat& sf, bool check_length) { +void validate_input_file(const SoxFormat& sf) { if (static_cast(sf) == nullptr) { throw std::runtime_error("Error loading audio file: failed to open file."); } if (sf->encoding.encoding == SOX_ENCODING_UNKNOWN) { throw std::runtime_error("Error loading audio file: unknown encoding."); } - if (check_length && sf->signal.length == 0) { - throw std::runtime_error("Error reading audio file: unknown length."); - } } void validate_input_tensor(const torch::Tensor tensor) { @@ -101,11 +99,15 @@ void validate_input_tensor(const torch::Tensor tensor) { throw std::runtime_error("Input tensor has to be 2D."); } - const auto dtype = tensor.dtype(); - if (!(dtype == torch::kFloat32 || dtype == torch::kInt32 || - dtype == torch::kInt16 || dtype == torch::kUInt8)) { - throw std::runtime_error( - "Input tensor has to be one of float32, int32, int16 or uint8 type."); + switch (tensor.dtype().toScalarType()) { + case c10::ScalarType::Byte: + case c10::ScalarType::Short: + case c10::ScalarType::Int: + case c10::ScalarType::Float: + break; + default: + throw std::runtime_error( + "Input tensor has to be one of float32, int32, int16 or uint8 type."); } } @@ -116,15 +118,16 @@ caffe2::TypeMeta get_dtype( switch (encoding) { case SOX_ENCODING_UNSIGNED: // 8-bit PCM WAV return torch::kUInt8; - case SOX_ENCODING_SIGN2: // 16-bit or 32-bit PCM WAV + case SOX_ENCODING_SIGN2: // 16-bit, 24-bit, or 32-bit PCM WAV switch (precision) { case 16: return torch::kInt16; + case 24: // Cast 24-bit to 32-bit. case 32: return torch::kInt32; default: throw std::runtime_error( - "Only 16 and 32 bits are supported for signed PCM."); + "Only 16, 24, and 32 bits are supported for signed PCM."); } default: // default to float32 for the other formats, including @@ -138,24 +141,6 @@ caffe2::TypeMeta get_dtype( return c10::scalarTypeToTypeMeta(dtype); } -caffe2::TypeMeta get_dtype_from_str(const std::string dtype) { - const auto tgt_dtype = [&]() { - if (dtype == "uint8") - return torch::kUInt8; - else if (dtype == "int16") - return torch::kInt16; - else if (dtype == "int32") - return torch::kInt32; - else if (dtype == "float32") - return torch::kFloat32; - else if (dtype == "float64") - return torch::kFloat64; - else - throw std::runtime_error("Unsupported dtype"); - }(); - return c10::scalarTypeToTypeMeta(tgt_dtype); -} - torch::Tensor convert_to_tensor( sox_sample_t* buffer, const int32_t num_samples, @@ -163,22 +148,32 @@ torch::Tensor convert_to_tensor( const caffe2::TypeMeta dtype, const bool normalize, const bool channels_first) { - auto t = torch::from_blob( - buffer, {num_samples / num_channels, num_channels}, torch::kInt32); - // Note: Tensor created from_blob does not own data but borrwos - // So make sure to create a new copy after processing samples. + torch::Tensor t; + uint64_t dummy = 0; + SOX_SAMPLE_LOCALS; if (normalize || dtype == torch::kFloat32) { - t = t.to(torch::kFloat32); - t *= (t > 0) / 2147483647. + (t < 0) / 2147483648.; + t = torch::empty( + {num_samples / num_channels, num_channels}, torch::kFloat32); + auto ptr = t.data_ptr(); + for (int32_t i = 0; i < num_samples; ++i) { + ptr[i] = SOX_SAMPLE_TO_FLOAT_32BIT(buffer[i], dummy); + } } else if (dtype == torch::kInt32) { - t = t.clone(); + t = torch::from_blob( + buffer, {num_samples / num_channels, num_channels}, torch::kInt32) + .clone(); } else if (dtype == torch::kInt16) { - t.floor_divide_(1 << 16); - t = t.to(torch::kInt16); + t = torch::empty({num_samples / num_channels, num_channels}, torch::kInt16); + auto ptr = t.data_ptr(); + for (int32_t i = 0; i < num_samples; ++i) { + ptr[i] = SOX_SAMPLE_TO_SIGNED_16BIT(buffer[i], dummy); + } } else if (dtype == torch::kUInt8) { - t.floor_divide_(1 << 24); - t += 128; - t = t.to(torch::kUInt8); + t = torch::empty({num_samples / num_channels, num_channels}, torch::kUInt8); + auto ptr = t.data_ptr(); + for (int32_t i = 0; i < num_samples; ++i) { + ptr[i] = SOX_SAMPLE_TO_UNSIGNED_8BIT(buffer[i], dummy); + } } else { throw std::runtime_error("Unsupported dtype."); } @@ -188,68 +183,202 @@ torch::Tensor convert_to_tensor( return t.contiguous(); } -torch::Tensor unnormalize_wav(const torch::Tensor input_tensor) { - const auto dtype = input_tensor.dtype(); - auto tensor = input_tensor; - if (dtype == torch::kFloat32) { - double multi_pos = 2147483647.; - double multi_neg = -2147483648.; - auto mult = (tensor > 0) * multi_pos - (tensor < 0) * multi_neg; - tensor = tensor.to(torch::dtype(torch::kFloat64)); - tensor *= mult; - tensor.clamp_(multi_neg, multi_pos); - tensor = tensor.to(torch::dtype(torch::kInt32)); - } else if (dtype == torch::kInt32) { - // already denormalized - } else if (dtype == torch::kInt16) { - tensor = tensor.to(torch::dtype(torch::kInt32)); - tensor *= ((tensor != 0) * 65536); - } else if (dtype == torch::kUInt8) { - tensor = tensor.to(torch::dtype(torch::kInt32)); - tensor -= 128; - tensor *= 16777216; - } else { - throw std::runtime_error("Unexpected dtype."); - } - return tensor; -} - const std::string get_filetype(const std::string path) { std::string ext = path.substr(path.find_last_of(".") + 1); std::transform(ext.begin(), ext.end(), ext.begin(), ::tolower); return ext; } -sox_encoding_t get_encoding( - const std::string filetype, - const caffe2::TypeMeta dtype) { - if (filetype == "mp3") - return SOX_ENCODING_MP3; - if (filetype == "flac") - return SOX_ENCODING_FLAC; - if (filetype == "ogg" || filetype == "vorbis") - return SOX_ENCODING_VORBIS; - if (filetype == "wav" || filetype == "amb") { - if (dtype == torch::kUInt8) - return SOX_ENCODING_UNSIGNED; - if (dtype == torch::kInt16) - return SOX_ENCODING_SIGN2; - if (dtype == torch::kInt32) - return SOX_ENCODING_SIGN2; - if (dtype == torch::kFloat32) - return SOX_ENCODING_FLOAT; - throw std::runtime_error("Unsupported dtype."); +namespace { + +std::tuple get_save_encoding_for_wav( + const std::string format, + caffe2::TypeMeta dtype, + const Encoding& encoding, + const BitDepth& bits_per_sample) { + switch (encoding) { + case Encoding::NOT_PROVIDED: + switch (bits_per_sample) { + case BitDepth::NOT_PROVIDED: + switch (dtype.toScalarType()) { + case c10::ScalarType::Float: + return std::make_tuple<>(SOX_ENCODING_FLOAT, 32); + case c10::ScalarType::Int: + return std::make_tuple<>(SOX_ENCODING_SIGN2, 32); + case c10::ScalarType::Short: + return std::make_tuple<>(SOX_ENCODING_SIGN2, 16); + case c10::ScalarType::Byte: + return std::make_tuple<>(SOX_ENCODING_UNSIGNED, 8); + default: + throw std::runtime_error("Internal Error: Unexpected dtype."); + } + case BitDepth::B8: + return std::make_tuple<>(SOX_ENCODING_UNSIGNED, 8); + default: + return std::make_tuple<>( + SOX_ENCODING_SIGN2, static_cast(bits_per_sample)); + } + case Encoding::PCM_SIGNED: + switch (bits_per_sample) { + case BitDepth::NOT_PROVIDED: + return std::make_tuple<>(SOX_ENCODING_SIGN2, 32); + case BitDepth::B8: + throw std::runtime_error( + format + " does not support 8-bit signed PCM encoding."); + default: + return std::make_tuple<>( + SOX_ENCODING_SIGN2, static_cast(bits_per_sample)); + } + case Encoding::PCM_UNSIGNED: + switch (bits_per_sample) { + case BitDepth::NOT_PROVIDED: + case BitDepth::B8: + return std::make_tuple<>(SOX_ENCODING_UNSIGNED, 8); + default: + throw std::runtime_error( + format + " only supports 8-bit for unsigned PCM encoding."); + } + case Encoding::PCM_FLOAT: + switch (bits_per_sample) { + case BitDepth::NOT_PROVIDED: + case BitDepth::B32: + return std::make_tuple<>(SOX_ENCODING_FLOAT, 32); + case BitDepth::B64: + return std::make_tuple<>(SOX_ENCODING_FLOAT, 64); + default: + throw std::runtime_error( + format + + " only supports 32-bit or 64-bit for floating-point PCM encoding."); + } + case Encoding::ULAW: + switch (bits_per_sample) { + case BitDepth::NOT_PROVIDED: + case BitDepth::B8: + return std::make_tuple<>(SOX_ENCODING_ULAW, 8); + default: + throw std::runtime_error( + format + " only supports 8-bit for mu-law encoding."); + } + case Encoding::ALAW: + switch (bits_per_sample) { + case BitDepth::NOT_PROVIDED: + case BitDepth::B8: + return std::make_tuple<>(SOX_ENCODING_ALAW, 8); + default: + throw std::runtime_error( + format + " only supports 8-bit for a-law encoding."); + } + default: + throw std::runtime_error( + format + " does not support encoding: " + to_string(encoding)); } - if (filetype == "sph") - return SOX_ENCODING_SIGN2; - if (filetype == "amr-nb") - return SOX_ENCODING_AMR_NB; - throw std::runtime_error("Unsupported file type: " + filetype); } -unsigned get_precision( - const std::string filetype, - const caffe2::TypeMeta dtype) { +std::tuple get_save_encoding( + const std::string& format, + const caffe2::TypeMeta dtype, + const c10::optional encoding, + const c10::optional bits_per_sample) { + const Format fmt = get_format_from_string(format); + const Encoding enc = get_encoding_from_option(encoding); + const BitDepth bps = get_bit_depth_from_option(bits_per_sample); + + switch (fmt) { + case Format::WAV: + case Format::AMB: + return get_save_encoding_for_wav(format, dtype, enc, bps); + case Format::MP3: + if (enc != Encoding::NOT_PROVIDED) + throw std::runtime_error("mp3 does not support `encoding` option."); + if (bps != BitDepth::NOT_PROVIDED) + throw std::runtime_error( + "mp3 does not support `bits_per_sample` option."); + return std::make_tuple<>(SOX_ENCODING_MP3, 16); + case Format::HTK: + if (enc != Encoding::NOT_PROVIDED) + throw std::runtime_error("htk does not support `encoding` option."); + if (bps != BitDepth::NOT_PROVIDED) + throw std::runtime_error( + "htk does not support `bits_per_sample` option."); + return std::make_tuple<>(SOX_ENCODING_SIGN2, 16); + case Format::VORBIS: + if (enc != Encoding::NOT_PROVIDED) + throw std::runtime_error("vorbis does not support `encoding` option."); + if (bps != BitDepth::NOT_PROVIDED) + throw std::runtime_error( + "vorbis does not support `bits_per_sample` option."); + return std::make_tuple<>(SOX_ENCODING_VORBIS, 16); + case Format::AMR_NB: + if (enc != Encoding::NOT_PROVIDED) + throw std::runtime_error("amr-nb does not support `encoding` option."); + if (bps != BitDepth::NOT_PROVIDED) + throw std::runtime_error( + "amr-nb does not support `bits_per_sample` option."); + return std::make_tuple<>(SOX_ENCODING_AMR_NB, 16); + case Format::FLAC: + if (enc != Encoding::NOT_PROVIDED) + throw std::runtime_error("flac does not support `encoding` option."); + switch (bps) { + case BitDepth::B32: + case BitDepth::B64: + throw std::runtime_error( + "flac does not support `bits_per_sample` larger than 24."); + default: + return std::make_tuple<>( + SOX_ENCODING_FLAC, static_cast(bps)); + } + case Format::SPHERE: + switch (enc) { + case Encoding::NOT_PROVIDED: + case Encoding::PCM_SIGNED: + switch (bps) { + case BitDepth::NOT_PROVIDED: + return std::make_tuple<>(SOX_ENCODING_SIGN2, 32); + default: + return std::make_tuple<>( + SOX_ENCODING_SIGN2, static_cast(bps)); + } + case Encoding::PCM_UNSIGNED: + throw std::runtime_error( + "sph does not support unsigned integer PCM."); + case Encoding::PCM_FLOAT: + throw std::runtime_error("sph does not support floating point PCM."); + case Encoding::ULAW: + switch (bps) { + case BitDepth::NOT_PROVIDED: + case BitDepth::B8: + return std::make_tuple<>(SOX_ENCODING_ULAW, 8); + default: + throw std::runtime_error( + "sph only supports 8-bit for mu-law encoding."); + } + case Encoding::ALAW: + switch (bps) { + case BitDepth::NOT_PROVIDED: + case BitDepth::B8: + return std::make_tuple<>(SOX_ENCODING_ALAW, 8); + default: + return std::make_tuple<>( + SOX_ENCODING_ALAW, static_cast(bps)); + } + default: + throw std::runtime_error( + "sph does not support encoding: " + encoding.value()); + } + case Format::GSM: + if (enc != Encoding::NOT_PROVIDED) + throw std::runtime_error("gsm does not support `encoding` option."); + if (bps != BitDepth::NOT_PROVIDED) + throw std::runtime_error( + "gsm does not support `bits_per_sample` option."); + return std::make_tuple<>(SOX_ENCODING_GSM, 16); + + default: + throw std::runtime_error("Unsupported format: " + format); + } +} + +unsigned get_precision(const std::string filetype, caffe2::TypeMeta dtype) { if (filetype == "mp3") return SOX_UNSPEC; if (filetype == "flac") @@ -257,27 +386,35 @@ unsigned get_precision( if (filetype == "ogg" || filetype == "vorbis") return SOX_UNSPEC; if (filetype == "wav" || filetype == "amb") { - if (dtype == torch::kUInt8) - return 8; - if (dtype == torch::kInt16) - return 16; - if (dtype == torch::kInt32) - return 32; - if (dtype == torch::kFloat32) - return 32; - throw std::runtime_error("Unsupported dtype."); + switch (dtype.toScalarType()) { + case c10::ScalarType::Byte: + return 8; + case c10::ScalarType::Short: + return 16; + case c10::ScalarType::Int: + return 32; + case c10::ScalarType::Float: + return 32; + default: + throw std::runtime_error("Unsupported dtype."); + } } if (filetype == "sph") return 32; if (filetype == "amr-nb") { - TORCH_INTERNAL_ASSERT( - dtype == torch::kInt16, - "When saving to AMR-NB format, the input tensor must be int16 type."); + return 16; + } + if (filetype == "gsm") { + return 16; + } + if (filetype == "htk") { return 16; } throw std::runtime_error("Unsupported file type: " + filetype); } +} // namespace + sox_signalinfo_t get_signalinfo( const torch::Tensor* waveform, const int64_t sample_rate, @@ -291,28 +428,34 @@ sox_signalinfo_t get_signalinfo( /*length=*/static_cast(waveform->numel())}; } -sox_encodinginfo_t get_tensor_encodinginfo(const caffe2::TypeMeta dtype) { +sox_encodinginfo_t get_tensor_encodinginfo(caffe2::TypeMeta dtype) { sox_encoding_t encoding = [&]() { - if (dtype == torch::kUInt8) - return SOX_ENCODING_UNSIGNED; - if (dtype == torch::kInt16) - return SOX_ENCODING_SIGN2; - if (dtype == torch::kInt32) - return SOX_ENCODING_SIGN2; - if (dtype == torch::kFloat32) - return SOX_ENCODING_FLOAT; - throw std::runtime_error("Unsupported dtype."); + switch (dtype.toScalarType()) { + case c10::ScalarType::Byte: + return SOX_ENCODING_UNSIGNED; + case c10::ScalarType::Short: + return SOX_ENCODING_SIGN2; + case c10::ScalarType::Int: + return SOX_ENCODING_SIGN2; + case c10::ScalarType::Float: + return SOX_ENCODING_FLOAT; + default: + throw std::runtime_error("Unsupported dtype."); + } }(); unsigned bits_per_sample = [&]() { - if (dtype == torch::kUInt8) - return 8; - if (dtype == torch::kInt16) - return 16; - if (dtype == torch::kInt32) - return 32; - if (dtype == torch::kFloat32) - return 32; - throw std::runtime_error("Unsupported dtype."); + switch (dtype.toScalarType()) { + case c10::ScalarType::Byte: + return 8; + case c10::ScalarType::Short: + return 16; + case c10::ScalarType::Int: + return 32; + case c10::ScalarType::Float: + return 32; + default: + throw std::runtime_error("Unsupported dtype."); + } }(); return sox_encodinginfo_t{ /*encoding=*/encoding, @@ -325,12 +468,15 @@ sox_encodinginfo_t get_tensor_encodinginfo(const caffe2::TypeMeta dtype) { } sox_encodinginfo_t get_encodinginfo_for_save( - const std::string filetype, + const std::string& format, const caffe2::TypeMeta dtype, - c10::optional& compression) { + const c10::optional compression, + const c10::optional encoding, + const c10::optional bits_per_sample) { + auto enc = get_save_encoding(format, dtype, encoding, bits_per_sample); return sox_encodinginfo_t{ - /*encoding=*/get_encoding(filetype, dtype), - /*bits_per_sample=*/get_precision(filetype, dtype), + /*encoding=*/std::get<0>(enc), + /*bits_per_sample=*/std::get<1>(enc), /*compression=*/compression.value_or(HUGE_VAL), /*reverse_bytes=*/sox_option_default, /*reverse_nibbles=*/sox_option_default, diff --git a/torchaudio/csrc/sox/utils.h b/torchaudio/csrc/sox/utils.h index ea2a6a2953..7e736dbe8d 100644 --- a/torchaudio/csrc/sox/utils.h +++ b/torchaudio/csrc/sox/utils.h @@ -56,7 +56,7 @@ struct SoxFormat { /// /// Verify that input file is found, has known encoding, and not empty -void validate_input_file(const SoxFormat& sf, bool check_length = true); +void validate_input_file(const SoxFormat& sf); /// /// Verify that input Tensor is 2D, CPU and either uin8, int16, int32 or float32 @@ -68,8 +68,6 @@ caffe2::TypeMeta get_dtype( const sox_encoding_t encoding, const unsigned precision); -caffe2::TypeMeta get_dtype_from_str(const std::string dtype); - /// /// Convert sox_sample_t buffer to uint8/int16/int32/float32 Tensor /// NOTE: This function might modify the values in the input buffer to @@ -93,11 +91,6 @@ torch::Tensor convert_to_tensor( const bool normalize, const bool channels_first); -/// -/// Convert float32/int32/int16/uint8 Tensor to int32 for Torch -> Sox -/// conversion. -torch::Tensor unnormalize_wav(const torch::Tensor); - /// Extract extension from file path const std::string get_filetype(const std::string path); @@ -113,9 +106,11 @@ sox_encodinginfo_t get_tensor_encodinginfo(const caffe2::TypeMeta dtype); /// Get sox_encodinginfo_t for saving to file/file object sox_encodinginfo_t get_encodinginfo_for_save( - const std::string filetype, + const std::string& format, const caffe2::TypeMeta dtype, - c10::optional& compression); + const c10::optional compression, + const c10::optional encoding, + const c10::optional bits_per_sample); #ifdef TORCH_API_INCLUDE_EXTENSION_H diff --git a/torchaudio/csrc/transducer.cpp b/torchaudio/csrc/transducer.cpp index f5d06c1ba9..00fa49b4b5 100644 --- a/torchaudio/csrc/transducer.cpp +++ b/torchaudio/csrc/transducer.cpp @@ -17,11 +17,40 @@ int64_t cpu_rnnt_loss( torch::Tensor grads, int64_t blank_label, int64_t num_threads) { + TORCH_CHECK(labels.dtype() == torch::kInt32, "labels must be int32 type"); + TORCH_CHECK( + label_lengths.dtype() == torch::kInt32, + "label_lengths must be int32 type"); + TORCH_CHECK( + input_lengths.dtype() == torch::kInt32, "lengths must be int32 type"); + TORCH_CHECK(acts.is_contiguous(), "acts must be contiguous"); + TORCH_CHECK(labels.is_contiguous(), "labels must be contiguous"); + TORCH_CHECK( + label_lengths.is_contiguous(), "label_lengths must be contiguous"); + TORCH_CHECK(input_lengths.is_contiguous(), "lengths must be contiguous"); + TORCH_CHECK( + input_lengths.size(0) == acts.size(0), + "batch dimension mismatch between acts and input_lengths: each example must have a length"); + TORCH_CHECK( + label_lengths.size(0) == acts.size(0), + "batch dimension mismatch between acts and label_lengths: each example must have a label length"); + TORCH_CHECK(acts.dim() == 4, "acts must be 4-D (batch, time, label, class)"); + TORCH_CHECK( + labels.dim() == 2, "labels must be 2-D (batch, max label length)"); + TORCH_CHECK(input_lengths.dim() == 1, "input_lengths must be 1-D"); + TORCH_CHECK(label_lengths.dim() == 1, "label_lengths must be 1-D"); + int maxT = acts.size(1); int maxU = acts.size(2); int minibatch_size = acts.size(0); int alphabet_size = acts.size(3); + TORCH_CHECK( + at::max(input_lengths).item().toInt() == maxT, "input length mismatch"); + TORCH_CHECK( + at::max(label_lengths).item().toInt() + 1 == maxU, + "output length mismatch"); + rnntOptions options; memset(&options, 0, sizeof(options)); options.maxT = maxT; diff --git a/torchaudio/csrc/utils.cpp b/torchaudio/csrc/utils.cpp new file mode 100644 index 0000000000..e8050bb69a --- /dev/null +++ b/torchaudio/csrc/utils.cpp @@ -0,0 +1,30 @@ +#include + +namespace torchaudio { + +namespace { + +bool is_sox_available() { +#ifdef INCLUDE_SOX + return true; +#else + return false; +#endif +} + +bool is_kaldi_available() { +#ifdef INCLUDE_KALDI + return true; +#else + return false; +#endif +} + +} // namespace + +TORCH_LIBRARY_FRAGMENT(torchaudio, m) { + m.def("torchaudio::is_sox_available", &is_sox_available); + m.def("torchaudio::is_kaldi_available", &is_kaldi_available); +} + +} // namespace torchaudio diff --git a/torchaudio/datasets/speechcommands.py b/torchaudio/datasets/speechcommands.py index 5264ea24de..fdde2855ba 100644 --- a/torchaudio/datasets/speechcommands.py +++ b/torchaudio/datasets/speechcommands.py @@ -34,7 +34,15 @@ def _load_list(root, *filenames): def load_speechcommands_item(filepath: str, path: str) -> Tuple[Tensor, int, str, str, int]: relpath = os.path.relpath(filepath, path) label, filename = os.path.split(relpath) + # Besides the officially supported split method for datasets defined by "validation_list.txt" + # and "testing_list.txt" over "speech_commands_v0.0x.tar.gz" archives, an alternative split + # method referred to in paragraph 2-3 of Section 7.1, references 13 and 14 of the original + # paper, and the checksums file from the tensorflow_datasets package [1] is also supported. + # Some filenames in those "speech_commands_test_set_v0.0x.tar.gz" archives have the form + # "xxx.wav.wav", so file extensions twice needs to be stripped twice. + # [1] https://github.com/tensorflow/datasets/blob/master/tensorflow_datasets/url_checksums/speech_commands.txt speaker, _ = os.path.splitext(filename) + speaker, _ = os.path.splitext(speaker) speaker_id, utterance_number = speaker.split(HASH_DIVIDER) utterance_number = int(utterance_number) @@ -60,7 +68,10 @@ class SPEECHCOMMANDS(Dataset): subset (Optional[str]): Select a subset of the dataset [None, "training", "validation", "testing"]. None means the whole dataset. "validation" and "testing" are defined in "validation_list.txt" and - "testing_list.txt", respectively, and "training" is the rest. (default: ``None``) + "testing_list.txt", respectively, and "training" is the rest. Details for the files + "validation_list.txt" and "testing_list.txt" are explained in the README of the dataset + and in the introduction of Section 7 of the original paper and its reference 12. The + original paper can be found `here `_. (Default: ``None``) """ def __init__(self, diff --git a/torchaudio/datasets/tedlium.py b/torchaudio/datasets/tedlium.py index e8d1d1cefc..fb96ca5789 100644 --- a/torchaudio/datasets/tedlium.py +++ b/torchaudio/datasets/tedlium.py @@ -153,11 +153,7 @@ def _load_audio(self, path: str, start_time: float, end_time: float, sample_rate start_time = int(float(start_time) * sample_rate) end_time = int(float(end_time) * sample_rate) - backend = torchaudio.get_audio_backend() - if backend == "sox" or (backend == "soundfile" and torchaudio.USE_SOUNDFILE_LEGACY_INTERFACE): - kwargs = {"offset": start_time, "num_frames": end_time - start_time} - else: - kwargs = {"frame_offset": start_time, "num_frames": end_time - start_time} + kwargs = {"frame_offset": start_time, "num_frames": end_time - start_time} return torchaudio.load(path, **kwargs) diff --git a/torchaudio/extension/extension.py b/torchaudio/extension/extension.py index 5875f41023..5af62f19be 100644 --- a/torchaudio/extension/extension.py +++ b/torchaudio/extension/extension.py @@ -9,6 +9,7 @@ def _init_extension(): ext = 'torchaudio._torchaudio' if _mod_utils.is_module_available(ext): _init_script_module(ext) + import torchaudio._torchaudio # noqa else: warnings.warn('torchaudio C++ extension is not available.') diff --git a/torchaudio/functional/__init__.py b/torchaudio/functional/__init__.py index d59400e82e..88fc4d545f 100644 --- a/torchaudio/functional/__init__.py +++ b/torchaudio/functional/__init__.py @@ -3,6 +3,7 @@ angle, complex_norm, compute_deltas, + compute_kaldi_pitch, create_dct, create_fb_matrix, DB_to_amplitude, @@ -17,6 +18,7 @@ sliding_window_cmn, spectrogram, spectral_centroid, + apply_codec, ) from .filtering import ( allpass_biquad, @@ -47,6 +49,7 @@ 'angle', 'complex_norm', 'compute_deltas', + 'compute_kaldi_pitch', 'create_dct', 'create_fb_matrix', 'DB_to_amplitude', @@ -82,4 +85,5 @@ 'riaa_biquad', 'treble_biquad', 'vad', + 'apply_codec' ] diff --git a/torchaudio/functional/filtering.py b/torchaudio/functional/filtering.py index 55cf05a51f..82d9727876 100644 --- a/torchaudio/functional/filtering.py +++ b/torchaudio/functional/filtering.py @@ -20,7 +20,7 @@ def _generate_wave_table( phase: float, device: torch.device, ) -> Tensor: - r"""A helper fucntion for phaser. Generates a table with given parameters + r"""A helper function for phaser. Generates a table with given parameters. Args: wave_type (str): SINE or TRIANGULAR @@ -446,7 +446,7 @@ def _apply_probability_distribution( or Gaussian curve, typical of dither generated by analog sources. Args: waveform (Tensor): Tensor of audio of dimension (..., time) - probability_density_function (str, optional): The density function of a + density_function (str, optional): The density function of a continuous random variable (Default: ``"TPDF"``) Options: Triangular Probability Density Function - `TPDF` Rectangular Probability Density Function - `RPDF` @@ -625,7 +625,7 @@ def flanger( Allowed range of values are 0 to 30 depth (float): desired delay depth in milliseconds(ms) Allowed range of values are 0 to 10 - regen (float): desired regen(feeback gain) in dB + regen (float): desired regen(feedback gain) in dB Allowed range of values are -95 to 95 width (float): desired width(delay gain) in dB Allowed range of values are 0 to 100 @@ -808,83 +808,104 @@ def highpass_biquad( return biquad(waveform, b0, b1, b2, a0, a1, a2) -def lfilter( +def _lfilter_core_generic_loop(input_signal_windows: Tensor, a_coeffs_flipped: Tensor, padded_output_waveform: Tensor): + n_order = a_coeffs_flipped.size(0) + for i_sample, o0 in enumerate(input_signal_windows.t()): + windowed_output_signal = padded_output_waveform[ + :, i_sample:i_sample + n_order + ] + o0.addmv_(windowed_output_signal, a_coeffs_flipped, alpha=-1) + padded_output_waveform[:, i_sample + n_order - 1] = o0 + + +try: + _lfilter_core_cpu_loop = torch.ops.torchaudio._lfilter_core_loop +except RuntimeError as err: + assert str(err) == 'No such operator torchaudio::_lfilter_core_loop' + _lfilter_core_cpu_loop = _lfilter_core_generic_loop + + +def _lfilter_core( waveform: Tensor, a_coeffs: Tensor, b_coeffs: Tensor, - clamp: bool = True, ) -> Tensor: - r"""Perform an IIR filter by evaluating difference equation. - - Args: - waveform (Tensor): audio waveform of dimension of ``(..., time)``. Must be normalized to -1 to 1. - a_coeffs (Tensor): denominator coefficients of difference equation of dimension of ``(n_order + 1)``. - Lower delays coefficients are first, e.g. ``[a0, a1, a2, ...]``. - Must be same size as b_coeffs (pad with 0's as necessary). - b_coeffs (Tensor): numerator coefficients of difference equation of dimension of ``(n_order + 1)``. - Lower delays coefficients are first, e.g. ``[b0, b1, b2, ...]``. - Must be same size as a_coeffs (pad with 0's as necessary). - clamp (bool, optional): If ``True``, clamp the output signal to be in the range [-1, 1] (Default: ``True``) - - Returns: - Tensor: Waveform with dimension of ``(..., time)``. - """ - # pack batch - shape = waveform.size() - waveform = waveform.reshape(-1, shape[-1]) assert a_coeffs.size(0) == b_coeffs.size(0) assert len(waveform.size()) == 2 assert waveform.device == a_coeffs.device assert b_coeffs.device == a_coeffs.device - device = waveform.device - dtype = waveform.dtype n_channel, n_sample = waveform.size() n_order = a_coeffs.size(0) - n_sample_padded = n_sample + n_order - 1 assert n_order > 0 # Pad the input and create output - padded_waveform = torch.zeros( - n_channel, n_sample_padded, dtype=dtype, device=device - ) - padded_waveform[:, n_order - 1:] = waveform - padded_output_waveform = torch.zeros( - n_channel, n_sample_padded, dtype=dtype, device=device - ) + + padded_waveform = torch.nn.functional.pad(waveform, [n_order - 1, 0]) + padded_output_waveform = torch.zeros_like(padded_waveform) # Set up the coefficients matrix # Flip coefficients' order a_coeffs_flipped = a_coeffs.flip(0) b_coeffs_flipped = b_coeffs.flip(0) - # calculate windowed_input_signal in parallel - # create indices of original with shape (n_channel, n_order, n_sample) - window_idxs = torch.arange(n_sample, device=device).unsqueeze(0) + torch.arange( - n_order, device=device - ).unsqueeze(1) - window_idxs = window_idxs.repeat(n_channel, 1, 1) - window_idxs += ( - torch.arange(n_channel, device=device).unsqueeze(-1).unsqueeze(-1) - * n_sample_padded - ) - window_idxs = window_idxs.long() - # (n_order, ) matmul (n_channel, n_order, n_sample) -> (n_channel, n_sample) - input_signal_windows = torch.matmul( - b_coeffs_flipped, torch.take(padded_waveform, window_idxs) - ) + # calculate windowed_input_signal in parallel using convolution + input_signal_windows = torch.nn.functional.conv1d( + padded_waveform.unsqueeze(1), + b_coeffs_flipped.view(1, 1, -1) + ).squeeze(1) input_signal_windows.div_(a_coeffs[0]) a_coeffs_flipped.div_(a_coeffs[0]) - for i_sample, o0 in enumerate(input_signal_windows.t()): - windowed_output_signal = padded_output_waveform[ - :, i_sample:i_sample + n_order - ] - o0.addmv_(windowed_output_signal, a_coeffs_flipped, alpha=-1) - padded_output_waveform[:, i_sample + n_order - 1] = o0 + + if input_signal_windows.device == torch.device('cpu') and\ + a_coeffs_flipped.device == torch.device('cpu') and\ + padded_output_waveform.device == torch.device('cpu'): + _lfilter_core_cpu_loop(input_signal_windows, a_coeffs_flipped, padded_output_waveform) + else: + _lfilter_core_generic_loop(input_signal_windows, a_coeffs_flipped, padded_output_waveform) output = padded_output_waveform[:, n_order - 1:] + return output + +try: + _lfilter = torch.ops.torchaudio._lfilter +except RuntimeError as err: + assert str(err) == 'No such operator torchaudio::_lfilter' + _lfilter = _lfilter_core + + +def lfilter( + waveform: Tensor, + a_coeffs: Tensor, + b_coeffs: Tensor, + clamp: bool = True, +) -> Tensor: + r"""Perform an IIR filter by evaluating difference equation. + + Note: + To avoid numerical problems, small filter order is preferred. + Using double precision could also minimize numerical precision errors. + + Args: + waveform (Tensor): audio waveform of dimension of ``(..., time)``. Must be normalized to -1 to 1. + a_coeffs (Tensor): denominator coefficients of difference equation of dimension of ``(n_order + 1)``. + Lower delays coefficients are first, e.g. ``[a0, a1, a2, ...]``. + Must be same size as b_coeffs (pad with 0's as necessary). + b_coeffs (Tensor): numerator coefficients of difference equation of dimension of ``(n_order + 1)``. + Lower delays coefficients are first, e.g. ``[b0, b1, b2, ...]``. + Must be same size as a_coeffs (pad with 0's as necessary). + clamp (bool, optional): If ``True``, clamp the output signal to be in the range [-1, 1] (Default: ``True``) + + Returns: + Tensor: Waveform with dimension of ``(..., time)``. + """ + # pack batch + shape = waveform.size() + waveform = waveform.reshape(-1, shape[-1]) + + output = _lfilter(waveform, a_coeffs, b_coeffs) if clamp: output = torch.clamp(output, min=-1.0, max=1.0) @@ -921,6 +942,26 @@ def lowpass_biquad( return biquad(waveform, b0, b1, b2, a0, a1, a2) +def _overdrive_core_loop_generic( + waveform: Tensor, + temp: Tensor, + last_in: Tensor, + last_out: Tensor, + output_waveform: Tensor +): + for i in range(waveform.shape[-1]): + last_out = temp[:, i] - last_in + 0.995 * last_out + last_in = temp[:, i] + output_waveform[:, i] = waveform[:, i] * 0.5 + last_out * 0.75 + + +try: + _overdrive_core_loop_cpu = torch.ops.torchaudio._overdrive_core_loop +except RuntimeError as err: + assert str(err) == 'No such operator torchaudio::_overdrive_core_loop' + _overdrive_core_loop_cpu = _overdrive_core_loop_generic + + def overdrive(waveform: Tensor, gain: float = 20, colour: float = 20) -> Tensor: r"""Apply a overdrive effect to the audio. Similar to SoX implementation. This effect applies a non linear distortion to the audio signal. @@ -963,11 +1004,11 @@ def overdrive(waveform: Tensor, gain: float = 20, colour: float = 20) -> Tensor: output_waveform = torch.zeros_like(waveform, dtype=dtype, device=device) - # TODO: Implement a torch CPP extension - for i in range(waveform.shape[-1]): - last_out = temp[:, i] - last_in + 0.995 * last_out - last_in = temp[:, i] - output_waveform[:, i] = waveform[:, i] * 0.5 + last_out * 0.75 + # Uses CPU optimized loop function if available for CPU device + if device == torch.device('cpu'): + _overdrive_core_loop_cpu(waveform, temp, last_in, last_out, output_waveform) + else: + _overdrive_core_loop_generic(waveform, temp, last_in, last_out, output_waveform) return output_waveform.clamp(min=-1, max=1).view(actual_shape) @@ -991,7 +1032,7 @@ def phaser( Allowed range of values are 0 to 1 gain_out (float): desired output gain at the boost (or attenuation) in dB Allowed range of values are 0 to 1e9 - delay_ms (float): desired delay in milli seconds + delay_ms (float): desired delay in milliseconds Allowed range of values are 0 to 5.0 decay (float): desired decay relative to gain-in Allowed range of values are 0 to 0.99 @@ -1064,7 +1105,7 @@ def phaser( def riaa_biquad(waveform: Tensor, sample_rate: int) -> Tensor: - r"""Apply RIAA vinyl playback equalisation. Similar to SoX implementation. + r"""Apply RIAA vinyl playback equalization. Similar to SoX implementation. Args: waveform (Tensor): audio waveform of dimension of `(..., time)` @@ -1108,7 +1149,7 @@ def riaa_biquad(waveform: Tensor, sample_rate: int) -> Tensor: a1 = -(poles[0] + poles[1]) a2 = poles[0] * poles[1] - # Normalise to 0dB at 1kHz + # Normalize to 0dB at 1kHz y = 2 * math.pi * 1000 / sample_rate b_re = b0 + b1 * math.cos(-y) + b2 * math.cos(-2 * y) a_re = a0 + a1 * math.cos(-y) + a2 * math.cos(-2 * y) @@ -1288,7 +1329,7 @@ def vad( to search for quieter/shorter bursts of audio to include prior to the detected trigger point. (Default: 1.0) allowed_gap (float, optional): The allowed gap (in seconds) between - quiteter/shorter bursts of audio to include prior + quieter/shorter bursts of audio to include prior to the detected trigger point. (Default: 0.25) pre_trigger_time (float, optional): The amount of audio (in seconds) to preserve before the trigger point and any found quieter/shorter bursts. (Default: 0.0) diff --git a/torchaudio/functional/functional.py b/torchaudio/functional/functional.py index 4dde324a31..b114b9aacf 100644 --- a/torchaudio/functional/functional.py +++ b/torchaudio/functional/functional.py @@ -1,11 +1,14 @@ # -*- coding: utf-8 -*- +import io import math -from typing import Optional, Tuple import warnings +from typing import Optional, Tuple import torch from torch import Tensor +from torchaudio._internal import module_utils as _mod_utils +import torchaudio __all__ = [ "spectrogram", @@ -13,6 +16,7 @@ "amplitude_to_DB", "DB_to_amplitude", "compute_deltas", + "compute_kaldi_pitch", "create_fb_matrix", "create_dct", "compute_deltas", @@ -28,6 +32,7 @@ 'mask_along_axis_iid', 'sliding_window_cmn', "spectral_centroid", + "apply_codec", ] @@ -113,7 +118,6 @@ def griffinlim( hop_length: int, win_length: int, power: float, - normalized: bool, n_iter: int, momentum: float, length: Optional[int], @@ -143,7 +147,6 @@ def griffinlim( win_length (int): Window size. (Default: ``n_fft``) power (float): Exponent for the magnitude spectrogram, (must be > 0) e.g., 1 for energy, 2 for power, etc. - normalized (bool): Whether to normalize by magnitude after stft. n_iter (int): Number of iteration for phase recovery process. momentum (float): The momentum parameter for fast Griffin-Lim. Setting this to 0 recovers the original Griffin-Lim method. @@ -157,12 +160,6 @@ def griffinlim( assert momentum < 1, 'momentum={} > 1 can be unstable'.format(momentum) assert momentum >= 0, 'momentum={} < 0'.format(momentum) - if normalized: - warnings.warn( - "The argument normalized is not used in Griffin-Lim, " - "and will be removed in v0.9.0 release. To suppress this warning, " - "please use `normalized=False`.") - # pack batch shape = specgram.size() specgram = specgram.reshape([-1] + list(shape[-2:])) @@ -291,13 +288,81 @@ def DB_to_amplitude( return ref * torch.pow(torch.pow(10.0, 0.1 * x), power) +def _hz_to_mel(freq: float, mel_scale: str = "htk") -> float: + r"""Convert Hz to Mels. + + Args: + freqs (float): Frequencies in Hz + mel_scale (str, optional): Scale to use: ``htk`` or ``slaney``. (Default: ``htk``) + + Returns: + mels (float): Frequency in Mels + """ + + if mel_scale not in ['slaney', 'htk']: + raise ValueError('mel_scale should be one of "htk" or "slaney".') + + if mel_scale == "htk": + return 2595.0 * math.log10(1.0 + (freq / 700.0)) + + # Fill in the linear part + f_min = 0.0 + f_sp = 200.0 / 3 + + mels = (freq - f_min) / f_sp + + # Fill in the log-scale part + min_log_hz = 1000.0 + min_log_mel = (min_log_hz - f_min) / f_sp + logstep = math.log(6.4) / 27.0 + + if freq >= min_log_hz: + mels = min_log_mel + math.log(freq / min_log_hz) / logstep + + return mels + + +def _mel_to_hz(mels: Tensor, mel_scale: str = "htk") -> Tensor: + """Convert mel bin numbers to frequencies. + + Args: + mels (Tensor): Mel frequencies + mel_scale (str, optional): Scale to use: ``htk`` or ``slaney``. (Default: ``htk``) + + Returns: + freqs (Tensor): Mels converted in Hz + """ + + if mel_scale not in ['slaney', 'htk']: + raise ValueError('mel_scale should be one of "htk" or "slaney".') + + if mel_scale == "htk": + return 700.0 * (10.0**(mels / 2595.0) - 1.0) + + # Fill in the linear scale + f_min = 0.0 + f_sp = 200.0 / 3 + freqs = f_min + f_sp * mels + + # And now the nonlinear scale + min_log_hz = 1000.0 + min_log_mel = (min_log_hz - f_min) / f_sp + logstep = math.log(6.4) / 27.0 + + log_t = (mels >= min_log_mel) + freqs[log_t] = min_log_hz * torch.exp(logstep * (mels[log_t] - min_log_mel)) + + return freqs + + def create_fb_matrix( n_freqs: int, f_min: float, f_max: float, n_mels: int, sample_rate: int, - norm: Optional[str] = None + norm: Optional[str] = None, + mel_scale: str = "htk", ) -> Tensor: r"""Create a frequency bin conversion matrix. @@ -309,6 +374,7 @@ def create_fb_matrix( sample_rate (int): Sample rate of the audio waveform norm (Optional[str]): If 'slaney', divide the triangular mel weights by the width of the mel band (area normalization). (Default: ``None``) + mel_scale (str, optional): Scale to use: ``htk`` or ``slaney``. (Default: ``htk``) Returns: Tensor: Triangular filter banks (fb matrix) of size (``n_freqs``, ``n_mels``) @@ -326,12 +392,12 @@ def create_fb_matrix( all_freqs = torch.linspace(0, sample_rate // 2, n_freqs) # calculate mel freq bins - # hertz to mel(f) is 2595. * math.log10(1. + (f / 700.)) - m_min = 2595.0 * math.log10(1.0 + (f_min / 700.0)) - m_max = 2595.0 * math.log10(1.0 + (f_max / 700.0)) + m_min = _hz_to_mel(f_min, mel_scale=mel_scale) + m_max = _hz_to_mel(f_max, mel_scale=mel_scale) + m_pts = torch.linspace(m_min, m_max, n_mels + 2) - # mel to hertz(mel) is 700. * (10**(mel / 2595.) - 1.) - f_pts = 700.0 * (10 ** (m_pts / 2595.0) - 1.0) + f_pts = _mel_to_hz(m_pts, mel_scale=mel_scale) + # calculate the difference between each mel point and each stft freq point in hertz f_diff = f_pts[1:] - f_pts[:-1] # (n_mels + 1) slopes = f_pts.unsqueeze(0) - all_freqs.unsqueeze(1) # (n_freqs, n_mels + 2) @@ -868,7 +934,7 @@ def detect_pitch_frequency( def sliding_window_cmn( - waveform: Tensor, + specgram: Tensor, cmn_window: int = 600, min_cmn_window: int = 100, center: bool = False, @@ -878,7 +944,7 @@ def sliding_window_cmn( Apply sliding-window cepstral mean (and optionally variance) normalization per utterance. Args: - waveform (Tensor): Tensor of audio of dimension (..., freq, time) + specgram (Tensor): Tensor of audio of dimension (..., time, freq) cmn_window (int, optional): Window in frames for running average CMN computation (int, default = 600) min_cmn_window (int, optional): Minimum CMN window used at start of decoding (adds latency only at start). Only applicable if center == false, ignored if center==true (int, default = 100) @@ -887,19 +953,19 @@ def sliding_window_cmn( norm_vars (bool, optional): If true, normalize variance to one. (bool, default = false) Returns: - Tensor: Tensor of freq of dimension (..., frame) + Tensor: Tensor matching input shape (..., freq, time) """ - input_shape = waveform.shape + input_shape = specgram.shape num_frames, num_feats = input_shape[-2:] - waveform = waveform.view(-1, num_frames, num_feats) - num_channels = waveform.shape[0] + specgram = specgram.view(-1, num_frames, num_feats) + num_channels = specgram.shape[0] - dtype = waveform.dtype - device = waveform.device + dtype = specgram.dtype + device = specgram.device last_window_start = last_window_end = -1 cur_sum = torch.zeros(num_channels, num_feats, dtype=dtype, device=device) cur_sumsq = torch.zeros(num_channels, num_feats, dtype=dtype, device=device) - cmn_waveform = torch.zeros( + cmn_specgram = torch.zeros( num_channels, num_frames, num_feats, dtype=dtype, device=device) for t in range(num_frames): window_start = 0 @@ -922,40 +988,40 @@ def sliding_window_cmn( if window_start < 0: window_start = 0 if last_window_start == -1: - input_part = waveform[:, window_start: window_end - window_start, :] + input_part = specgram[:, window_start: window_end - window_start, :] cur_sum += torch.sum(input_part, 1) if norm_vars: cur_sumsq += torch.cumsum(input_part ** 2, 1)[:, -1, :] else: if window_start > last_window_start: - frame_to_remove = waveform[:, last_window_start, :] + frame_to_remove = specgram[:, last_window_start, :] cur_sum -= frame_to_remove if norm_vars: cur_sumsq -= (frame_to_remove ** 2) if window_end > last_window_end: - frame_to_add = waveform[:, last_window_end, :] + frame_to_add = specgram[:, last_window_end, :] cur_sum += frame_to_add if norm_vars: cur_sumsq += (frame_to_add ** 2) window_frames = window_end - window_start last_window_start = window_start last_window_end = window_end - cmn_waveform[:, t, :] = waveform[:, t, :] - cur_sum / window_frames + cmn_specgram[:, t, :] = specgram[:, t, :] - cur_sum / window_frames if norm_vars: if window_frames == 1: - cmn_waveform[:, t, :] = torch.zeros( + cmn_specgram[:, t, :] = torch.zeros( num_channels, num_feats, dtype=dtype, device=device) else: variance = cur_sumsq variance = variance / window_frames variance -= ((cur_sum ** 2) / (window_frames ** 2)) variance = torch.pow(variance, -0.5) - cmn_waveform[:, t, :] *= variance + cmn_specgram[:, t, :] *= variance - cmn_waveform = cmn_waveform.view(input_shape[:-2] + (num_frames, num_feats)) + cmn_specgram = cmn_specgram.view(input_shape[:-2] + (num_frames, num_feats)) if len(input_shape) == 2: - cmn_waveform = cmn_waveform.squeeze(0) - return cmn_waveform + cmn_specgram = cmn_specgram.squeeze(0) + return cmn_specgram def spectral_centroid( @@ -991,3 +1057,155 @@ def spectral_centroid( device=specgram.device).reshape((-1, 1)) freq_dim = -2 return (freqs * specgram).sum(dim=freq_dim) / specgram.sum(dim=freq_dim) + + +@_mod_utils.requires_sox() +def apply_codec( + waveform: Tensor, + sample_rate: int, + format: str, + channels_first: bool = True, + compression: Optional[float] = None, + encoding: Optional[str] = None, + bits_per_sample: Optional[int] = None, +) -> Tensor: + r""" + Apply codecs as a form of augmentation. + + Args: + waveform (Tensor): Audio data. Must be 2 dimensional. See also ```channels_first```. + sample_rate (int): Sample rate of the audio waveform. + format (str): File format. + channels_first (bool): + When True, both the input and output Tensor have dimension ``[channel, time]``. + Otherwise, they have dimension ``[time, channel]``. + compression (float): Used for formats other than WAV. + For mor details see :py:func:`torchaudio.backend.sox_io_backend.save`. + encoding (str, optional): Changes the encoding for the supported formats. + For more details see :py:func:`torchaudio.backend.sox_io_backend.save`. + bits_per_sample (int, optional): Changes the bit depth for the supported formats. + For more details see :py:func:`torchaudio.backend.sox_io_backend.save`. + + Returns: + torch.Tensor: Resulting Tensor. + If ``channels_first=True``, it has ``[channel, time]`` else ``[time, channel]``. + """ + bytes = io.BytesIO() + torchaudio.backend.sox_io_backend.save(bytes, + waveform, + sample_rate, + channels_first, + compression, + format, + encoding, + bits_per_sample + ) + bytes.seek(0) + augmented, _ = torchaudio.sox_effects.sox_effects.apply_effects_file( + bytes, effects=[["rate", f"{sample_rate}"]], channels_first=channels_first, format=format) + return augmented + + +@_mod_utils.requires_kaldi() +def compute_kaldi_pitch( + waveform: torch.Tensor, + sample_rate: float, + frame_length: float = 25.0, + frame_shift: float = 10.0, + min_f0: float = 50, + max_f0: float = 400, + soft_min_f0: float = 10.0, + penalty_factor: float = 0.1, + lowpass_cutoff: float = 1000, + resample_frequency: float = 4000, + delta_pitch: float = 0.005, + nccf_ballast: float = 7000, + lowpass_filter_width: int = 1, + upsample_filter_width: int = 5, + max_frames_latency: int = 0, + frames_per_chunk: int = 0, + simulate_first_pass_online: bool = False, + recompute_frame: int = 500, + snip_edges: bool = True, +) -> torch.Tensor: + """Extract pitch based on method described in [1]. + + This function computes the equivalent of `compute-kaldi-pitch-feats` from Kaldi. + + Args: + waveform (Tensor): + The input waveform of shape `(..., time)`. + sample_rate (float): + Sample rate of `waveform`. + frame_length (float, optional): + Frame length in milliseconds. (default: 25.0) + frame_shift (float, optional): + Frame shift in milliseconds. (default: 10.0) + min_f0 (float, optional): + Minimum F0 to search for (Hz) (default: 50.0) + max_f0 (float, optional): + Maximum F0 to search for (Hz) (default: 400.0) + soft_min_f0 (float, optional): + Minimum f0, applied in soft way, must not exceed min-f0 (default: 10.0) + penalty_factor (float, optional): + Cost factor for FO change. (default: 0.1) + lowpass_cutoff (float, optional): + Cutoff frequency for LowPass filter (Hz) (default: 1000) + resample_frequency (float, optional): + Frequency that we down-sample the signal to. Must be more than twice lowpass-cutoff. + (default: 4000) + delta_pitch( float, optional): + Smallest relative change in pitch that our algorithm measures. (default: 0.005) + nccf_ballast (float, optional): + Increasing this factor reduces NCCF for quiet frames (default: 7000) + lowpass_filter_width (int, optional): + Integer that determines filter width of lowpass filter, more gives sharper filter. + (default: 1) + upsample_filter_width (int, optional): + Integer that determines filter width when upsampling NCCF. (default: 5) + max_frames_latency (int, optional): + Maximum number of frames of latency that we allow pitch tracking to introduce into + the feature processing (affects output only if ``frames_per_chunk > 0`` and + ``simulate_first_pass_online=True``) (default: 0) + frames_per_chunk (int, optional): + The number of frames used for energy normalization. (default: 0) + simulate_first_pass_online (bool, optional): + If true, the function will output features that correspond to what an online decoder + would see in the first pass of decoding -- not the final version of the features, + which is the default. (default: False) + Relevant if ``frames_per_chunk > 0``. + recompute_frame (int, optional): + Only relevant for compatibility with online pitch extraction. + A non-critical parameter; the frame at which we recompute some of the forward pointers, + after revising our estimate of the signal energy. + Relevant if ``frames_per_chunk > 0``. (default: 500) + snip_edges (bool, optional): + If this is set to false, the incomplete frames near the ending edge won't be snipped, + so that the number of frames is the file size divided by the frame-shift. + This makes different types of features give the same number of frames. (default: True) + + Returns: + Tensor: Pitch feature. Shape: ``(batch, frames 2)`` where the last dimension + corresponds to pitch and NCCF. + + Reference: + - A pitch extraction algorithm tuned for automatic speech recognition + + P. Ghahremani, B. BabaAli, D. Povey, K. Riedhammer, J. Trmal and S. Khudanpur + + 2014 IEEE International Conference on Acoustics, Speech and Signal Processing (ICASSP), + + Florence, 2014, pp. 2494-2498, doi: 10.1109/ICASSP.2014.6854049. + """ + shape = waveform.shape + waveform = waveform.reshape(-1, shape[-1]) + result = torch.ops.torchaudio.kaldi_ComputeKaldiPitch( + waveform, sample_rate, frame_length, frame_shift, + min_f0, max_f0, soft_min_f0, penalty_factor, lowpass_cutoff, + resample_frequency, delta_pitch, nccf_ballast, + lowpass_filter_width, upsample_filter_width, max_frames_latency, + frames_per_chunk, simulate_first_pass_online, recompute_frame, + snip_edges, + ) + result = result.reshape(shape[:-1] + result.shape[-2:]) + return result diff --git a/torchaudio/kaldi_io.py b/torchaudio/kaldi_io.py index 7f14f48e2c..ba1689da2b 100644 --- a/torchaudio/kaldi_io.py +++ b/torchaudio/kaldi_io.py @@ -57,7 +57,7 @@ def read_vec_int_ark(file_or_fd: Any) -> Iterable[Tuple[str, Tensor]]: >>> d = { u:d for u,d in torchaudio.kaldi_io.read_vec_int_ark(file) } """ # Requires convert_contiguous to be True because elements from int32 vector are - # sored in tuples: (sizeof(int32), value) so strides are (5,) instead of (4,) which will throw an error + # sorted in tuples: (sizeof(int32), value) so strides are (5,) instead of (4,) which will throw an error # in from_numpy as it expects strides to be a multiple of 4 (int32). return _convert_method_output_to_tensor(file_or_fd, kaldi_io.read_vec_int_ark, convert_contiguous=True) diff --git a/torchaudio/prototype/transducer.py b/torchaudio/prototype/transducer.py index 843cf5f9a4..99c1e9877e 100644 --- a/torchaudio/prototype/transducer.py +++ b/torchaudio/prototype/transducer.py @@ -19,7 +19,6 @@ def forward(ctx, acts, labels, act_lens, label_lens, blank, reduction): """ device = acts.device - check_inputs(acts, labels, act_lens, label_lens) acts = acts.to("cpu") labels = labels.to("cpu") @@ -118,45 +117,3 @@ def forward(self, acts, labels, act_lens, label_lens): # log_softmax is computed within GPU version. acts = torch.nn.functional.log_softmax(acts, -1) return self.loss(acts, labels, act_lens, label_lens, self.blank, self.reduction) - - -def check_type(var, t, name): - if var.dtype is not t: - raise TypeError("{} must be {}".format(name, t)) - - -def check_contiguous(var, name): - if not var.is_contiguous(): - raise ValueError("{} must be contiguous".format(name)) - - -def check_dim(var, dim, name): - if len(var.shape) != dim: - raise ValueError("{} must be {}D".format(name, dim)) - - -def check_inputs(log_probs, labels, lengths, label_lengths): - check_type(labels, torch.int32, "labels") - check_type(label_lengths, torch.int32, "label_lengths") - check_type(lengths, torch.int32, "lengths") - check_contiguous(log_probs, "log_probs") - check_contiguous(labels, "labels") - check_contiguous(label_lengths, "label_lengths") - check_contiguous(lengths, "lengths") - - if lengths.shape[0] != log_probs.shape[0]: - raise ValueError("must have a length per example.") - if label_lengths.shape[0] != log_probs.shape[0]: - raise ValueError("must have a label length per example.") - - check_dim(log_probs, 4, "log_probs") - check_dim(labels, 2, "labels") - check_dim(lengths, 1, "lengths") - check_dim(label_lengths, 1, "label_lengths") - max_T = torch.max(lengths) - max_U = torch.max(label_lengths) - T, U = log_probs.shape[1:3] - if T != max_T: - raise ValueError("Input length mismatch") - if U != max_U + 1: - raise ValueError("Output length mismatch") diff --git a/torchaudio/sox_effects/__init__.py b/torchaudio/sox_effects/__init__.py index b3e2708ad1..3c46cebdd2 100644 --- a/torchaudio/sox_effects/__init__.py +++ b/torchaudio/sox_effects/__init__.py @@ -8,7 +8,7 @@ ) -if _mod_utils.is_module_available('torchaudio._torchaudio'): +if _mod_utils.is_sox_available(): import atexit init_sox_effects() atexit.register(shutdown_sox_effects) diff --git a/torchaudio/sox_effects/sox_effects.py b/torchaudio/sox_effects/sox_effects.py index e183932788..26fc0659e6 100644 --- a/torchaudio/sox_effects/sox_effects.py +++ b/torchaudio/sox_effects/sox_effects.py @@ -8,7 +8,7 @@ from torchaudio.utils.sox_utils import list_effects -@_mod_utils.requires_module('torchaudio._torchaudio') +@_mod_utils.requires_sox() def init_sox_effects(): """Initialize resources required to use sox effects. @@ -23,7 +23,7 @@ def init_sox_effects(): torch.ops.torchaudio.sox_effects_initialize_sox_effects() -@_mod_utils.requires_module("torchaudio._torchaudio") +@_mod_utils.requires_sox() def shutdown_sox_effects(): """Clean up resources required to use sox effects. @@ -37,7 +37,7 @@ def shutdown_sox_effects(): torch.ops.torchaudio.sox_effects_shutdown_sox_effects() -@_mod_utils.requires_module('torchaudio._torchaudio') +@_mod_utils.requires_sox() def effect_names() -> List[str]: """Gets list of valid sox effect names @@ -51,7 +51,7 @@ def effect_names() -> List[str]: return list(list_effects().keys()) -@_mod_utils.requires_module('torchaudio._torchaudio') +@_mod_utils.requires_sox() def apply_effects_tensor( tensor: torch.Tensor, sample_rate: int, @@ -152,7 +152,7 @@ def apply_effects_tensor( tensor, sample_rate, effects, channels_first) -@_mod_utils.requires_module('torchaudio._torchaudio') +@_mod_utils.requires_sox() def apply_effects_file( path: str, effects: List[List[str]], @@ -173,14 +173,16 @@ def apply_effects_file( Args: path (path-like object or file-like object): Source of audio data. When the function is not compiled by TorchScript, - (e.g. ``torch.jit.script``), the following types are accepted; + (e.g. ``torch.jit.script``), the following types are accepted: + * ``path-like``: file path * ``file-like``: Object with ``read(size: int) -> bytes`` method, which returns byte string of at most ``size`` length. + When the function is compiled by TorchScript, only ``str`` type is allowed. - Note: - * This argument is intentionally annotated as ``str`` only for - TorchScript compiler compatibility. + + Note: This argument is intentionally annotated as ``str`` only for + TorchScript compiler compatibility. effects (List[List[str]]): List of effects. normalize (bool): When ``True``, this function always return ``float32``, and sample values are diff --git a/torchaudio/transforms.py b/torchaudio/transforms.py index af89d5b250..d57b3eb35c 100644 --- a/torchaudio/transforms.py +++ b/torchaudio/transforms.py @@ -71,7 +71,7 @@ def __init__(self, super(Spectrogram, self).__init__() self.n_fft = n_fft # number of FFT bins. the returned STFT result will have n_fft // 2 + 1 - # number of frequecies due to onesided=True in torch.stft + # number of frequencies due to onesided=True in torch.stft self.win_length = win_length if win_length is not None else n_fft self.hop_length = hop_length if hop_length is not None else self.win_length // 2 window = window_fn(self.win_length) if wkwargs is None else window_fn(self.win_length, **wkwargs) @@ -122,7 +122,6 @@ class GriffinLim(torch.nn.Module): that is applied/multiplied to each frame/window. (Default: ``torch.hann_window``) power (float, optional): Exponent for the magnitude spectrogram, (must be > 0) e.g., 1 for energy, 2 for power, etc. (Default: ``2``) - normalized (bool, optional): Whether to normalize by magnitude after stft. (Default: ``False``) wkwargs (dict or None, optional): Arguments for window function. (Default: ``None``) momentum (float, optional): The momentum parameter for fast Griffin-Lim. Setting this to 0 recovers the original Griffin-Lim method. @@ -158,7 +157,6 @@ def __init__(self, hop_length: Optional[int] = None, window_fn: Callable[..., Tensor] = torch.hann_window, power: float = 2., - normalized: bool = False, wkwargs: Optional[dict] = None, momentum: float = 0.99, length: Optional[int] = None, @@ -174,7 +172,6 @@ def __init__(self, self.hop_length = hop_length if hop_length is not None else self.win_length // 2 window = window_fn(self.win_length) if wkwargs is None else window_fn(self.win_length, **wkwargs) self.register_buffer('window', window) - self.normalized = normalized self.length = length self.power = power self.momentum = momentum / (1 + momentum) @@ -191,7 +188,7 @@ def forward(self, specgram: Tensor) -> Tensor: Tensor: waveform of (..., time), where time equals the ``length`` parameter if given. """ return F.griffinlim(specgram, self.window, self.n_fft, self.hop_length, self.win_length, self.power, - self.normalized, self.n_iter, self.momentum, self.length, self.rand_init) + self.n_iter, self.momentum, self.length, self.rand_init) class AmplitudeToDB(torch.nn.Module): @@ -249,6 +246,7 @@ class MelScale(torch.nn.Module): if None is given. See ``n_fft`` in :class:`Spectrogram`. (Default: ``None``) norm (Optional[str]): If 'slaney', divide the triangular mel weights by the width of the mel band (area normalization). (Default: ``None``) + mel_scale (str, optional): Scale to use: ``htk`` or ``slaney``. (Default: ``htk``) """ __constants__ = ['n_mels', 'sample_rate', 'f_min', 'f_max'] @@ -258,18 +256,21 @@ def __init__(self, f_min: float = 0., f_max: Optional[float] = None, n_stft: Optional[int] = None, - norm: Optional[str] = None) -> None: + norm: Optional[str] = None, + mel_scale: str = "htk") -> None: super(MelScale, self).__init__() self.n_mels = n_mels self.sample_rate = sample_rate self.f_max = f_max if f_max is not None else float(sample_rate // 2) self.f_min = f_min self.norm = norm + self.mel_scale = mel_scale assert f_min <= self.f_max, 'Require f_min: {} < f_max: {}'.format(f_min, self.f_max) fb = torch.empty(0) if n_stft is None else F.create_fb_matrix( - n_stft, self.f_min, self.f_max, self.n_mels, self.sample_rate, self.norm) + n_stft, self.f_min, self.f_max, self.n_mels, self.sample_rate, self.norm, + self.mel_scale) self.register_buffer('fb', fb) def forward(self, specgram: Tensor) -> Tensor: @@ -287,7 +288,8 @@ def forward(self, specgram: Tensor) -> Tensor: if self.fb.numel() == 0: tmp_fb = F.create_fb_matrix(specgram.size(1), self.f_min, self.f_max, - self.n_mels, self.sample_rate, self.norm) + self.n_mels, self.sample_rate, self.norm, + self.mel_scale) # Attributes cannot be reassigned outside __init__ so workaround self.fb.resize_(tmp_fb.size()) self.fb.copy_(tmp_fb) @@ -321,6 +323,7 @@ class InverseMelScale(torch.nn.Module): sgdargs (dict or None, optional): Arguments for the SGD optimizer. (Default: ``None``) norm (Optional[str]): If 'slaney', divide the triangular mel weights by the width of the mel band (area normalization). (Default: ``None``) + mel_scale (str, optional): Scale to use: ``htk`` or ``slaney``. (Default: ``htk``) """ __constants__ = ['n_stft', 'n_mels', 'sample_rate', 'f_min', 'f_max', 'max_iter', 'tolerance_loss', 'tolerance_change', 'sgdargs'] @@ -335,7 +338,8 @@ def __init__(self, tolerance_loss: float = 1e-5, tolerance_change: float = 1e-8, sgdargs: Optional[dict] = None, - norm: Optional[str] = None) -> None: + norm: Optional[str] = None, + mel_scale: str = "htk") -> None: super(InverseMelScale, self).__init__() self.n_mels = n_mels self.sample_rate = sample_rate @@ -348,7 +352,8 @@ def __init__(self, assert f_min <= self.f_max, 'Require f_min: {} < f_max: {}'.format(f_min, self.f_max) - fb = F.create_fb_matrix(n_stft, self.f_min, self.f_max, self.n_mels, self.sample_rate, norm) + fb = F.create_fb_matrix(n_stft, self.f_min, self.f_max, self.n_mels, self.sample_rate, norm, + mel_scale) self.register_buffer('fb', fb) def forward(self, melspec: Tensor) -> Tensor: @@ -427,6 +432,7 @@ class MelSpectrogram(torch.nn.Module): avoid redundancy. Default: ``True`` norm (Optional[str]): If 'slaney', divide the triangular mel weights by the width of the mel band (area normalization). (Default: ``None``) + mel_scale (str, optional): Scale to use: ``htk`` or ``slaney``. (Default: ``htk``) Example >>> waveform, sample_rate = torchaudio.load('test.wav', normalization=True) @@ -450,7 +456,8 @@ def __init__(self, center: bool = True, pad_mode: str = "reflect", onesided: bool = True, - norm: Optional[str] = None) -> None: + norm: Optional[str] = None, + mel_scale: str = "htk") -> None: super(MelSpectrogram, self).__init__() self.sample_rate = sample_rate self.n_fft = n_fft @@ -467,7 +474,15 @@ def __init__(self, pad=self.pad, window_fn=window_fn, power=self.power, normalized=self.normalized, wkwargs=wkwargs, center=center, pad_mode=pad_mode, onesided=onesided) - self.mel_scale = MelScale(self.n_mels, self.sample_rate, self.f_min, self.f_max, self.n_fft // 2 + 1, norm) + self.mel_scale = MelScale( + self.n_mels, + self.sample_rate, + self.f_min, + self.f_max, + self.n_fft // 2 + 1, + norm, + mel_scale + ) def forward(self, waveform: Tensor) -> Tensor: r""" @@ -547,8 +562,8 @@ def forward(self, waveform: Tensor) -> Tensor: else: mel_specgram = self.amplitude_to_DB(mel_specgram) - # (..., channel, n_mels, time).tranpose(...) dot (n_mels, n_mfcc) - # -> (..., channel, time, n_mfcc).tranpose(...) + # (..., channel, n_mels, time).transpose(...) dot (n_mels, n_mfcc) + # -> (..., channel, time, n_mfcc).transpose(...) mfcc = torch.matmul(mel_specgram.transpose(-2, -1), self.dct_mat).transpose(-2, -1) return mfcc diff --git a/torchaudio/utils/__init__.py b/torchaudio/utils/__init__.py index bc11f86893..578a51925a 100644 --- a/torchaudio/utils/__init__.py +++ b/torchaudio/utils/__init__.py @@ -1,9 +1,8 @@ from . import ( sox_utils, ) - from torchaudio._internal import module_utils as _mod_utils -if _mod_utils.is_module_available('torchaudio._torchaudio'): +if _mod_utils.is_sox_available(): sox_utils.set_verbosity(1) diff --git a/torchaudio/utils/sox_utils.py b/torchaudio/utils/sox_utils.py index 3f9ad0b5ec..ed576a83a3 100644 --- a/torchaudio/utils/sox_utils.py +++ b/torchaudio/utils/sox_utils.py @@ -1,13 +1,10 @@ from typing import List, Dict import torch +from torchaudio._internal import module_utils as _mod_utils -from torchaudio._internal import ( - module_utils as _mod_utils, -) - -@_mod_utils.requires_module('torchaudio._torchaudio') +@_mod_utils.requires_sox() def set_seed(seed: int): """Set libsox's PRNG @@ -20,7 +17,7 @@ def set_seed(seed: int): torch.ops.torchaudio.sox_utils_set_seed(seed) -@_mod_utils.requires_module('torchaudio._torchaudio') +@_mod_utils.requires_sox() def set_verbosity(verbosity: int): """Set libsox's verbosity @@ -38,7 +35,7 @@ def set_verbosity(verbosity: int): torch.ops.torchaudio.sox_utils_set_verbosity(verbosity) -@_mod_utils.requires_module('torchaudio._torchaudio') +@_mod_utils.requires_sox() def set_buffer_size(buffer_size: int): """Set buffer size for sox effect chain @@ -51,7 +48,7 @@ def set_buffer_size(buffer_size: int): torch.ops.torchaudio.sox_utils_set_buffer_size(buffer_size) -@_mod_utils.requires_module('torchaudio._torchaudio') +@_mod_utils.requires_sox() def set_use_threads(use_threads: bool): """Set multithread option for sox effect chain @@ -65,7 +62,7 @@ def set_use_threads(use_threads: bool): torch.ops.torchaudio.sox_utils_set_use_threads(use_threads) -@_mod_utils.requires_module('torchaudio._torchaudio') +@_mod_utils.requires_sox() def list_effects() -> Dict[str, str]: """List the available sox effect names @@ -75,7 +72,7 @@ def list_effects() -> Dict[str, str]: return dict(torch.ops.torchaudio.sox_utils_list_effects()) -@_mod_utils.requires_module('torchaudio._torchaudio') +@_mod_utils.requires_sox() def list_read_formats() -> List[str]: """List the supported audio formats for read @@ -85,7 +82,7 @@ def list_read_formats() -> List[str]: return torch.ops.torchaudio.sox_utils_list_read_formats() -@_mod_utils.requires_module('torchaudio._torchaudio') +@_mod_utils.requires_sox() def list_write_formats() -> List[str]: """List the supported audio formats for write From f88723cd3c1f5e30478a9d1d8d25f1b1e22863f3 Mon Sep 17 00:00:00 2001 From: Dmitry Polukhin Date: Tue, 30 Mar 2021 02:18:05 -0700 Subject: [PATCH 34/73] Fix broken list of checks (#1401) Summary: Pull Request resolved: https://github.com/pytorch/audio/pull/1401 Extra spaces broke list of checks. Reviewed By: mthrok Differential Revision: D27125520 fbshipit-source-id: 506924f9b73266b3f3ac174a020830f33b0c7489 --- .clang-tidy | 57 ++++++++++++++++++++++++++++------------------------- 1 file changed, 30 insertions(+), 27 deletions(-) diff --git a/.clang-tidy b/.clang-tidy index a3a40b5907..e2d7eb387d 100644 --- a/.clang-tidy +++ b/.clang-tidy @@ -1,32 +1,35 @@ --- -# NOTE there must be no spaces before the '-', so put the comma first. +# NOTE there must be no spaces before the '-' and check name. +# If you edit this list, please verify list of enabled check with +# clang-tidy --list-checks +InheritParentConfig: true Checks: ' - -* - ,bugprone-* - ,-bugprone-forward-declaration-namespace - ,-bugprone-macro-parentheses - ,cppcoreguidelines-* - ,-cppcoreguidelines-interfaces-global-init - ,-cppcoreguidelines-owning-memory - ,-cppcoreguidelines-pro-bounds-array-to-pointer-decay - ,-cppcoreguidelines-pro-bounds-constant-array-index - ,-cppcoreguidelines-pro-bounds-pointer-arithmetic - ,-cppcoreguidelines-pro-type-cstyle-cast - ,-cppcoreguidelines-pro-type-reinterpret-cast - ,-cppcoreguidelines-pro-type-static-cast-downcast - ,-cppcoreguidelines-pro-type-union-access - ,-cppcoreguidelines-pro-type-vararg - ,-cppcoreguidelines-special-member-functions - ,hicpp-exception-baseclass - ,hicpp-avoid-goto - ,modernize-* - ,-modernize-return-braced-init-list - ,-modernize-use-auto - ,-modernize-use-default-member-init - ,-modernize-use-using - ,performance-unnecessary-value-param - ' -WarningsAsErrors: '*' +bugprone-*, +-bugprone-forward-declaration-namespace, +-bugprone-macro-parentheses, +-clang-analyzer-*, +cppcoreguidelines-*, +-cppcoreguidelines-interfaces-global-init, +-cppcoreguidelines-owning-memory, +-cppcoreguidelines-pro-bounds-array-to-pointer-decay, +-cppcoreguidelines-pro-bounds-constant-array-index, +-cppcoreguidelines-pro-bounds-pointer-arithmetic, +-cppcoreguidelines-pro-type-cstyle-cast, +-cppcoreguidelines-pro-type-reinterpret-cast, +-cppcoreguidelines-pro-type-static-cast-downcast, +-cppcoreguidelines-pro-type-union-access, +-cppcoreguidelines-pro-type-vararg, +-cppcoreguidelines-special-member-functions, +-facebook-hte-RelativeInclude, +hicpp-exception-baseclass, +hicpp-avoid-goto, +modernize-*, +-modernize-return-braced-init-list, +-modernize-use-auto, +-modernize-use-default-member-init, +-modernize-use-using, +performance-unnecessary-value-param, +' HeaderFilterRegex: 'torchaudio/.*' AnalyzeTemporaryDtors: false CheckOptions: From d48089a05fef44aad03a0a9bc428d3c93ffac63d Mon Sep 17 00:00:00 2001 From: Parmeet Singh Bhatia Date: Wed, 31 Mar 2021 00:03:31 -0700 Subject: [PATCH 35/73] Import torchaudio #1412 c0bfb03 Summary: Import latest from github to fbcode Pass: 951 Skip: 19 Omit: 1 ListingSuccess: 26 Result available at: https://www.internalfb.com/intern/testinfra/testrun/8444249336935844 Reviewed By: mthrok Differential Revision: D27448988 fbshipit-source-id: 61f63ffa1295a31b4452abaf2c74ebfefb827dcf --- docs/source/functional.rst | 7 +- .../common_utils/__init__.py | 1 - .../common_utils/case_utils.py | 3 - .../compliance_kaldi_test.py | 3 +- .../functional/librosa_compatibility_test.py | 19 ++++ .../functional/sox_compatibility_test.py | 4 +- .../transforms/sox_compatibility_test.py | 14 ++- torchaudio/compliance/kaldi.py | 81 +------------- torchaudio/datasets/yesno.py | 4 +- torchaudio/functional/__init__.py | 4 +- torchaudio/functional/functional.py | 103 ++++++++++++++++++ torchaudio/transforms.py | 13 +-- 12 files changed, 153 insertions(+), 103 deletions(-) diff --git a/docs/source/functional.rst b/docs/source/functional.rst index e52e83ca42..98517929ea 100644 --- a/docs/source/functional.rst +++ b/docs/source/functional.rst @@ -55,7 +55,7 @@ apply_codec ----------- .. autofunction:: apply_codec - + :hidden:`Complex Utility` ~~~~~~~~~~~~~~~~~~~~~~~~~ @@ -230,3 +230,8 @@ vad --------------------------- .. autofunction:: spectral_centroid + +:hidden:`resample` +--------------------------- + +.. autofunction:: resample diff --git a/test/torchaudio_unittest/common_utils/__init__.py b/test/torchaudio_unittest/common_utils/__init__.py index 22cb18a08e..736ec82855 100644 --- a/test/torchaudio_unittest/common_utils/__init__.py +++ b/test/torchaudio_unittest/common_utils/__init__.py @@ -17,7 +17,6 @@ skipIfNoModule, skipIfNoKaldi, skipIfNoSox, - skipIfNoSoxBackend, ) from .wav_utils import ( get_wav_data, diff --git a/test/torchaudio_unittest/common_utils/case_utils.py b/test/torchaudio_unittest/common_utils/case_utils.py index 5d476072bb..69b9a795cd 100644 --- a/test/torchaudio_unittest/common_utils/case_utils.py +++ b/test/torchaudio_unittest/common_utils/case_utils.py @@ -7,7 +7,6 @@ import torch from torch.testing._internal.common_utils import TestCase as PytorchTestCase -import torchaudio from torchaudio._internal.module_utils import ( is_module_available, is_sox_available, @@ -96,8 +95,6 @@ def skipIfNoModule(module, display_name=None): return unittest.skipIf(not is_module_available(module), f'"{display_name}" is not available') -skipIfNoSoxBackend = unittest.skipIf( - 'sox' not in torchaudio.list_audio_backends(), 'Sox backend not available') skipIfNoCuda = unittest.skipIf(not torch.cuda.is_available(), reason='CUDA not available') skipIfNoSox = unittest.skipIf(not is_sox_available(), reason='Sox not available') skipIfNoKaldi = unittest.skipIf(not is_kaldi_available(), reason='Kaldi not available') diff --git a/test/torchaudio_unittest/compliance_kaldi_test.py b/test/torchaudio_unittest/compliance_kaldi_test.py index a98240a9b8..17d73fbf2f 100644 --- a/test/torchaudio_unittest/compliance_kaldi_test.py +++ b/test/torchaudio_unittest/compliance_kaldi_test.py @@ -47,7 +47,6 @@ def first_sample_of_frame(frame, window_size, window_shift, snip_edges): @common_utils.skipIfNoSox class Test_Kaldi(common_utils.TempDirMixin, common_utils.TorchaudioTestCase): - backend = 'sox_io' kaldi_output_dir = common_utils.get_asset_path('kaldi') test_filepath = common_utils.get_asset_path('kaldi_file.wav') @@ -113,7 +112,7 @@ def _create_data_set(self): # clear the last 16 bits because they aren't used anyways y = ((y >> 16) << 16).float() torchaudio.save(self.test_filepath, y, sr) - sound, sample_rate = torchaudio.load(self.test_filepath, normalization=False) + sound, sample_rate = common_utils.load_wav(self.test_filepath, normalize=False) print(y >> 16) self.assertTrue(sample_rate == sr) self.assertEqual(y, sound) diff --git a/test/torchaudio_unittest/functional/librosa_compatibility_test.py b/test/torchaudio_unittest/functional/librosa_compatibility_test.py index c88d9f3ccd..5905c239d3 100644 --- a/test/torchaudio_unittest/functional/librosa_compatibility_test.py +++ b/test/torchaudio_unittest/functional/librosa_compatibility_test.py @@ -109,6 +109,25 @@ def test_amplitude_to_DB(self): self.assertEqual(ta_out, lr_out, atol=5e-5, rtol=1e-5) + def test_resample(self): + input_path = common_utils.get_asset_path('sinewave.wav') + waveform, sample_rate = common_utils.load_wav(input_path) + + upsample_rate = sample_rate * 2 + downsample_rate = sample_rate // 2 + + ta_upsampled = F.resample(waveform, sample_rate, upsample_rate) + lr_upsampled = librosa.resample(waveform.squeeze(0).numpy(), sample_rate, upsample_rate) + lr_upsampled = torch.from_numpy(lr_upsampled).unsqueeze(0) + + self.assertEqual(ta_upsampled, lr_upsampled, atol=1e-2, rtol=1e-5) + + ta_downsampled = F.resample(waveform, sample_rate, downsample_rate) + lr_downsampled = librosa.resample(waveform.squeeze(0).numpy(), sample_rate, downsample_rate) + lr_downsampled = torch.from_numpy(lr_downsampled).unsqueeze(0) + + self.assertEqual(ta_downsampled, lr_downsampled, atol=1e-2, rtol=1e-5) + @unittest.skipIf(not LIBROSA_AVAILABLE, "Librosa not available") class TestPhaseVocoder(common_utils.TorchaudioTestCase): diff --git a/test/torchaudio_unittest/functional/sox_compatibility_test.py b/test/torchaudio_unittest/functional/sox_compatibility_test.py index 21f082683c..fe9744f22a 100644 --- a/test/torchaudio_unittest/functional/sox_compatibility_test.py +++ b/test/torchaudio_unittest/functional/sox_compatibility_test.py @@ -2,7 +2,7 @@ import torchaudio.functional as F from torchaudio_unittest.common_utils import ( - skipIfNoSoxBackend, + skipIfNoSox, skipIfNoExec, TempDirMixin, TorchaudioTestCase, @@ -14,7 +14,7 @@ ) -@skipIfNoSoxBackend +@skipIfNoSox @skipIfNoExec('sox') class TestFunctionalFiltering(TempDirMixin, TorchaudioTestCase): def run_sox_effect(self, input_file, effect): diff --git a/test/torchaudio_unittest/transforms/sox_compatibility_test.py b/test/torchaudio_unittest/transforms/sox_compatibility_test.py index 4bf6bf7884..81582c8393 100644 --- a/test/torchaudio_unittest/transforms/sox_compatibility_test.py +++ b/test/torchaudio_unittest/transforms/sox_compatibility_test.py @@ -2,17 +2,19 @@ from parameterized import parameterized from torchaudio_unittest.common_utils import ( - skipIfNoSoxBackend, + skipIfNoSox, skipIfNoExec, TempDirMixin, TorchaudioTestCase, get_asset_path, sox_utils, load_wav, + save_wav, + get_whitenoise, ) -@skipIfNoSoxBackend +@skipIfNoSox @skipIfNoExec('sox') class TestFunctionalFiltering(TempDirMixin, TorchaudioTestCase): def run_sox_effect(self, input_file, effect): @@ -24,6 +26,14 @@ def assert_sox_effect(self, result, input_path, effects, atol=1e-04, rtol=1e-5): expected, _ = self.run_sox_effect(input_path, effects) self.assertEqual(result, expected, atol=atol, rtol=rtol) + def get_whitenoise(self, sample_rate=8000): + noise = get_whitenoise( + sample_rate=sample_rate, duration=3, scale_factor=0.9, + ) + path = self.get_temp_path("whitenoise.wav") + save_wav(path, noise, sample_rate) + return noise, path + @parameterized.expand([ ('q', 'quarter_sine'), ('h', 'half_sine'), diff --git a/torchaudio/compliance/kaldi.py b/torchaudio/compliance/kaldi.py index f1e1ddf5b5..a5c3354c9b 100644 --- a/torchaudio/compliance/kaldi.py +++ b/torchaudio/compliance/kaldi.py @@ -3,7 +3,6 @@ import math import torch from torch import Tensor -from torch.nn import functional as F import torchaudio import torchaudio._internal.fft @@ -753,71 +752,16 @@ def mfcc( return feature -def _get_sinc_resample_kernel(orig_freq: int, new_freq: int, lowpass_filter_width: int, - device: torch.device, dtype: torch.dtype): - assert lowpass_filter_width > 0 - kernels = [] - base_freq = min(orig_freq, new_freq) - # This will perform antialiasing filtering by removing the highest frequencies. - # At first I thought I only needed this when downsampling, but when upsampling - # you will get edge artifacts without this, as the edge is equivalent to zero padding, - # which will add high freq artifacts. - base_freq *= 0.99 - - # The key idea of the algorithm is that x(t) can be exactly reconstructed from x[i] (tensor) - # using the sinc interpolation formula: - # x(t) = sum_i x[i] sinc(pi * orig_freq * (i / orig_freq - t)) - # We can then sample the function x(t) with a different sample rate: - # y[j] = x(j / new_freq) - # or, - # y[j] = sum_i x[i] sinc(pi * orig_freq * (i / orig_freq - j / new_freq)) - - # We see here that y[j] is the convolution of x[i] with a specific filter, for which - # we take an FIR approximation, stopping when we see at least `lowpass_filter_width` zeros crossing. - # But y[j+1] is going to have a different set of weights and so on, until y[j + new_freq]. - # Indeed: - # y[j + new_freq] = sum_i x[i] sinc(pi * orig_freq * ((i / orig_freq - (j + new_freq) / new_freq)) - # = sum_i x[i] sinc(pi * orig_freq * ((i - orig_freq) / orig_freq - j / new_freq)) - # = sum_i x[i + orig_freq] sinc(pi * orig_freq * (i / orig_freq - j / new_freq)) - # so y[j+new_freq] uses the same filter as y[j], but on a shifted version of x by `orig_freq`. - # This will explain the F.conv1d after, with a stride of orig_freq. - width = math.ceil(lowpass_filter_width * orig_freq / base_freq) - # If orig_freq is still big after GCD reduction, most filters will be very unbalanced, i.e., - # they will have a lot of almost zero values to the left or to the right... - # There is probably a way to evaluate those filters more efficiently, but this is kept for - # future work. - idx = torch.arange(-width, width + orig_freq, device=device, dtype=dtype) - - for i in range(new_freq): - t = (-i / new_freq + idx / orig_freq) * base_freq - t = t.clamp_(-lowpass_filter_width, lowpass_filter_width) - t *= math.pi - # we do not use torch.hann_window here as we need to evaluate the window - # at specific positions, not over a regular grid. - window = torch.cos(t / lowpass_filter_width / 2)**2 - kernel = torch.where(t == 0, torch.tensor(1.).to(t), torch.sin(t) / t) - kernel.mul_(window) - kernels.append(kernel) - - scale = base_freq / orig_freq - return torch.stack(kernels).view(new_freq, 1, -1).mul_(scale), width - - def resample_waveform(waveform: Tensor, orig_freq: float, new_freq: float, lowpass_filter_width: int = 6) -> Tensor: - r"""Resamples the waveform at the new frequency. This matches Kaldi's OfflineFeatureTpl ResampleWaveform - which uses a LinearResample (resample a signal at linearly spaced intervals to upsample/downsample - a signal). LinearResample (LR) means that the output signal is at linearly spaced intervals (i.e - the output signal has a frequency of ``new_freq``). It uses sinc/bandlimited interpolation to - upsample/downsample the signal. + r"""Resamples the waveform at the new frequency. - https://ccrma.stanford.edu/~jos/resample/Theory_Ideal_Bandlimited_Interpolation.html - https://github.com/kaldi-asr/kaldi/blob/master/src/feat/resample.h#L56 + This is a wrapper around ``torchaudio.functional.resample``. Args: - waveform (Tensor): The input signal of size (c, n) + waveform (Tensor): The input signal of size (..., time) orig_freq (float): The original frequency of the signal new_freq (float): The desired frequency lowpass_filter_width (int, optional): Controls the sharpness of the filter, more == sharper @@ -826,21 +770,4 @@ def resample_waveform(waveform: Tensor, Returns: Tensor: The waveform at the new frequency """ - assert waveform.dim() == 2 - assert orig_freq > 0.0 and new_freq > 0.0 - - orig_freq = int(orig_freq) - new_freq = int(new_freq) - gcd = math.gcd(orig_freq, new_freq) - orig_freq = orig_freq // gcd - new_freq = new_freq // gcd - - kernel, width = _get_sinc_resample_kernel(orig_freq, new_freq, lowpass_filter_width, - waveform.device, waveform.dtype) - - num_wavs, length = waveform.shape - waveform = F.pad(waveform, (width, width + orig_freq)) - resampled = F.conv1d(waveform[:, None], kernel, stride=orig_freq) - resampled = resampled.transpose(1, 2).reshape(num_wavs, -1) - target_length = int(math.ceil(new_freq * length / orig_freq)) - return resampled[..., :target_length] + return torchaudio.functional.resample(waveform, orig_freq, new_freq, lowpass_filter_width) diff --git a/torchaudio/datasets/yesno.py b/torchaudio/datasets/yesno.py index 6d0d2c0a5f..10b38a1260 100644 --- a/torchaudio/datasets/yesno.py +++ b/torchaudio/datasets/yesno.py @@ -16,7 +16,7 @@ "release1": { "folder_in_archive": "waves_yesno", "url": "http://www.openslr.org/resources/1/waves_yesno.tar.gz", - "checksum": "30301975fd8c5cac4040c261c0852f57cfa8adbbad2ce78e77e4986957445f27", + "checksum": "c3f49e0cca421f96b75b41640749167b52118f232498667ca7a5f9416aef8e73", } } @@ -54,7 +54,7 @@ def _parse_filesystem(self, root: str, url: str, folder_in_archive: str, downloa if not os.path.isdir(self._path): if not os.path.isfile(archive): checksum = _RELEASE_CONFIGS["release1"]["checksum"] - download_url(url, root, hash_value=checksum, hash_type="md5") + download_url(url, root, hash_value=checksum) extract_archive(archive) if not os.path.isdir(self._path): diff --git a/torchaudio/functional/__init__.py b/torchaudio/functional/__init__.py index 88fc4d545f..39f2fb8f53 100644 --- a/torchaudio/functional/__init__.py +++ b/torchaudio/functional/__init__.py @@ -19,6 +19,7 @@ spectrogram, spectral_centroid, apply_codec, + resample, ) from .filtering import ( allpass_biquad, @@ -85,5 +86,6 @@ 'riaa_biquad', 'treble_biquad', 'vad', - 'apply_codec' + 'apply_codec', + 'resample', ] diff --git a/torchaudio/functional/functional.py b/torchaudio/functional/functional.py index b114b9aacf..73496bf4cc 100644 --- a/torchaudio/functional/functional.py +++ b/torchaudio/functional/functional.py @@ -33,6 +33,7 @@ 'sliding_window_cmn', "spectral_centroid", "apply_codec", + "resample", ] @@ -1209,3 +1210,105 @@ def compute_kaldi_pitch( ) result = result.reshape(shape[:-1] + result.shape[-2:]) return result + + +def _get_sinc_resample_kernel(orig_freq: int, new_freq: int, lowpass_filter_width: int, + device: torch.device, dtype: torch.dtype): + assert lowpass_filter_width > 0 + kernels = [] + base_freq = min(orig_freq, new_freq) + # This will perform antialiasing filtering by removing the highest frequencies. + # At first I thought I only needed this when downsampling, but when upsampling + # you will get edge artifacts without this, as the edge is equivalent to zero padding, + # which will add high freq artifacts. + base_freq *= 0.99 + + # The key idea of the algorithm is that x(t) can be exactly reconstructed from x[i] (tensor) + # using the sinc interpolation formula: + # x(t) = sum_i x[i] sinc(pi * orig_freq * (i / orig_freq - t)) + # We can then sample the function x(t) with a different sample rate: + # y[j] = x(j / new_freq) + # or, + # y[j] = sum_i x[i] sinc(pi * orig_freq * (i / orig_freq - j / new_freq)) + + # We see here that y[j] is the convolution of x[i] with a specific filter, for which + # we take an FIR approximation, stopping when we see at least `lowpass_filter_width` zeros crossing. + # But y[j+1] is going to have a different set of weights and so on, until y[j + new_freq]. + # Indeed: + # y[j + new_freq] = sum_i x[i] sinc(pi * orig_freq * ((i / orig_freq - (j + new_freq) / new_freq)) + # = sum_i x[i] sinc(pi * orig_freq * ((i - orig_freq) / orig_freq - j / new_freq)) + # = sum_i x[i + orig_freq] sinc(pi * orig_freq * (i / orig_freq - j / new_freq)) + # so y[j+new_freq] uses the same filter as y[j], but on a shifted version of x by `orig_freq`. + # This will explain the F.conv1d after, with a stride of orig_freq. + width = math.ceil(lowpass_filter_width * orig_freq / base_freq) + # If orig_freq is still big after GCD reduction, most filters will be very unbalanced, i.e., + # they will have a lot of almost zero values to the left or to the right... + # There is probably a way to evaluate those filters more efficiently, but this is kept for + # future work. + idx = torch.arange(-width, width + orig_freq, device=device, dtype=dtype) + + for i in range(new_freq): + t = (-i / new_freq + idx / orig_freq) * base_freq + t = t.clamp_(-lowpass_filter_width, lowpass_filter_width) + t *= math.pi + # we do not use torch.hann_window here as we need to evaluate the window + # at specific positions, not over a regular grid. + window = torch.cos(t / lowpass_filter_width / 2)**2 + kernel = torch.where(t == 0, torch.tensor(1.).to(t), torch.sin(t) / t) + kernel.mul_(window) + kernels.append(kernel) + + scale = base_freq / orig_freq + return torch.stack(kernels).view(new_freq, 1, -1).mul_(scale), width + + +def resample( + waveform: Tensor, + orig_freq: float, + new_freq: float, + lowpass_filter_width: int = 6 +) -> Tensor: + r"""Resamples the waveform at the new frequency. This matches Kaldi's OfflineFeatureTpl ResampleWaveform + which uses a LinearResample (resample a signal at linearly spaced intervals to upsample/downsample + a signal). LinearResample (LR) means that the output signal is at linearly spaced intervals (i.e + the output signal has a frequency of ``new_freq``). It uses sinc/bandlimited interpolation to + upsample/downsample the signal. + + https://ccrma.stanford.edu/~jos/resample/Theory_Ideal_Bandlimited_Interpolation.html + https://github.com/kaldi-asr/kaldi/blob/master/src/feat/resample.h#L56 + + Args: + waveform (Tensor): The input signal of dimension (..., time) + orig_freq (float): The original frequency of the signal + new_freq (float): The desired frequency + lowpass_filter_width (int, optional): Controls the sharpness of the filter, more == sharper + but less efficient. We suggest around 4 to 10 for normal use. (Default: ``6``) + + Returns: + Tensor: The waveform at the new frequency of dimension (..., time). + """ + # pack batch + shape = waveform.size() + waveform = waveform.view(-1, shape[-1]) + + assert orig_freq > 0.0 and new_freq > 0.0 + + orig_freq = int(orig_freq) + new_freq = int(new_freq) + gcd = math.gcd(orig_freq, new_freq) + orig_freq = orig_freq // gcd + new_freq = new_freq // gcd + + kernel, width = _get_sinc_resample_kernel(orig_freq, new_freq, lowpass_filter_width, + waveform.device, waveform.dtype) + + num_wavs, length = waveform.shape + waveform = torch.nn.functional.pad(waveform, (width, width + orig_freq)) + resampled = torch.nn.functional.conv1d(waveform[:, None], kernel, stride=orig_freq) + resampled = resampled.transpose(1, 2).reshape(num_wavs, -1) + target_length = int(math.ceil(new_freq * length / orig_freq)) + resampled = resampled[..., :target_length] + + # unpack batch + resampled = resampled.view(shape[:-1] + resampled.shape[-1:]) + return resampled diff --git a/torchaudio/transforms.py b/torchaudio/transforms.py index d57b3eb35c..6f3ea1b6e1 100644 --- a/torchaudio/transforms.py +++ b/torchaudio/transforms.py @@ -6,7 +6,6 @@ import torch from torch import Tensor from torchaudio import functional as F -from torchaudio.compliance import kaldi __all__ = [ @@ -649,17 +648,7 @@ def forward(self, waveform: Tensor) -> Tensor: Tensor: Output signal of dimension (..., time). """ if self.resampling_method == 'sinc_interpolation': - - # pack batch - shape = waveform.size() - waveform = waveform.view(-1, shape[-1]) - - waveform = kaldi.resample_waveform(waveform, self.orig_freq, self.new_freq) - - # unpack batch - waveform = waveform.view(shape[:-1] + waveform.shape[-1:]) - - return waveform + return F.resample(waveform, self.orig_freq, self.new_freq) raise ValueError('Invalid resampling method: {}'.format(self.resampling_method)) From 561f357d76aecf80b74639ce65ed6a65c1ebdbec Mon Sep 17 00:00:00 2001 From: Christian Puhrsch Date: Fri, 2 Apr 2021 10:47:25 -0700 Subject: [PATCH 36/73] fbshipit-source-id: 5ee15b601a9c5c08836e4a7198401d54aa50aa3f --- test/torchscript_bc_test/assets/.gitignore | 1 - 1 file changed, 1 deletion(-) delete mode 100644 test/torchscript_bc_test/assets/.gitignore diff --git a/test/torchscript_bc_test/assets/.gitignore b/test/torchscript_bc_test/assets/.gitignore deleted file mode 100644 index 72e8ffc0db..0000000000 --- a/test/torchscript_bc_test/assets/.gitignore +++ /dev/null @@ -1 +0,0 @@ -* From 5b7417bc6085d1677ea4b07dc11ccb2ec31289d0 Mon Sep 17 00:00:00 2001 From: Moto Hira Date: Thu, 15 Apr 2021 17:57:24 -0700 Subject: [PATCH 37/73] Import torchaudio #1420 ad534c1 Summary: Import torchaudio from github Reviewed By: carolineechen Differential Revision: D27770998 fbshipit-source-id: 0b4a4a143769ae49cc30478dd9f8e075594074e8 --- .circleci/regenerate.py | 3 +- .circleci/unittest/linux/scripts/run_test.sh | 4 +- .github/workflows/bandit.yml | 23 ++ .github/workflows/codeql.yml | 43 +++ CMakeLists.txt | 8 + README.md | 9 + build_tools/setup_helpers/extension.py | 2 + cmake/LoadHIP.cmake | 234 +++++++++++++++++ .../backend/soundfile/save_test.py | 2 + .../common_utils/__init__.py | 32 ++- .../common_utils/case_utils.py | 2 + .../common_utils/data_utils.py | 44 +++- .../common_utils/parameterized_utils.py | 54 +++- .../functional/autograd_impl.py | 184 +++++++++++-- .../functional/batch_consistency_test.py | 16 -- .../functional/functional_cpu_test.py | 20 +- .../functional/functional_cuda_test.py | 20 +- .../functional/functional_impl.py | 52 +++- .../librosa_compatibility_cpu_test.py | 10 + .../librosa_compatibility_cuda_test.py | 12 + .../functional/librosa_compatibility_test.py | 174 ------------- .../librosa_compatibility_test_impl.py | 161 ++++++++++++ .../torchscript_consistency_cpu_test.py | 14 +- .../torchscript_consistency_cuda_test.py | 16 +- .../torchscript_consistency_impl.py | 68 +++-- .../transforms/autograd_cpu_test.py | 6 + .../transforms/autograd_cuda_test.py | 10 + .../transforms/autograd_test_impl.py | 183 +++++++++++++ .../transforms/batch_consistency_test.py | 36 +-- .../librosa_compatibility_cpu_test.py | 9 + .../librosa_compatibility_cuda_test.py | 10 + .../transforms/librosa_compatibility_test.py | 245 ------------------ .../librosa_compatibility_test_impl.py | 141 ++++++++++ .../torchscript_consistency_cpu_test.py | 14 +- .../torchscript_consistency_cuda_test.py | 16 +- .../torchscript_consistency_impl.py | 66 ++++- .../transforms/transforms_cpu_test.py | 14 + .../transforms/transforms_cuda_test.py | 19 ++ .../transforms/transforms_test_impl.py | 61 +++++ torchaudio/datasets/utils.py | 3 +- torchaudio/functional/filtering.py | 184 ++++++++----- torchaudio/functional/functional.py | 183 +++++++++---- torchaudio/transforms.py | 40 +-- 43 files changed, 1747 insertions(+), 700 deletions(-) create mode 100644 .github/workflows/bandit.yml create mode 100644 .github/workflows/codeql.yml create mode 100644 cmake/LoadHIP.cmake create mode 100644 test/torchaudio_unittest/functional/librosa_compatibility_cpu_test.py create mode 100644 test/torchaudio_unittest/functional/librosa_compatibility_cuda_test.py delete mode 100644 test/torchaudio_unittest/functional/librosa_compatibility_test.py create mode 100644 test/torchaudio_unittest/functional/librosa_compatibility_test_impl.py create mode 100644 test/torchaudio_unittest/transforms/autograd_cpu_test.py create mode 100644 test/torchaudio_unittest/transforms/autograd_cuda_test.py create mode 100644 test/torchaudio_unittest/transforms/autograd_test_impl.py create mode 100644 test/torchaudio_unittest/transforms/librosa_compatibility_cpu_test.py create mode 100644 test/torchaudio_unittest/transforms/librosa_compatibility_cuda_test.py delete mode 100644 test/torchaudio_unittest/transforms/librosa_compatibility_test.py create mode 100644 test/torchaudio_unittest/transforms/librosa_compatibility_test_impl.py create mode 100644 test/torchaudio_unittest/transforms/transforms_cpu_test.py create mode 100644 test/torchaudio_unittest/transforms/transforms_cuda_test.py create mode 100644 test/torchaudio_unittest/transforms/transforms_test_impl.py diff --git a/.circleci/regenerate.py b/.circleci/regenerate.py index 0985c1f9f6..137fed87c4 100755 --- a/.circleci/regenerate.py +++ b/.circleci/regenerate.py @@ -15,6 +15,7 @@ """ import jinja2 +from jinja2 import select_autoescape import yaml import os.path @@ -213,7 +214,7 @@ def unittest_workflows(indentation=6): env = jinja2.Environment( loader=jinja2.FileSystemLoader(d), lstrip_blocks=True, - autoescape=False, + autoescape=select_autoescape(enabled_extensions=('html', 'xml')), ) with open(os.path.join(d, 'config.yml'), 'w') as f: diff --git a/.circleci/unittest/linux/scripts/run_test.sh b/.circleci/unittest/linux/scripts/run_test.sh index cbd96f79a8..e083743630 100755 --- a/.circleci/unittest/linux/scripts/run_test.sh +++ b/.circleci/unittest/linux/scripts/run_test.sh @@ -11,9 +11,7 @@ case "$(uname -s)" in esac python -m torch.utils.collect_env -if [ "${os}" == Linux ]; then - cat /proc/cpuinfo -fi + export TORCHAUDIO_TEST_FAIL_IF_NO_EXTENSION=1 export PATH="${PWD}/third_party/install/bin/:${PATH}" diff --git a/.github/workflows/bandit.yml b/.github/workflows/bandit.yml new file mode 100644 index 0000000000..93bae80f9b --- /dev/null +++ b/.github/workflows/bandit.yml @@ -0,0 +1,23 @@ +# GitHub Actions Bandit Workflow + +name: Bandit + +on: + pull_request: + branches: [ master ] + + workflow_dispatch: + +jobs: + build: + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@v2 + + # Task will fail if any high-severity issues are found + # Ignoring submodules + - name: Run Bandit Security Analysis + run: | + python -m pip install bandit + python -m bandit -r . -x ./third_party -lll diff --git a/.github/workflows/codeql.yml b/.github/workflows/codeql.yml new file mode 100644 index 0000000000..f0ea58f309 --- /dev/null +++ b/.github/workflows/codeql.yml @@ -0,0 +1,43 @@ +# GitHub Actions CodeQL Workflow + +name: CodeQL + +on: + pull_request: + branches: [ master ] + + workflow_dispatch: + +jobs: + build: + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@v2 + + - name: Initialize CodeQL + uses: github/codeql-action/init@v1 + with: + languages: python, cpp + + - name: Install Ninja + run: | + sudo apt-get update -y + sudo apt-get install -y ninja-build + + - name: Update submodules + run: git submodule update --init --recursive + + - name: Install Torch + run: | + python -m pip install cmake + python -m pip install torch==1.8.1+cpu -f https://download.pytorch.org/whl/torch_stable.html + sudo ln -s /usr/bin/ninja /usr/bin/ninja-build + + - name: Build TorchAudio + run: BUILD_SOX=1 USE_CUDA=0 python setup.py develop --user + + # If any code scanning alerts are found, they will be under Security -> CodeQL + # Link: https://github.com/pytorch/audio/security/code-scanning + - name: Perform CodeQL Analysis + uses: github/codeql-action/analyze@v1 diff --git a/CMakeLists.txt b/CMakeLists.txt index 87abef1262..96360532f2 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -18,6 +18,14 @@ endif() project(torchaudio) +# Find the HIP package, set the HIP paths, load the HIP CMake. +if(USE_ROCM) + include(cmake/LoadHIP.cmake) + if(NOT PYTORCH_FOUND_HIP) + set(USE_ROCM OFF) + endif() +endif() + # check and set CMAKE_CXX_STANDARD string(FIND "${CMAKE_CXX_FLAGS}" "-std=c++" env_cxx_standard) if(env_cxx_standard GREATER -1) diff --git a/README.md b/README.md index 2cff4bf076..820301c041 100644 --- a/README.md +++ b/README.md @@ -93,6 +93,15 @@ BUILD_SOX=1 python setup.py install # OSX BUILD_SOX=1 MACOSX_DEPLOYMENT_TARGET=10.9 CC=clang CXX=clang++ python setup.py install + +# Windows +# We need to use the MSVC x64 toolset for compilation, with Visual Studio's vcvarsall.bat or directly with vcvars64.bat. +# These batch files are under Visual Studio's installation folder, under 'VC\Auxiliary\Build\'. +# More information available at: +# https://docs.microsoft.com/en-us/cpp/build/how-to-enable-a-64-bit-visual-cpp-toolset-on-the-command-line?view=msvc-160#use-vcvarsallbat-to-set-a-64-bit-hosted-build-architecture +call "C:\Program Files (x86)\Microsoft Visual Studio\2019\Community\VC\Auxiliary\Build\vcvarsall.bat" x64 && set BUILD_SOX=0 && python setup.py install +# or +call "C:\Program Files (x86)\Microsoft Visual Studio\2019\Community\VC\Auxiliary\Build\vcvars64.bat" && set BUILD_SOX=0 && python setup.py install ``` This is known to work on linux and unix distributions such as Ubuntu and CentOS 7 and macOS. diff --git a/build_tools/setup_helpers/extension.py b/build_tools/setup_helpers/extension.py index 4e04097716..430ff168c3 100644 --- a/build_tools/setup_helpers/extension.py +++ b/build_tools/setup_helpers/extension.py @@ -37,6 +37,7 @@ def _get_build(var, default=False): _BUILD_SOX = False if platform.system() == 'Windows' else _get_build("BUILD_SOX") _BUILD_KALDI = False if platform.system() == 'Windows' else _get_build("BUILD_KALDI", True) _BUILD_TRANSDUCER = _get_build("BUILD_TRANSDUCER") +_USE_ROCM = _get_build("USE_ROCM") def get_ext_modules(): @@ -74,6 +75,7 @@ def build_extension(self, ext): f"-DBUILD_TRANSDUCER:BOOL={'ON' if _BUILD_TRANSDUCER else 'OFF'}", "-DBUILD_TORCHAUDIO_PYTHON_EXTENSION:BOOL=ON", "-DBUILD_LIBTORCHAUDIO:BOOL=OFF", + f"-DUSE_ROCM:BOOL={'ON' if _USE_ROCM else 'OFF'}", ] build_args = [ '--target', 'install' diff --git a/cmake/LoadHIP.cmake b/cmake/LoadHIP.cmake new file mode 100644 index 0000000000..09ae6385cf --- /dev/null +++ b/cmake/LoadHIP.cmake @@ -0,0 +1,234 @@ +set(PYTORCH_FOUND_HIP FALSE) + +if(NOT DEFINED ENV{ROCM_PATH}) + set(ROCM_PATH /opt/rocm) +else() + set(ROCM_PATH $ENV{ROCM_PATH}) +endif() + +# HIP_PATH +if(NOT DEFINED ENV{HIP_PATH}) + set(HIP_PATH ${ROCM_PATH}/hip) +else() + set(HIP_PATH $ENV{HIP_PATH}) +endif() + +if(NOT EXISTS ${HIP_PATH}) + return() +endif() + +# HCC_PATH +if(NOT DEFINED ENV{HCC_PATH}) + set(HCC_PATH ${ROCM_PATH}/hcc) +else() + set(HCC_PATH $ENV{HCC_PATH}) +endif() + +# HSA_PATH +if(NOT DEFINED ENV{HSA_PATH}) + set(HSA_PATH ${ROCM_PATH}/hsa) +else() + set(HSA_PATH $ENV{HSA_PATH}) +endif() + +# ROCBLAS_PATH +if(NOT DEFINED ENV{ROCBLAS_PATH}) + set(ROCBLAS_PATH ${ROCM_PATH}/rocblas) +else() + set(ROCBLAS_PATH $ENV{ROCBLAS_PATH}) +endif() + +# ROCFFT_PATH +if(NOT DEFINED ENV{ROCFFT_PATH}) + set(ROCFFT_PATH ${ROCM_PATH}/rocfft) +else() + set(ROCFFT_PATH $ENV{ROCFFT_PATH}) +endif() + +# HIPFFT_PATH +if(NOT DEFINED ENV{HIPFFT_PATH}) + set(HIPFFT_PATH ${ROCM_PATH}/hipfft) +else() + set(HIPFFT_PATH $ENV{HIPFFT_PATH}) +endif() + +# HIPSPARSE_PATH +if(NOT DEFINED ENV{HIPSPARSE_PATH}) + set(HIPSPARSE_PATH ${ROCM_PATH}/hipsparse) +else() + set(HIPSPARSE_PATH $ENV{HIPSPARSE_PATH}) +endif() + +# THRUST_PATH +if(DEFINED ENV{THRUST_PATH}) + set(THRUST_PATH $ENV{THRUST_PATH}) +else() + set(THRUST_PATH ${ROCM_PATH}/include) +endif() + +# HIPRAND_PATH +if(NOT DEFINED ENV{HIPRAND_PATH}) + set(HIPRAND_PATH ${ROCM_PATH}/hiprand) +else() + set(HIPRAND_PATH $ENV{HIPRAND_PATH}) +endif() + +# ROCRAND_PATH +if(NOT DEFINED ENV{ROCRAND_PATH}) + set(ROCRAND_PATH ${ROCM_PATH}/rocrand) +else() + set(ROCRAND_PATH $ENV{ROCRAND_PATH}) +endif() + +# MIOPEN_PATH +if(NOT DEFINED ENV{MIOPEN_PATH}) + set(MIOPEN_PATH ${ROCM_PATH}/miopen) +else() + set(MIOPEN_PATH $ENV{MIOPEN_PATH}) +endif() + +# RCCL_PATH +if(NOT DEFINED ENV{RCCL_PATH}) + set(RCCL_PATH ${ROCM_PATH}/rccl) +else() + set(RCCL_PATH $ENV{RCCL_PATH}) +endif() + +# ROCPRIM_PATH +if(NOT DEFINED ENV{ROCPRIM_PATH}) + set(ROCPRIM_PATH ${ROCM_PATH}/rocprim) +else() + set(ROCPRIM_PATH $ENV{ROCPRIM_PATH}) +endif() + +# HIPCUB_PATH +if(NOT DEFINED ENV{HIPCUB_PATH}) + set(HIPCUB_PATH ${ROCM_PATH}/hipcub) +else() + set(HIPCUB_PATH $ENV{HIPCUB_PATH}) +endif() + +# ROCTHRUST_PATH +if(NOT DEFINED ENV{ROCTHRUST_PATH}) + set(ROCTHRUST_PATH ${ROCM_PATH}/rocthrust) +else() + set(ROCTHRUST_PATH $ENV{ROCTHRUST_PATH}) +endif() + +# ROCTRACER_PATH +if(NOT DEFINED ENV{ROCTRACER_PATH}) + set(ROCTRACER_PATH ${ROCM_PATH}/roctracer) +else() + set(ROCTRACER_PATH $ENV{ROCTRACER_PATH}) +endif() + +if(NOT DEFINED ENV{PYTORCH_ROCM_ARCH}) + set(PYTORCH_ROCM_ARCH gfx803;gfx900;gfx906;gfx908) +else() + set(PYTORCH_ROCM_ARCH $ENV{PYTORCH_ROCM_ARCH}) +endif() + +# Add HIP to the CMAKE Module Path +set(CMAKE_MODULE_PATH ${HIP_PATH}/cmake ${CMAKE_MODULE_PATH}) + +# Disable Asserts In Code (Can't use asserts on HIP stack.) +add_definitions(-DNDEBUG) + +macro(find_package_and_print_version PACKAGE_NAME) + find_package("${PACKAGE_NAME}" ${ARGN}) + message("${PACKAGE_NAME} VERSION: ${${PACKAGE_NAME}_VERSION}") +endmacro() + +# Find the HIP Package +find_package_and_print_version(HIP 1.0) + +if(HIP_FOUND) + set(PYTORCH_FOUND_HIP TRUE) + + # Find ROCM version for checks + file(READ "${ROCM_PATH}/.info/version-dev" ROCM_VERSION_DEV_RAW) + string(REGEX MATCH "^([0-9]+)\.([0-9]+)\.([0-9]+)-.*$" ROCM_VERSION_DEV_MATCH ${ROCM_VERSION_DEV_RAW}) + if(ROCM_VERSION_DEV_MATCH) + set(ROCM_VERSION_DEV_MAJOR ${CMAKE_MATCH_1}) + set(ROCM_VERSION_DEV_MINOR ${CMAKE_MATCH_2}) + set(ROCM_VERSION_DEV_PATCH ${CMAKE_MATCH_3}) + set(ROCM_VERSION_DEV "${ROCM_VERSION_DEV_MAJOR}.${ROCM_VERSION_DEV_MINOR}.${ROCM_VERSION_DEV_PATCH}") + endif() + message("\n***** ROCm version from ${ROCM_PATH}/.info/version-dev ****\n") + message("ROCM_VERSION_DEV: ${ROCM_VERSION_DEV}") + message("ROCM_VERSION_DEV_MAJOR: ${ROCM_VERSION_DEV_MAJOR}") + message("ROCM_VERSION_DEV_MINOR: ${ROCM_VERSION_DEV_MINOR}") + message("ROCM_VERSION_DEV_PATCH: ${ROCM_VERSION_DEV_PATCH}") + + message("\n***** Library versions from dpkg *****\n") + execute_process(COMMAND dpkg -l COMMAND grep rocm-dev COMMAND awk "{print $2 \" VERSION: \" $3}") + execute_process(COMMAND dpkg -l COMMAND grep rocm-libs COMMAND awk "{print $2 \" VERSION: \" $3}") + execute_process(COMMAND dpkg -l COMMAND grep hsakmt-roct COMMAND awk "{print $2 \" VERSION: \" $3}") + execute_process(COMMAND dpkg -l COMMAND grep rocr-dev COMMAND awk "{print $2 \" VERSION: \" $3}") + execute_process(COMMAND dpkg -l COMMAND grep -w hcc COMMAND awk "{print $2 \" VERSION: \" $3}") + execute_process(COMMAND dpkg -l COMMAND grep hip_base COMMAND awk "{print $2 \" VERSION: \" $3}") + execute_process(COMMAND dpkg -l COMMAND grep hip_hcc COMMAND awk "{print $2 \" VERSION: \" $3}") + + message("\n***** Library versions from cmake find_package *****\n") + + set(CMAKE_HCC_FLAGS_DEBUG ${CMAKE_CXX_FLAGS_DEBUG}) + set(CMAKE_HCC_FLAGS_RELEASE ${CMAKE_CXX_FLAGS_RELEASE}) + ### Remove setting of Flags when FindHIP.CMake PR #558 is accepted.### + + set(hip_DIR ${HIP_PATH}/lib/cmake/hip) + set(hsa-runtime64_DIR ${ROCM_PATH}/lib/cmake/hsa-runtime64) + set(AMDDeviceLibs_DIR ${ROCM_PATH}/lib/cmake/AMDDeviceLibs) + set(amd_comgr_DIR ${ROCM_PATH}/lib/cmake/amd_comgr) + set(rocrand_DIR ${ROCRAND_PATH}/lib/cmake/rocrand) + set(hiprand_DIR ${HIPRAND_PATH}/lib/cmake/hiprand) + set(rocblas_DIR ${ROCBLAS_PATH}/lib/cmake/rocblas) + set(miopen_DIR ${MIOPEN_PATH}/lib/cmake/miopen) + set(rocfft_DIR ${ROCFFT_PATH}/lib/cmake/rocfft) + set(hipfft_DIR ${HIPFFT_PATH}/lib/cmake/hipfft) + set(hipsparse_DIR ${HIPSPARSE_PATH}/lib/cmake/hipsparse) + set(rccl_DIR ${RCCL_PATH}/lib/cmake/rccl) + set(rocprim_DIR ${ROCPRIM_PATH}/lib/cmake/rocprim) + set(hipcub_DIR ${HIPCUB_PATH}/lib/cmake/hipcub) + set(rocthrust_DIR ${ROCTHRUST_PATH}/lib/cmake/rocthrust) + + find_package_and_print_version(hip REQUIRED) + find_package_and_print_version(hsa-runtime64 REQUIRED) + find_package_and_print_version(amd_comgr REQUIRED) + find_package_and_print_version(rocrand REQUIRED) + find_package_and_print_version(hiprand REQUIRED) + find_package_and_print_version(rocblas REQUIRED) + find_package_and_print_version(miopen REQUIRED) + find_package_and_print_version(rocfft REQUIRED) + if(ROCM_VERSION_DEV VERSION_GREATER_EQUAL "4.1.0") + find_package_and_print_version(hipfft REQUIRED) + endif() + find_package_and_print_version(hipsparse REQUIRED) + find_package_and_print_version(rccl) + find_package_and_print_version(rocprim REQUIRED) + find_package_and_print_version(hipcub REQUIRED) + find_package_and_print_version(rocthrust REQUIRED) + + if(HIP_COMPILER STREQUAL clang) + set(hip_library_name amdhip64) + else() + set(hip_library_name hip_hcc) + endif() + message("HIP library name: ${hip_library_name}") + + # TODO: hip_hcc has an interface include flag "-hc" which is only + # recognizable by hcc, but not gcc and clang. Right now in our + # setup, hcc is only used for linking, but it should be used to + # compile the *_hip.cc files as well. + find_library(PYTORCH_HIP_HCC_LIBRARIES ${hip_library_name} HINTS ${HIP_PATH}/lib) + # TODO: miopen_LIBRARIES should return fullpath to the library file, + # however currently it's just the lib name + find_library(PYTORCH_MIOPEN_LIBRARIES ${miopen_LIBRARIES} HINTS ${MIOPEN_PATH}/lib) + # TODO: rccl_LIBRARIES should return fullpath to the library file, + # however currently it's just the lib name + find_library(PYTORCH_RCCL_LIBRARIES ${rccl_LIBRARIES} HINTS ${RCCL_PATH}/lib) + # hiprtc is part of HIP + find_library(ROCM_HIPRTC_LIB ${hip_library_name} HINTS ${HIP_PATH}/lib) + # roctx is part of roctracer + find_library(ROCM_ROCTX_LIB roctx64 HINTS ${ROCTRACER_PATH}/lib) + set(roctracer_INCLUDE_DIRS ${ROCTRACER_PATH}/include) +endif() diff --git a/test/torchaudio_unittest/backend/soundfile/save_test.py b/test/torchaudio_unittest/backend/soundfile/save_test.py index e4e8c93631..c8c97436e5 100644 --- a/test/torchaudio_unittest/backend/soundfile/save_test.py +++ b/test/torchaudio_unittest/backend/soundfile/save_test.py @@ -11,6 +11,7 @@ get_wav_data, load_wav, nested_params, + skipIfRocm, ) from .common import ( fetch_wav_subtype, @@ -280,6 +281,7 @@ def test_fileobj_wav(self): self._test_fileobj('wav') @skipIfFormatNotSupported("FLAC") + @skipIfRocm def test_fileobj_flac(self): """Saving audio via file-like object works""" self._test_fileobj('flac') diff --git a/test/torchaudio_unittest/common_utils/__init__.py b/test/torchaudio_unittest/common_utils/__init__.py index 736ec82855..f7e48b878f 100644 --- a/test/torchaudio_unittest/common_utils/__init__.py +++ b/test/torchaudio_unittest/common_utils/__init__.py @@ -2,6 +2,7 @@ get_asset_path, get_whitenoise, get_sinusoid, + get_spectrogram, ) from .backend_utils import ( set_audio_backend, @@ -17,6 +18,7 @@ skipIfNoModule, skipIfNoKaldi, skipIfNoSox, + skipIfRocm, ) from .wav_utils import ( get_wav_data, @@ -29,8 +31,28 @@ nested_params ) -__all__ = ['get_asset_path', 'get_whitenoise', 'get_sinusoid', 'set_audio_backend', - 'TempDirMixin', 'HttpServerMixin', 'TestBaseMixin', 'PytorchTestCase', 'TorchaudioTestCase', - 'skipIfNoCuda', 'skipIfNoExec', 'skipIfNoModule', 'skipIfNoKaldi', 'skipIfNoSox', - 'skipIfNoSoxBackend', 'get_wav_data', 'normalize_wav', 'load_wav', 'save_wav', 'load_params', - 'nested_params'] +__all__ = [ + 'get_asset_path', + 'get_whitenoise', + 'get_sinusoid', + 'get_spectrogram', + 'set_audio_backend', + 'TempDirMixin', + 'HttpServerMixin', + 'TestBaseMixin', + 'PytorchTestCase', + 'TorchaudioTestCase', + 'skipIfNoCuda', + 'skipIfNoExec', + 'skipIfNoModule', + 'skipIfNoKaldi', + 'skipIfNoSox', + 'skipIfNoSoxBackend', + 'skipIfRocm', + 'get_wav_data', + 'normalize_wav', + 'load_wav', + 'save_wav', + 'load_params', + 'nested_params', +] diff --git a/test/torchaudio_unittest/common_utils/case_utils.py b/test/torchaudio_unittest/common_utils/case_utils.py index 69b9a795cd..7357cec4c4 100644 --- a/test/torchaudio_unittest/common_utils/case_utils.py +++ b/test/torchaudio_unittest/common_utils/case_utils.py @@ -98,3 +98,5 @@ def skipIfNoModule(module, display_name=None): skipIfNoCuda = unittest.skipIf(not torch.cuda.is_available(), reason='CUDA not available') skipIfNoSox = unittest.skipIf(not is_sox_available(), reason='Sox not available') skipIfNoKaldi = unittest.skipIf(not is_kaldi_available(), reason='Kaldi not available') +skipIfRocm = unittest.skipIf(os.getenv('TORCHAUDIO_TEST_WITH_ROCM', '0') == '1', + reason="test doesn't currently work on the ROCm stack") diff --git a/test/torchaudio_unittest/common_utils/data_utils.py b/test/torchaudio_unittest/common_utils/data_utils.py index 9bbafe4f36..3facfbc6d7 100644 --- a/test/torchaudio_unittest/common_utils/data_utils.py +++ b/test/torchaudio_unittest/common_utils/data_utils.py @@ -1,5 +1,5 @@ import os.path -from typing import Union +from typing import Union, Optional import torch @@ -62,7 +62,7 @@ def get_whitenoise( """ if isinstance(dtype, str): dtype = getattr(torch, dtype) - if dtype not in [torch.float32, torch.int32, torch.int16, torch.uint8]: + if dtype not in [torch.float64, torch.float32, torch.int32, torch.int16, torch.uint8]: raise NotImplementedError(f'dtype {dtype} is not supported.') # According to the doc, folking rng on all CUDA devices is slow when there are many CUDA devices, # so we only fork on CPU, generate values and move the data to the given device @@ -110,3 +110,43 @@ def get_sinusoid( if not channels_first: tensor = tensor.t() return convert_tensor_encoding(tensor, dtype) + + +def get_spectrogram( + waveform, + *, + n_fft: int = 2048, + hop_length: Optional[int] = None, + win_length: Optional[int] = None, + window: Optional[torch.Tensor] = None, + center: bool = True, + pad_mode: str = 'reflect', + power: Optional[float] = None, +): + """Generate a spectrogram of the given Tensor + + Args: + n_fft: The number of FFT bins. + hop_length: Stride for sliding window. default: ``n_fft // 4``. + win_length: The size of window frame and STFT filter. default: ``n_fft``. + winwdow: Window function. default: Hann window + center: Pad the input sequence if True. See ``torch.stft`` for the detail. + pad_mode: Padding method used when center is True. Default: "reflect". + power: If ``None``, raw spectrogram with complex values are returned, + otherwise the norm of the spectrogram is returned. + """ + hop_length = hop_length or n_fft // 4 + win_length = win_length or n_fft + window = torch.hann_window(win_length) if window is None else window + spec = torch.stft( + waveform, + n_fft=n_fft, + hop_length=hop_length, + win_length=win_length, + center=center, + window=window, + pad_mode=pad_mode, + return_complex=True) + if power is not None: + spec = spec.abs() ** power + return spec diff --git a/test/torchaudio_unittest/common_utils/parameterized_utils.py b/test/torchaudio_unittest/common_utils/parameterized_utils.py index 412ee82554..000dccaf12 100644 --- a/test/torchaudio_unittest/common_utils/parameterized_utils.py +++ b/test/torchaudio_unittest/common_utils/parameterized_utils.py @@ -11,17 +11,43 @@ def load_params(*paths): return [param(json.loads(line)) for line in file] -def nested_params(*params): - def _name_func(func, _, params): - strs = [] - for arg in params.args: - if isinstance(arg, tuple): - strs.append("_".join(str(a) for a in arg)) - else: - strs.append(str(arg)) - return f'{func.__name__}_{"_".join(strs)}' - - return parameterized.expand( - list(product(*params)), - name_func=_name_func - ) +def _name_func(func, _, params): + strs = [] + for arg in params.args: + if isinstance(arg, tuple): + strs.append("_".join(str(a) for a in arg)) + else: + strs.append(str(arg)) + # sanitize the test name + name = "_".join(strs).replace(".", "_") + return f'{func.__name__}_{name}' + + +def nested_params(*params_set): + """Generate the cartesian product of the given list of parameters. + + Args: + params_set (list of parameters): Parameters. When using ``parameterized.param`` class, + all the parameters have to be specified with the class, only using kwargs. + """ + flatten = [p for params in params_set for p in params] + + # Parameters to be nested are given as list of plain objects + if all(not isinstance(p, param) for p in flatten): + args = list(product(*params_set)) + return parameterized.expand(args, name_func=_name_func) + + # Parameters to be nested are given as list of `parameterized.param` + if not all(isinstance(p, param) for p in flatten): + raise TypeError( + "When using ``parameterized.param``, " + "all the parameters have to be of the ``param`` type.") + if any(p.args for p in flatten): + raise ValueError( + "When using ``parameterized.param``, " + "all the parameters have to be provided as keyword argument." + ) + args = [param()] + for params in params_set: + args = [param(**x.kwargs, **y.kwargs) for x in args for y in params] + return parameterized.expand(args) diff --git a/test/torchaudio_unittest/functional/autograd_impl.py b/test/torchaudio_unittest/functional/autograd_impl.py index 02477d0d33..e273369ea6 100644 --- a/test/torchaudio_unittest/functional/autograd_impl.py +++ b/test/torchaudio_unittest/functional/autograd_impl.py @@ -1,40 +1,174 @@ +from typing import Callable, Tuple import torch +from parameterized import parameterized +from torch import Tensor import torchaudio.functional as F from torch.autograd import gradcheck -from torchaudio_unittest import common_utils +from torchaudio_unittest.common_utils import ( + TestBaseMixin, + get_whitenoise, +) -class Autograd(common_utils.TestBaseMixin): - def test_x_grad(self): +class Autograd(TestBaseMixin): + def assert_grad( + self, + transform: Callable[..., Tensor], + inputs: Tuple[torch.Tensor], + *, + enable_all_grad: bool = True, + ): + inputs_ = [] + for i in inputs: + if torch.is_tensor(i): + i = i.to(dtype=self.dtype, device=self.device) + if enable_all_grad: + i.requires_grad = True + inputs_.append(i) + assert gradcheck(transform, inputs_) + + def test_lfilter_x(self): torch.random.manual_seed(2434) - x = torch.rand(2, 4, 256 * 2, dtype=self.dtype, device=self.device) - a = torch.tensor([0.7, 0.2, 0.6], dtype=self.dtype, device=self.device) - b = torch.tensor([0.4, 0.2, 0.9], dtype=self.dtype, device=self.device) + x = get_whitenoise(sample_rate=22050, duration=0.01, n_channels=2) + a = torch.tensor([0.7, 0.2, 0.6]) + b = torch.tensor([0.4, 0.2, 0.9]) x.requires_grad = True - assert gradcheck(F.lfilter, (x, a, b), eps=1e-10) + self.assert_grad(F.lfilter, (x, a, b), enable_all_grad=False) - def test_a_grad(self): + def test_lfilter_a(self): torch.random.manual_seed(2434) - x = torch.rand(2, 4, 256 * 2, dtype=self.dtype, device=self.device) - a = torch.tensor([0.7, 0.2, 0.6], dtype=self.dtype, device=self.device) - b = torch.tensor([0.4, 0.2, 0.9], dtype=self.dtype, device=self.device) + x = get_whitenoise(sample_rate=22050, duration=0.01, n_channels=2) + a = torch.tensor([0.7, 0.2, 0.6]) + b = torch.tensor([0.4, 0.2, 0.9]) a.requires_grad = True - assert gradcheck(F.lfilter, (x, a, b), eps=1e-10) + self.assert_grad(F.lfilter, (x, a, b), enable_all_grad=False) - def test_b_grad(self): + def test_lfilter_b(self): torch.random.manual_seed(2434) - x = torch.rand(2, 4, 256 * 2, dtype=self.dtype, device=self.device) - a = torch.tensor([0.7, 0.2, 0.6], dtype=self.dtype, device=self.device) - b = torch.tensor([0.4, 0.2, 0.9], dtype=self.dtype, device=self.device) + x = get_whitenoise(sample_rate=22050, duration=0.01, n_channels=2) + a = torch.tensor([0.7, 0.2, 0.6]) + b = torch.tensor([0.4, 0.2, 0.9]) b.requires_grad = True - assert gradcheck(F.lfilter, (x, a, b), eps=1e-10) + self.assert_grad(F.lfilter, (x, a, b), enable_all_grad=False) - def test_all_grad(self): + def test_lfilter_all_inputs(self): torch.random.manual_seed(2434) - x = torch.rand(2, 4, 256 * 2, dtype=self.dtype, device=self.device) - a = torch.tensor([0.7, 0.2, 0.6], dtype=self.dtype, device=self.device) - b = torch.tensor([0.4, 0.2, 0.9], dtype=self.dtype, device=self.device) - b.requires_grad = True - a.requires_grad = True - x.requires_grad = True - assert gradcheck(F.lfilter, (x, a, b), eps=1e-10) + x = get_whitenoise(sample_rate=22050, duration=0.01, n_channels=2) + a = torch.tensor([0.7, 0.2, 0.6]) + b = torch.tensor([0.4, 0.2, 0.9]) + self.assert_grad(F.lfilter, (x, a, b)) + + def test_biquad(self): + torch.random.manual_seed(2434) + x = get_whitenoise(sample_rate=22050, duration=0.01, n_channels=1) + a = torch.tensor([0.7, 0.2, 0.6]) + b = torch.tensor([0.4, 0.2, 0.9]) + self.assert_grad(F.biquad, (x, b[0], b[1], b[2], a[0], a[1], a[2])) + + @parameterized.expand([ + (800, 0.7, True), + (800, 0.7, False), + ]) + def test_band_biquad(self, central_freq, Q, noise): + torch.random.manual_seed(2434) + sr = 22050 + x = get_whitenoise(sample_rate=sr, duration=0.01, n_channels=1) + central_freq = torch.tensor(central_freq) + Q = torch.tensor(Q) + self.assert_grad(F.band_biquad, (x, sr, central_freq, Q, noise)) + + @parameterized.expand([ + (800, 0.7, 10), + (800, 0.7, -10), + ]) + def test_bass_biquad(self, central_freq, Q, gain): + torch.random.manual_seed(2434) + sr = 22050 + x = get_whitenoise(sample_rate=sr, duration=0.01, n_channels=1) + central_freq = torch.tensor(central_freq) + Q = torch.tensor(Q) + gain = torch.tensor(gain) + self.assert_grad(F.bass_biquad, (x, sr, gain, central_freq, Q)) + + @parameterized.expand([ + (3000, 0.7, 10), + (3000, 0.7, -10), + + ]) + def test_treble_biquad(self, central_freq, Q, gain): + torch.random.manual_seed(2434) + sr = 22050 + x = get_whitenoise(sample_rate=sr, duration=0.01, n_channels=1) + central_freq = torch.tensor(central_freq) + Q = torch.tensor(Q) + gain = torch.tensor(gain) + self.assert_grad(F.treble_biquad, (x, sr, gain, central_freq, Q)) + + @parameterized.expand([ + (800, 0.7, ), + ]) + def test_allpass_biquad(self, central_freq, Q): + torch.random.manual_seed(2434) + sr = 22050 + x = get_whitenoise(sample_rate=sr, duration=0.01, n_channels=1) + central_freq = torch.tensor(central_freq) + Q = torch.tensor(Q) + self.assert_grad(F.allpass_biquad, (x, sr, central_freq, Q)) + + @parameterized.expand([ + (800, 0.7, ), + ]) + def test_lowpass_biquad(self, cutoff_freq, Q): + torch.random.manual_seed(2434) + sr = 22050 + x = get_whitenoise(sample_rate=sr, duration=0.01, n_channels=1) + cutoff_freq = torch.tensor(cutoff_freq) + Q = torch.tensor(Q) + self.assert_grad(F.lowpass_biquad, (x, sr, cutoff_freq, Q)) + + @parameterized.expand([ + (800, 0.7, ), + ]) + def test_highpass_biquad(self, cutoff_freq, Q): + torch.random.manual_seed(2434) + sr = 22050 + x = get_whitenoise(sample_rate=sr, duration=0.01, n_channels=1) + cutoff_freq = torch.tensor(cutoff_freq) + Q = torch.tensor(Q) + self.assert_grad(F.highpass_biquad, (x, sr, cutoff_freq, Q)) + + @parameterized.expand([ + (800, 0.7, True), + (800, 0.7, False), + ]) + def test_bandpass_biquad(self, central_freq, Q, const_skirt_gain): + torch.random.manual_seed(2434) + sr = 22050 + x = get_whitenoise(sample_rate=sr, duration=0.01, n_channels=1) + central_freq = torch.tensor(central_freq) + Q = torch.tensor(Q) + self.assert_grad(F.bandpass_biquad, (x, sr, central_freq, Q, const_skirt_gain)) + + @parameterized.expand([ + (800, 0.7, 10), + (800, 0.7, -10), + ]) + def test_equalizer_biquad(self, central_freq, Q, gain): + torch.random.manual_seed(2434) + sr = 22050 + x = get_whitenoise(sample_rate=sr, duration=0.01, n_channels=1) + central_freq = torch.tensor(central_freq) + Q = torch.tensor(Q) + gain = torch.tensor(gain) + self.assert_grad(F.equalizer_biquad, (x, sr, central_freq, gain, Q)) + + @parameterized.expand([ + (800, 0.7, ), + ]) + def test_bandreject_biquad(self, central_freq, Q): + torch.random.manual_seed(2434) + sr = 22050 + x = get_whitenoise(sample_rate=sr, duration=0.01, n_channels=1) + central_freq = torch.tensor(central_freq) + Q = torch.tensor(Q) + self.assert_grad(F.bandreject_biquad, (x, sr, central_freq, Q)) diff --git a/test/torchaudio_unittest/functional/batch_consistency_test.py b/test/torchaudio_unittest/functional/batch_consistency_test.py index 44a9580fe8..d9b49dfa61 100644 --- a/test/torchaudio_unittest/functional/batch_consistency_test.py +++ b/test/torchaudio_unittest/functional/batch_consistency_test.py @@ -197,22 +197,6 @@ def test_sliding_window_cmn(self, center, norm_vars): F.sliding_window_cmn, spectrogram, center=center, norm_vars=norm_vars) - def test_vad_from_file(self): - filepath = common_utils.get_asset_path("vad-go-stereo-44100.wav") - waveform, sample_rate = common_utils.load_wav(filepath) - # Each channel is slightly offset - we can use this to create a batch - # with different items. - batch = waveform.view(2, 1, -1) - self.assert_batch_consistency(F.vad, batch, sample_rate=sample_rate) - - def test_vad_different_items(self): - """Separate test to ensure VAD consistency with differing items.""" - sample_rate = 44100 - torch.manual_seed(0) - waveforms = torch.rand(self.batch_size, 2, 100) - 0.5 - self.assert_batch_consistency( - F.vad, waveforms, sample_rate=sample_rate) - @common_utils.skipIfNoKaldi def test_compute_kaldi_pitch(self): sample_rate = 44100 diff --git a/test/torchaudio_unittest/functional/functional_cpu_test.py b/test/torchaudio_unittest/functional/functional_cpu_test.py index 7669d96744..b9c5a6f64e 100644 --- a/test/torchaudio_unittest/functional/functional_cpu_test.py +++ b/test/torchaudio_unittest/functional/functional_cpu_test.py @@ -14,30 +14,32 @@ skipIfNoSox, ) -from .functional_impl import Lfilter, Spectrogram +from .functional_impl import Functional, FunctionalComplex -class TestLFilterFloat32(Lfilter, common_utils.PytorchTestCase): +class TestFunctionalFloat32(Functional, common_utils.PytorchTestCase): dtype = torch.float32 device = torch.device('cpu') @unittest.expectedFailure - def test_9th_order_filter_stability(self): - super().test_9th_order_filter_stability() + def test_lfilter_9th_order_filter_stability(self): + super().test_lfilter_9th_order_filter_stability() -class TestLFilterFloat64(Lfilter, common_utils.PytorchTestCase): +class TestFunctionalFloat64(Functional, common_utils.PytorchTestCase): dtype = torch.float64 device = torch.device('cpu') -class TestSpectrogramFloat32(Spectrogram, common_utils.PytorchTestCase): - dtype = torch.float32 +class TestFunctionalComplex64(FunctionalComplex, common_utils.PytorchTestCase): + complex_dtype = torch.complex64 + real_dtype = torch.float32 device = torch.device('cpu') -class TestSpectrogramFloat64(Spectrogram, common_utils.PytorchTestCase): - dtype = torch.float64 +class TestFunctionalComplex128(FunctionalComplex, common_utils.PytorchTestCase): + complex_dtype = torch.complex128 + real_dtype = torch.float64 device = torch.device('cpu') diff --git a/test/torchaudio_unittest/functional/functional_cuda_test.py b/test/torchaudio_unittest/functional/functional_cuda_test.py index f4db6ca3a0..ebf8cd8326 100644 --- a/test/torchaudio_unittest/functional/functional_cuda_test.py +++ b/test/torchaudio_unittest/functional/functional_cuda_test.py @@ -2,32 +2,34 @@ import unittest from torchaudio_unittest import common_utils -from .functional_impl import Lfilter, Spectrogram +from .functional_impl import Functional, FunctionalComplex @common_utils.skipIfNoCuda -class TestLFilterFloat32(Lfilter, common_utils.PytorchTestCase): +class TestFunctionalloat32(Functional, common_utils.PytorchTestCase): dtype = torch.float32 device = torch.device('cuda') @unittest.expectedFailure - def test_9th_order_filter_stability(self): - super().test_9th_order_filter_stability() + def test_lfilter_9th_order_filter_stability(self): + super().test_lfilter_9th_order_filter_stability() @common_utils.skipIfNoCuda -class TestLFilterFloat64(Lfilter, common_utils.PytorchTestCase): +class TestLFilterFloat64(Functional, common_utils.PytorchTestCase): dtype = torch.float64 device = torch.device('cuda') @common_utils.skipIfNoCuda -class TestSpectrogramFloat32(Spectrogram, common_utils.PytorchTestCase): - dtype = torch.float32 +class TestFunctionalComplex64(FunctionalComplex, common_utils.PytorchTestCase): + complex_dtype = torch.complex64 + real_dtype = torch.float32 device = torch.device('cuda') @common_utils.skipIfNoCuda -class TestSpectrogramFloat64(Spectrogram, common_utils.PytorchTestCase): - dtype = torch.float64 +class TestFunctionalComplex128(FunctionalComplex, common_utils.PytorchTestCase): + complex_dtype = torch.complex64 + real_dtype = torch.float32 device = torch.device('cuda') diff --git a/test/torchaudio_unittest/functional/functional_impl.py b/test/torchaudio_unittest/functional/functional_impl.py index f7f8c17ecb..8b890e9563 100644 --- a/test/torchaudio_unittest/functional/functional_impl.py +++ b/test/torchaudio_unittest/functional/functional_impl.py @@ -2,13 +2,15 @@ import torch import torchaudio.functional as F from parameterized import parameterized +import numpy as np from scipy import signal from torchaudio_unittest import common_utils +from torchaudio_unittest.common_utils import nested_params -class Lfilter(common_utils.TestBaseMixin): - def test_simple(self): +class Functional(common_utils.TestBaseMixin): + def test_lfilter_simple(self): """ Create a very basic signal, Then make a simple 4th order delay @@ -23,7 +25,7 @@ def test_simple(self): self.assertEqual(output_waveform[:, 3:], waveform[:, 0:-3], atol=1e-5, rtol=1e-5) - def test_clamp(self): + def test_lfilter_clamp(self): input_signal = torch.ones(1, 44100 * 1, dtype=self.dtype, device=self.device) b_coeffs = torch.tensor([1, 0], dtype=self.dtype, device=self.device) a_coeffs = torch.tensor([1, -0.95], dtype=self.dtype, device=self.device) @@ -38,7 +40,7 @@ def test_clamp(self): ((2, 3, 44100),), ((1, 2, 3, 44100),) ]) - def test_shape(self, shape): + def test_lfilter_shape(self, shape): torch.random.manual_seed(42) waveform = torch.rand(*shape, dtype=self.dtype, device=self.device) b_coeffs = torch.tensor([0, 0, 0, 1], dtype=self.dtype, device=self.device) @@ -46,7 +48,7 @@ def test_shape(self, shape): output_waveform = F.lfilter(waveform, a_coeffs, b_coeffs) assert shape == waveform.size() == output_waveform.size() - def test_9th_order_filter_stability(self): + def test_lfilter_9th_order_filter_stability(self): """ Validate the precision of lfilter against reference scipy implementation when using high order filter. The reference implementation use cascaded second-order filters so is more numerically accurate. @@ -68,10 +70,8 @@ def test_9th_order_filter_stability(self): yhat = F.lfilter(x, a, b, False) self.assertEqual(yhat, y, atol=1e-4, rtol=1e-5) - -class Spectrogram(common_utils.TestBaseMixin): @parameterized.expand([(0., ), (1., ), (2., ), (3., )]) - def test_grad_at_zero(self, power): + def test_spectogram_grad_at_zero(self, power): """The gradient of power spectrogram should not be nan but zero near x=0 https://github.com/pytorch/audio/issues/993 @@ -89,3 +89,39 @@ def test_grad_at_zero(self, power): ) spec.sum().backward() assert not x.grad.isnan().sum() + + +class FunctionalComplex(common_utils.TestBaseMixin): + complex_dtype = None + real_dtype = None + device = None + + @nested_params( + [0.5, 1.01, 1.3], + [True, False], + ) + def test_phase_vocoder_shape(self, rate, test_pseudo_complex): + """Verify the output shape of phase vocoder""" + hop_length = 256 + num_freq = 1025 + num_frames = 400 + batch_size = 2 + + torch.random.manual_seed(42) + spec = torch.randn( + batch_size, num_freq, num_frames, dtype=self.complex_dtype, device=self.device) + if test_pseudo_complex: + spec = torch.view_as_real(spec) + + phase_advance = torch.linspace( + 0, + np.pi * hop_length, + num_freq, + dtype=self.real_dtype, device=self.device)[..., None] + + spec_stretch = F.phase_vocoder(spec, rate=rate, phase_advance=phase_advance) + + assert spec.dim() == spec_stretch.dim() + expected_shape = torch.Size([batch_size, num_freq, int(np.ceil(num_frames / rate))]) + output_shape = (torch.view_as_complex(spec_stretch) if test_pseudo_complex else spec_stretch).shape + assert output_shape == expected_shape diff --git a/test/torchaudio_unittest/functional/librosa_compatibility_cpu_test.py b/test/torchaudio_unittest/functional/librosa_compatibility_cpu_test.py new file mode 100644 index 0000000000..dcfe6fcf4d --- /dev/null +++ b/test/torchaudio_unittest/functional/librosa_compatibility_cpu_test.py @@ -0,0 +1,10 @@ +from torchaudio_unittest.common_utils import PytorchTestCase +from .librosa_compatibility_test_impl import Functional, FunctionalComplex + + +class TestFunctionalCPU(Functional, PytorchTestCase): + device = 'cpu' + + +class TestFunctionalComplexCPU(FunctionalComplex, PytorchTestCase): + device = 'cpu' diff --git a/test/torchaudio_unittest/functional/librosa_compatibility_cuda_test.py b/test/torchaudio_unittest/functional/librosa_compatibility_cuda_test.py new file mode 100644 index 0000000000..9f42b4dc84 --- /dev/null +++ b/test/torchaudio_unittest/functional/librosa_compatibility_cuda_test.py @@ -0,0 +1,12 @@ +from torchaudio_unittest.common_utils import PytorchTestCase, skipIfNoCuda +from .librosa_compatibility_test_impl import Functional, FunctionalComplex + + +@skipIfNoCuda +class TestFunctionalCUDA(Functional, PytorchTestCase): + device = 'cuda' + + +@skipIfNoCuda +class TestFunctionalComplexCUDA(FunctionalComplex, PytorchTestCase): + device = 'cuda' diff --git a/test/torchaudio_unittest/functional/librosa_compatibility_test.py b/test/torchaudio_unittest/functional/librosa_compatibility_test.py deleted file mode 100644 index 5905c239d3..0000000000 --- a/test/torchaudio_unittest/functional/librosa_compatibility_test.py +++ /dev/null @@ -1,174 +0,0 @@ -import itertools -import unittest -from distutils.version import StrictVersion - -import torch -from parameterized import parameterized, param - -import torchaudio.functional as F -from torchaudio._internal.module_utils import is_module_available - -LIBROSA_AVAILABLE = is_module_available('librosa') - -if LIBROSA_AVAILABLE: - import numpy as np - import librosa - -from torchaudio_unittest import common_utils - - -@unittest.skipIf(not LIBROSA_AVAILABLE, "Librosa not available") -class TestFunctional(common_utils.TorchaudioTestCase): - """Test suite for functions in `functional` module.""" - def test_griffinlim(self): - # NOTE: This test is flaky without a fixed random seed - # See https://github.com/pytorch/audio/issues/382 - torch.random.manual_seed(42) - tensor = torch.rand((1, 1000)) - - n_fft = 400 - ws = 400 - hop = 100 - window = torch.hann_window(ws) - normalize = False - momentum = 0.99 - n_iter = 8 - length = 1000 - rand_init = False - init = 'random' if rand_init else None - - specgram = F.spectrogram(tensor, 0, window, n_fft, hop, ws, 2, normalize).sqrt() - ta_out = F.griffinlim(specgram, window, n_fft, hop, ws, 1, - n_iter, momentum, length, rand_init) - lr_out = librosa.griffinlim(specgram.squeeze(0).numpy(), n_iter=n_iter, hop_length=hop, - momentum=momentum, init=init, length=length) - lr_out = torch.from_numpy(lr_out).unsqueeze(0) - - self.assertEqual(ta_out, lr_out, atol=5e-5, rtol=1e-5) - - @parameterized.expand([ - param(norm=norm, mel_scale=mel_scale, **p.kwargs) - for p in [ - param(), - param(n_mels=128, sample_rate=44100), - param(n_mels=128, fmin=2000.0, fmax=5000.0), - param(n_mels=56, fmin=100.0, fmax=9000.0), - param(n_mels=56, fmin=800.0, fmax=900.0), - param(n_mels=56, fmin=1900.0, fmax=900.0), - param(n_mels=10, fmin=1900.0, fmax=900.0), - ] - for norm in [None, 'slaney'] - for mel_scale in ['htk', 'slaney'] - ]) - def test_create_fb(self, n_mels=40, sample_rate=22050, n_fft=2048, - fmin=0.0, fmax=8000.0, norm=None, mel_scale="htk"): - if (norm == "slaney" and StrictVersion(librosa.__version__) < StrictVersion("0.7.2")): - self.skipTest('Test is known to fail with older versions of librosa.') - - librosa_fb = librosa.filters.mel(sr=sample_rate, - n_fft=n_fft, - n_mels=n_mels, - fmax=fmax, - fmin=fmin, - htk=mel_scale == "htk", - norm=norm) - fb = F.create_fb_matrix(sample_rate=sample_rate, - n_mels=n_mels, - f_max=fmax, - f_min=fmin, - n_freqs=(n_fft // 2 + 1), - norm=norm, - mel_scale=mel_scale) - - for i_mel_bank in range(n_mels): - self.assertEqual( - fb[:, i_mel_bank], torch.tensor(librosa_fb[i_mel_bank]), atol=1e-4, rtol=1e-5) - - def test_amplitude_to_DB(self): - spec = torch.rand((6, 201)) - - amin = 1e-10 - db_multiplier = 0.0 - top_db = 80.0 - - # Power to DB - multiplier = 10.0 - - ta_out = F.amplitude_to_DB(spec, multiplier, amin, db_multiplier, top_db) - lr_out = librosa.core.power_to_db(spec.numpy()) - lr_out = torch.from_numpy(lr_out) - - self.assertEqual(ta_out, lr_out, atol=5e-5, rtol=1e-5) - - # Amplitude to DB - multiplier = 20.0 - - ta_out = F.amplitude_to_DB(spec, multiplier, amin, db_multiplier, top_db) - lr_out = librosa.core.amplitude_to_db(spec.numpy()) - lr_out = torch.from_numpy(lr_out) - - self.assertEqual(ta_out, lr_out, atol=5e-5, rtol=1e-5) - - def test_resample(self): - input_path = common_utils.get_asset_path('sinewave.wav') - waveform, sample_rate = common_utils.load_wav(input_path) - - upsample_rate = sample_rate * 2 - downsample_rate = sample_rate // 2 - - ta_upsampled = F.resample(waveform, sample_rate, upsample_rate) - lr_upsampled = librosa.resample(waveform.squeeze(0).numpy(), sample_rate, upsample_rate) - lr_upsampled = torch.from_numpy(lr_upsampled).unsqueeze(0) - - self.assertEqual(ta_upsampled, lr_upsampled, atol=1e-2, rtol=1e-5) - - ta_downsampled = F.resample(waveform, sample_rate, downsample_rate) - lr_downsampled = librosa.resample(waveform.squeeze(0).numpy(), sample_rate, downsample_rate) - lr_downsampled = torch.from_numpy(lr_downsampled).unsqueeze(0) - - self.assertEqual(ta_downsampled, lr_downsampled, atol=1e-2, rtol=1e-5) - - -@unittest.skipIf(not LIBROSA_AVAILABLE, "Librosa not available") -class TestPhaseVocoder(common_utils.TorchaudioTestCase): - @parameterized.expand(list(itertools.product( - [(2, 1025, 400, 2)], - [0.5, 1.01, 1.3], - [256] - ))) - def test_phase_vocoder(self, shape, rate, hop_length): - # Due to cummulative sum, numerical error in using torch.float32 will - # result in bottom right values of the stretched sectrogram to not - # match with librosa. - torch.random.manual_seed(42) - complex_specgrams = torch.randn(*shape) - complex_specgrams = complex_specgrams.type(torch.float64) - phase_advance = torch.linspace( - 0, - np.pi * hop_length, - complex_specgrams.shape[-3], - dtype=torch.float64)[..., None] - - complex_specgrams_stretch = F.phase_vocoder(complex_specgrams, rate=rate, phase_advance=phase_advance) - - # == Test shape - expected_size = list(complex_specgrams.size()) - expected_size[-2] = int(np.ceil(expected_size[-2] / rate)) - - assert complex_specgrams.dim() == complex_specgrams_stretch.dim() - assert complex_specgrams_stretch.size() == torch.Size(expected_size) - - # == Test values - index = [0] * (complex_specgrams.dim() - 3) + [slice(None)] * 3 - mono_complex_specgram = complex_specgrams[index].numpy() - mono_complex_specgram = mono_complex_specgram[..., 0] + \ - mono_complex_specgram[..., 1] * 1j - expected_complex_stretch = librosa.phase_vocoder( - mono_complex_specgram, - rate=rate, - hop_length=hop_length) - - complex_stretch = complex_specgrams_stretch[index].numpy() - complex_stretch = complex_stretch[..., 0] + 1j * complex_stretch[..., 1] - - self.assertEqual(complex_stretch, torch.from_numpy(expected_complex_stretch), atol=1e-5, rtol=1e-5) diff --git a/test/torchaudio_unittest/functional/librosa_compatibility_test_impl.py b/test/torchaudio_unittest/functional/librosa_compatibility_test_impl.py new file mode 100644 index 0000000000..f0ac4cdd75 --- /dev/null +++ b/test/torchaudio_unittest/functional/librosa_compatibility_test_impl.py @@ -0,0 +1,161 @@ +import unittest +from distutils.version import StrictVersion + +import torch +from parameterized import param + +import torchaudio.functional as F +from torchaudio._internal.module_utils import is_module_available + +LIBROSA_AVAILABLE = is_module_available('librosa') + +if LIBROSA_AVAILABLE: + import numpy as np + import librosa + + +from torchaudio_unittest.common_utils import ( + TestBaseMixin, + nested_params, + get_whitenoise, + get_spectrogram, +) + + +@unittest.skipIf(not LIBROSA_AVAILABLE, "Librosa not available") +class Functional(TestBaseMixin): + """Test suite for functions in `functional` module.""" + dtype = torch.float64 + + @nested_params([0, 0.99]) + def test_griffinlim(self, momentum): + # FFT params + n_fft = 400 + win_length = n_fft + hop_length = n_fft // 4 + window = torch.hann_window(win_length) + power = 1 + # GriffinLim params + n_iter = 8 + + waveform = get_whitenoise(device=self.device, dtype=self.dtype) + specgram = get_spectrogram( + waveform, n_fft=n_fft, hop_length=hop_length, power=power, + win_length=win_length, window=window) + + result = F.griffinlim( + specgram, + window=window, + n_fft=n_fft, + hop_length=hop_length, + win_length=win_length, + power=power, + n_iter=n_iter, + momentum=momentum, + length=waveform.size(1), + rand_init=False) + expected = librosa.griffinlim( + specgram[0].cpu().numpy(), + n_iter=n_iter, + hop_length=hop_length, + momentum=momentum, + init=None, + length=waveform.size(1))[None, ...] + self.assertEqual(result, torch.from_numpy(expected), atol=5e-5, rtol=1e-07) + + @nested_params( + [ + param(), + param(n_mels=128, sample_rate=44100), + param(n_mels=128, fmin=2000.0, fmax=5000.0), + param(n_mels=56, fmin=100.0, fmax=9000.0), + param(n_mels=56, fmin=800.0, fmax=900.0), + param(n_mels=56, fmin=1900.0, fmax=900.0), + param(n_mels=10, fmin=1900.0, fmax=900.0), + ], + [param(norm=n) for n in [None, 'slaney']], + [param(mel_scale=s) for s in ['htk', 'slaney']], + ) + def test_create_fb(self, n_mels=40, sample_rate=22050, n_fft=2048, + fmin=0.0, fmax=8000.0, norm=None, mel_scale="htk"): + if (norm == "slaney" and StrictVersion(librosa.__version__) < StrictVersion("0.7.2")): + self.skipTest('Test is known to fail with older versions of librosa.') + if self.device != 'cpu': + self.skipTest('No need to run this test on CUDA') + + expected = librosa.filters.mel( + sr=sample_rate, + n_fft=n_fft, + n_mels=n_mels, + fmax=fmax, + fmin=fmin, + htk=mel_scale == "htk", + norm=norm).T + result = F.create_fb_matrix( + sample_rate=sample_rate, + n_mels=n_mels, + f_max=fmax, + f_min=fmin, + n_freqs=(n_fft // 2 + 1), + norm=norm, + mel_scale=mel_scale) + self.assertEqual(result, torch.from_numpy(expected), atol=7e-5, rtol=1.3e-6) + + def test_amplitude_to_DB_power(self): + amin = 1e-10 + db_multiplier = 0.0 + top_db = 80.0 + multiplier = 10.0 + + spec = get_spectrogram(get_whitenoise(device=self.device, dtype=self.dtype), power=2) + result = F.amplitude_to_DB(spec, multiplier, amin, db_multiplier, top_db) + expected = librosa.core.power_to_db(spec[0].cpu().numpy())[None, ...] + self.assertEqual(result, torch.from_numpy(expected)) + + def test_amplitude_to_DB(self): + amin = 1e-10 + db_multiplier = 0.0 + top_db = 80.0 + multiplier = 20.0 + + spec = get_spectrogram(get_whitenoise(device=self.device, dtype=self.dtype), power=1) + result = F.amplitude_to_DB(spec, multiplier, amin, db_multiplier, top_db) + expected = librosa.core.amplitude_to_db(spec[0].cpu().numpy())[None, ...] + self.assertEqual(result, torch.from_numpy(expected)) + + +@unittest.skipIf(not LIBROSA_AVAILABLE, "Librosa not available") +class FunctionalComplex(TestBaseMixin): + @nested_params( + [0.5, 1.01, 1.3], + [True, False], + ) + def test_phase_vocoder(self, rate, test_pseudo_complex): + hop_length = 256 + num_freq = 1025 + num_frames = 400 + torch.random.manual_seed(42) + + # Due to cummulative sum, numerical error in using torch.float32 will + # result in bottom right values of the stretched sectrogram to not + # match with librosa. + spec = torch.randn(num_freq, num_frames, device=self.device, dtype=torch.complex128) + phase_advance = torch.linspace( + 0, + np.pi * hop_length, + num_freq, + device=self.device, + dtype=torch.float64)[..., None] + + stretched = F.phase_vocoder( + torch.view_as_real(spec) if test_pseudo_complex else spec, + rate=rate, phase_advance=phase_advance) + + expected_stretched = librosa.phase_vocoder( + spec.cpu().numpy(), + rate=rate, + hop_length=hop_length) + + self.assertEqual( + torch.view_as_complex(stretched) if test_pseudo_complex else stretched, + torch.from_numpy(expected_stretched)) diff --git a/test/torchaudio_unittest/functional/torchscript_consistency_cpu_test.py b/test/torchaudio_unittest/functional/torchscript_consistency_cpu_test.py index 06871f9bde..d9d34eff76 100644 --- a/test/torchaudio_unittest/functional/torchscript_consistency_cpu_test.py +++ b/test/torchaudio_unittest/functional/torchscript_consistency_cpu_test.py @@ -1,7 +1,7 @@ import torch from torchaudio_unittest.common_utils import PytorchTestCase -from .torchscript_consistency_impl import Functional +from .torchscript_consistency_impl import Functional, FunctionalComplex class TestFunctionalFloat32(Functional, PytorchTestCase): @@ -12,3 +12,15 @@ class TestFunctionalFloat32(Functional, PytorchTestCase): class TestFunctionalFloat64(Functional, PytorchTestCase): dtype = torch.float64 device = torch.device('cpu') + + +class TestFunctionalComplex64(FunctionalComplex, PytorchTestCase): + complex_dtype = torch.complex64 + real_dtype = torch.float32 + device = torch.device('cpu') + + +class TestFunctionalComplex128(FunctionalComplex, PytorchTestCase): + complex_dtype = torch.complex128 + real_dtype = torch.float64 + device = torch.device('cpu') diff --git a/test/torchaudio_unittest/functional/torchscript_consistency_cuda_test.py b/test/torchaudio_unittest/functional/torchscript_consistency_cuda_test.py index 53ccbad3c9..026e09abfa 100644 --- a/test/torchaudio_unittest/functional/torchscript_consistency_cuda_test.py +++ b/test/torchaudio_unittest/functional/torchscript_consistency_cuda_test.py @@ -1,7 +1,7 @@ import torch from torchaudio_unittest.common_utils import skipIfNoCuda, PytorchTestCase -from .torchscript_consistency_impl import Functional +from .torchscript_consistency_impl import Functional, FunctionalComplex @skipIfNoCuda @@ -14,3 +14,17 @@ class TestFunctionalFloat32(Functional, PytorchTestCase): class TestFunctionalFloat64(Functional, PytorchTestCase): dtype = torch.float64 device = torch.device('cuda') + + +@skipIfNoCuda +class TestFunctionalComplex64(FunctionalComplex, PytorchTestCase): + complex_dtype = torch.complex64 + real_dtype = torch.float32 + device = torch.device('cuda') + + +@skipIfNoCuda +class TestFunctionalComplex128(FunctionalComplex, PytorchTestCase): + complex_dtype = torch.complex128 + real_dtype = torch.float64 + device = torch.device('cuda') diff --git a/test/torchaudio_unittest/functional/torchscript_consistency_impl.py b/test/torchaudio_unittest/functional/torchscript_consistency_impl.py index b6aec04d9c..9c34846b9e 100644 --- a/test/torchaudio_unittest/functional/torchscript_consistency_impl.py +++ b/test/torchaudio_unittest/functional/torchscript_consistency_impl.py @@ -3,16 +3,24 @@ import torch import torchaudio.functional as F +from parameterized import parameterized from torchaudio_unittest import common_utils +from torchaudio_unittest.common_utils import TempDirMixin, TestBaseMixin +from torchaudio_unittest.common_utils import ( + skipIfRocm, +) -class Functional(common_utils.TestBaseMixin): +class Functional(TempDirMixin, TestBaseMixin): """Implements test for `functinoal` modul that are performed for different devices""" def _assert_consistency(self, func, tensor, shape_only=False): tensor = tensor.to(device=self.device, dtype=self.dtype) - ts_func = torch.jit.script(func) + path = self.get_temp_path('func.zip') + torch.jit.script(func).save(path) + ts_func = torch.jit.load(path) + output = func(tensor) ts_output = ts_func(tensor) if shape_only: @@ -34,6 +42,7 @@ def func(tensor): tensor = common_utils.get_whitenoise() self._assert_consistency(func, tensor) + @skipIfRocm def test_griffinlim(self): def func(tensor): n_fft = 400 @@ -547,21 +556,6 @@ def func(tensor): tensor = common_utils.get_whitenoise(sample_rate=44100) self._assert_consistency(func, tensor) - def test_phase_vocoder(self): - def func(tensor, device: torch.device = self.device): - rate = 0.5 - hop_length = 256 - phase_advance = torch.linspace( - 0, - 3.14 * hop_length, - tensor.shape[-3], - dtype=torch.float64, - ).to(device)[..., None] - return F.phase_vocoder(tensor, rate, phase_advance) - - tensor = torch.randn(2, 1025, 400, 2) - self._assert_consistency(func, tensor) - @common_utils.skipIfNoKaldi def test_compute_kaldi_pitch(self): if self.dtype != torch.float32 or self.device != torch.device('cpu'): @@ -573,3 +567,43 @@ def func(tensor): tensor = common_utils.get_whitenoise(sample_rate=44100) self._assert_consistency(func, tensor) + + +class FunctionalComplex(TempDirMixin, TestBaseMixin): + complex_dtype = None + real_dtype = None + device = None + + def _assert_consistency(self, func, tensor, test_pseudo_complex=False): + assert tensor.is_complex() + tensor = tensor.to(device=self.device, dtype=self.complex_dtype) + + path = self.get_temp_path('func.zip') + torch.jit.script(func).save(path) + ts_func = torch.jit.load(path) + + if test_pseudo_complex: + tensor = torch.view_as_real(tensor) + output = func(tensor) + ts_output = ts_func(tensor) + self.assertEqual(ts_output, output) + + @parameterized.expand([(True, ), (False, )]) + def test_phase_vocoder(self, test_paseudo_complex): + def func(tensor): + is_complex = tensor.is_complex() + + n_freq = tensor.size(-2 if is_complex else -3) + rate = 0.5 + hop_length = 256 + phase_advance = torch.linspace( + 0, + 3.14 * hop_length, + n_freq, + dtype=(torch.real(tensor) if is_complex else tensor).dtype, + device=tensor.device, + )[..., None] + return F.phase_vocoder(tensor, rate, phase_advance) + + tensor = torch.view_as_complex(torch.randn(2, 1025, 400, 2)) + self._assert_consistency(func, tensor, test_paseudo_complex) diff --git a/test/torchaudio_unittest/transforms/autograd_cpu_test.py b/test/torchaudio_unittest/transforms/autograd_cpu_test.py new file mode 100644 index 0000000000..e4abfb237d --- /dev/null +++ b/test/torchaudio_unittest/transforms/autograd_cpu_test.py @@ -0,0 +1,6 @@ +from torchaudio_unittest.common_utils import PytorchTestCase +from .autograd_test_impl import AutogradTestMixin + + +class AutogradCPUTest(AutogradTestMixin, PytorchTestCase): + device = 'cpu' diff --git a/test/torchaudio_unittest/transforms/autograd_cuda_test.py b/test/torchaudio_unittest/transforms/autograd_cuda_test.py new file mode 100644 index 0000000000..ecccb9d897 --- /dev/null +++ b/test/torchaudio_unittest/transforms/autograd_cuda_test.py @@ -0,0 +1,10 @@ +from torchaudio_unittest.common_utils import ( + PytorchTestCase, + skipIfNoCuda, +) +from .autograd_test_impl import AutogradTestMixin + + +@skipIfNoCuda +class AutogradCUDATest(AutogradTestMixin, PytorchTestCase): + device = 'cuda' diff --git a/test/torchaudio_unittest/transforms/autograd_test_impl.py b/test/torchaudio_unittest/transforms/autograd_test_impl.py new file mode 100644 index 0000000000..438f623855 --- /dev/null +++ b/test/torchaudio_unittest/transforms/autograd_test_impl.py @@ -0,0 +1,183 @@ +from typing import List +import unittest + +from parameterized import parameterized +import torch +from torch.autograd import gradcheck, gradgradcheck +import torchaudio.transforms as T + +from torchaudio_unittest.common_utils import ( + TestBaseMixin, + get_whitenoise, + get_spectrogram, + nested_params, +) + + +class _DeterministicWrapper(torch.nn.Module): + """Helper transform wrapper to make the given transform deterministic""" + def __init__(self, transform, seed=0): + super().__init__() + self.seed = seed + self.transform = transform + + def forward(self, input: torch.Tensor): + torch.random.manual_seed(self.seed) + return self.transform(input) + + +class AutogradTestMixin(TestBaseMixin): + def assert_grad( + self, + transform: torch.nn.Module, + inputs: List[torch.Tensor], + *, + nondet_tol: float = 0.0, + ): + transform = transform.to(dtype=torch.float64, device=self.device) + + # gradcheck and gradgradcheck only pass if the input tensors are of dtype `torch.double` or + # `torch.cdouble`, when the default eps and tolerance values are used. + inputs_ = [] + for i in inputs: + if torch.is_tensor(i): + i = i.to( + dtype=torch.cdouble if i.is_complex() else torch.double, + device=self.device) + i.requires_grad = True + inputs_.append(i) + assert gradcheck(transform, inputs_) + assert gradgradcheck(transform, inputs_, nondet_tol=nondet_tol) + + @parameterized.expand([ + ({'pad': 0, 'normalized': False, 'power': None, 'return_complex': True}, ), + ({'pad': 3, 'normalized': False, 'power': None, 'return_complex': True}, ), + ({'pad': 0, 'normalized': True, 'power': None, 'return_complex': True}, ), + ({'pad': 3, 'normalized': True, 'power': None, 'return_complex': True}, ), + ({'pad': 0, 'normalized': False, 'power': None}, ), + ({'pad': 3, 'normalized': False, 'power': None}, ), + ({'pad': 0, 'normalized': True, 'power': None}, ), + ({'pad': 3, 'normalized': True, 'power': None}, ), + ({'pad': 0, 'normalized': False, 'power': 1.0}, ), + ({'pad': 3, 'normalized': False, 'power': 1.0}, ), + ({'pad': 0, 'normalized': True, 'power': 1.0}, ), + ({'pad': 3, 'normalized': True, 'power': 1.0}, ), + ({'pad': 0, 'normalized': False, 'power': 2.0}, ), + ({'pad': 3, 'normalized': False, 'power': 2.0}, ), + ({'pad': 0, 'normalized': True, 'power': 2.0}, ), + ({'pad': 3, 'normalized': True, 'power': 2.0}, ), + ]) + def test_spectrogram(self, kwargs): + # replication_pad1d_backward_cuda is not deteministic and + # gives very small (~2.7756e-17) difference. + # + # See https://github.com/pytorch/pytorch/issues/54093 + transform = T.Spectrogram(**kwargs) + waveform = get_whitenoise(sample_rate=8000, duration=0.05, n_channels=2) + self.assert_grad(transform, [waveform], nondet_tol=1e-10) + + def test_melspectrogram(self): + # replication_pad1d_backward_cuda is not deteministic and + # gives very small (~2.7756e-17) difference. + # + # See https://github.com/pytorch/pytorch/issues/54093 + sample_rate = 8000 + transform = T.MelSpectrogram(sample_rate=sample_rate) + waveform = get_whitenoise(sample_rate=sample_rate, duration=0.05, n_channels=2) + self.assert_grad(transform, [waveform], nondet_tol=1e-10) + + @nested_params( + [0, 0.99], + [False, True], + ) + def test_griffinlim(self, momentum, rand_init): + n_fft = 400 + power = 1 + n_iter = 3 + spec = get_spectrogram( + get_whitenoise(sample_rate=8000, duration=0.05, n_channels=2), + n_fft=n_fft, power=power) + transform = _DeterministicWrapper( + T.GriffinLim(n_fft=n_fft, n_iter=n_iter, momentum=momentum, rand_init=rand_init, power=power)) + self.assert_grad(transform, [spec]) + + @parameterized.expand([(False, ), (True, )]) + def test_mfcc(self, log_mels): + sample_rate = 8000 + transform = T.MFCC(sample_rate=sample_rate, log_mels=log_mels) + waveform = get_whitenoise(sample_rate=sample_rate, duration=0.05, n_channels=2) + self.assert_grad(transform, [waveform]) + + def test_compute_deltas(self): + transform = T.ComputeDeltas() + spec = torch.rand(10, 20) + self.assert_grad(transform, [spec]) + + @parameterized.expand([(8000, 8000), (8000, 4000), (4000, 8000)]) + def test_resample(self, orig_freq, new_freq): + transform = T.Resample(orig_freq=orig_freq, new_freq=new_freq) + waveform = get_whitenoise(sample_rate=8000, duration=0.05, n_channels=2) + self.assert_grad(transform, [waveform]) + + @parameterized.expand([("linear", ), ("exponential", ), ("logarithmic", ), ("quarter_sine", ), ("half_sine", )]) + def test_fade(self, fade_shape): + transform = T.Fade(fade_shape=fade_shape) + waveform = get_whitenoise(sample_rate=8000, duration=0.05, n_channels=2) + self.assert_grad(transform, [waveform], nondet_tol=1e-10) + + def test_spectral_centroid(self): + sample_rate = 8000 + transform = T.SpectralCentroid(sample_rate=sample_rate) + waveform = get_whitenoise(sample_rate=sample_rate, duration=0.05, n_channels=2) + self.assert_grad(transform, [waveform], nondet_tol=1e-10) + + def test_amplitude_to_db(self): + sample_rate = 8000 + transform = T.AmplitudeToDB() + waveform = get_whitenoise(sample_rate=sample_rate, duration=0.05, n_channels=2) + self.assert_grad(transform, [waveform]) + + @unittest.expectedFailure + def test_timestretch_zeros_fail(self): + """Test that ``T.TimeStretch`` fails gradcheck at 0 + + This is because ``F.phase_vocoder`` converts data from cartesian to polar coordinate, + which performs ``atan2(img, real)``, and gradient is not defined at 0. + """ + n_fft = 16 + transform = T.TimeStretch(n_freq=n_fft // 2 + 1, fixed_rate=0.99) + waveform = torch.zeros(2, 40) + spectrogram = get_spectrogram(waveform, n_fft=n_fft, power=None) + self.assert_grad(transform, [spectrogram]) + + @nested_params( + [0.7, 0.8, 0.9, 1.0, 1.3], + [False, True], + ) + def test_timestretch_non_zero(self, rate, test_pseudo_complex): + """Verify that ``T.TimeStretch`` does not fail if it's not close to 0 + + ``T.TimeStrech`` is not differentiable around 0, so this test checks the differentiability + for cases where input is not zero. + + As tested above, when spectrogram contains values close to zero, the gradients are unstable + and gradcheck fails. + + In this test, we generate spectrogram from random signal, then we push the points around + zero away from the origin. + + This process does not reflect the real use-case, and it is not practical for users, but + this helps us understand to what degree the function is differentiable and when not. + """ + n_fft = 16 + transform = T.TimeStretch(n_freq=n_fft // 2 + 1, fixed_rate=rate) + waveform = get_whitenoise(sample_rate=40, duration=1, n_channels=2) + spectrogram = get_spectrogram(waveform, n_fft=n_fft, power=None) + + # 1e-3 is too small (on CPU) + epsilon = 1e-2 + too_close = spectrogram.abs() < epsilon + spectrogram[too_close] = epsilon * spectrogram[too_close] / spectrogram[too_close].abs() + if test_pseudo_complex: + spectrogram = torch.view_as_real(spectrogram) + self.assert_grad(transform, [spectrogram]) diff --git a/test/torchaudio_unittest/transforms/batch_consistency_test.py b/test/torchaudio_unittest/transforms/batch_consistency_test.py index 745401c328..cab68e0152 100644 --- a/test/torchaudio_unittest/transforms/batch_consistency_test.py +++ b/test/torchaudio_unittest/transforms/batch_consistency_test.py @@ -1,6 +1,7 @@ """Test numerical consistency among single input and batched input.""" import torch import torchaudio +from parameterized import parameterized from torchaudio_unittest import common_utils @@ -130,40 +131,31 @@ def test_batch_mfcc(self): computed = torchaudio.transforms.MFCC()(waveform.repeat(3, 1, 1)) self.assertEqual(computed, expected, atol=1e-4, rtol=1e-5) - def test_batch_TimeStretch(self): - test_filepath = common_utils.get_asset_path('steam-train-whistle-daniel_simon.wav') - waveform, _ = torchaudio.load(test_filepath) # (2, 278756), 44100 - + @parameterized.expand([(True, ), (False, )]) + def test_batch_TimeStretch(self, test_pseudo_complex): rate = 2 + num_freq = 1025 + num_frames = 400 - complex_specgrams = torch.view_as_real( - torch.stft( - input=waveform, - n_fft=2048, - hop_length=512, - win_length=2048, - window=torch.hann_window(2048), - center=True, - pad_mode='reflect', - normalized=True, - onesided=True, - return_complex=True, - ) - ) + spec = torch.randn(num_freq, num_frames, dtype=torch.complex64) + pattern = [3, 1, 1, 1] + if test_pseudo_complex: + spec = torch.view_as_real(spec) + pattern += [1] # Single then transform then batch expected = torchaudio.transforms.TimeStretch( fixed_rate=rate, - n_freq=1025, + n_freq=num_freq, hop_length=512, - )(complex_specgrams).repeat(3, 1, 1, 1, 1) + )(spec).repeat(*pattern) # Batch then transform computed = torchaudio.transforms.TimeStretch( fixed_rate=rate, - n_freq=1025, + n_freq=num_freq, hop_length=512, - )(complex_specgrams.repeat(3, 1, 1, 1, 1)) + )(spec.repeat(*pattern)) self.assertEqual(computed, expected, atol=1e-5, rtol=1e-5) diff --git a/test/torchaudio_unittest/transforms/librosa_compatibility_cpu_test.py b/test/torchaudio_unittest/transforms/librosa_compatibility_cpu_test.py new file mode 100644 index 0000000000..300f4a3f71 --- /dev/null +++ b/test/torchaudio_unittest/transforms/librosa_compatibility_cpu_test.py @@ -0,0 +1,9 @@ +import torch + +from torchaudio_unittest.common_utils import PytorchTestCase +from .librosa_compatibility_test_impl import TransformsTestBase + + +class TestTransforms(TransformsTestBase, PytorchTestCase): + dtype = torch.float64 + device = torch.device('cpu') diff --git a/test/torchaudio_unittest/transforms/librosa_compatibility_cuda_test.py b/test/torchaudio_unittest/transforms/librosa_compatibility_cuda_test.py new file mode 100644 index 0000000000..d553458aca --- /dev/null +++ b/test/torchaudio_unittest/transforms/librosa_compatibility_cuda_test.py @@ -0,0 +1,10 @@ +import torch + +from torchaudio_unittest.common_utils import PytorchTestCase, skipIfNoCuda +from .librosa_compatibility_test_impl import TransformsTestBase + + +@skipIfNoCuda +class TestTransforms(TransformsTestBase, PytorchTestCase): + dtype = torch.float64 + device = torch.device('cuda') diff --git a/test/torchaudio_unittest/transforms/librosa_compatibility_test.py b/test/torchaudio_unittest/transforms/librosa_compatibility_test.py deleted file mode 100644 index c954100f35..0000000000 --- a/test/torchaudio_unittest/transforms/librosa_compatibility_test.py +++ /dev/null @@ -1,245 +0,0 @@ -"""Test suites for numerical compatibility with librosa""" -import os -import unittest - -import torch -import torchaudio -import torchaudio.functional as F -from torchaudio._internal.module_utils import is_module_available -from parameterized import parameterized, param - -LIBROSA_AVAILABLE = is_module_available('librosa') - -if LIBROSA_AVAILABLE: - import librosa - import scipy - -from torchaudio_unittest import common_utils - - -def _load_audio_asset(*asset_paths, **kwargs): - file_path = common_utils.get_asset_path(*asset_paths) - sound, sample_rate = torchaudio.load(file_path, **kwargs) - return sound, sample_rate - - -@unittest.skipIf(not LIBROSA_AVAILABLE, "Librosa not available") -class TestTransforms(common_utils.TorchaudioTestCase): - """Test suite for functions in `transforms` module.""" - - @parameterized.expand([ - param(n_fft=400, hop_length=200, power=2.0), - param(n_fft=600, hop_length=100, power=2.0), - param(n_fft=400, hop_length=200, power=3.0), - param(n_fft=200, hop_length=50, power=2.0), - ]) - def test_spectrogram(self, n_fft, hop_length, power): - sample_rate = 16000 - sound = common_utils.get_sinusoid(n_channels=1, sample_rate=sample_rate) - sound_librosa = sound.cpu().numpy().squeeze() - spect_transform = torchaudio.transforms.Spectrogram( - n_fft=n_fft, hop_length=hop_length, power=power) - out_librosa, _ = librosa.core.spectrum._spectrogram( - y=sound_librosa, n_fft=n_fft, hop_length=hop_length, power=power) - - out_torch = spect_transform(sound).squeeze().cpu() - self.assertEqual(out_torch, torch.from_numpy(out_librosa), atol=1e-5, rtol=1e-5) - - @parameterized.expand([ - param(norm=norm, mel_scale=mel_scale, **p.kwargs) - for p in [ - param(n_fft=400, hop_length=200, n_mels=128), - param(n_fft=600, hop_length=100, n_mels=128), - param(n_fft=200, hop_length=50, n_mels=128), - ] - for norm in [None, 'slaney'] - for mel_scale in ['htk', 'slaney'] - ]) - def test_mel_spectrogram(self, n_fft, hop_length, n_mels, norm, mel_scale): - sample_rate = 16000 - sound = common_utils.get_sinusoid(n_channels=1, sample_rate=sample_rate) - sound_librosa = sound.cpu().numpy().squeeze() - melspect_transform = torchaudio.transforms.MelSpectrogram( - sample_rate=sample_rate, window_fn=torch.hann_window, - hop_length=hop_length, n_mels=n_mels, n_fft=n_fft, norm=norm, mel_scale=mel_scale) - librosa_mel = librosa.feature.melspectrogram( - y=sound_librosa, sr=sample_rate, n_fft=n_fft, - hop_length=hop_length, n_mels=n_mels, htk=mel_scale == "htk", norm=norm) - librosa_mel_tensor = torch.from_numpy(librosa_mel) - torch_mel = melspect_transform(sound).squeeze().cpu() - self.assertEqual( - torch_mel.type(librosa_mel_tensor.dtype), librosa_mel_tensor, atol=5e-3, rtol=1e-5) - - @parameterized.expand([ - param(norm=norm, mel_scale=mel_scale, **p.kwargs) - for p in [ - param(n_fft=400, hop_length=200, power=2.0, n_mels=128), - param(n_fft=600, hop_length=100, power=2.0, n_mels=128), - param(n_fft=400, hop_length=200, power=3.0, n_mels=128), - # NOTE: Test passes offline, but fails on TravisCI (and CircleCI), see #372. - param(n_fft=200, hop_length=50, power=2.0, n_mels=128, skip_ci=True), - ] - for norm in [None, 'slaney'] - for mel_scale in ['htk', 'slaney'] - ]) - def test_s2db(self, n_fft, hop_length, power, n_mels, norm, mel_scale, skip_ci=False): - if skip_ci and 'CI' in os.environ: - self.skipTest('Test is known to fail on CI') - sample_rate = 16000 - sound = common_utils.get_sinusoid(n_channels=1, sample_rate=sample_rate) - sound_librosa = sound.cpu().numpy().squeeze() - spect_transform = torchaudio.transforms.Spectrogram( - n_fft=n_fft, hop_length=hop_length, power=power) - out_librosa, _ = librosa.core.spectrum._spectrogram( - y=sound_librosa, n_fft=n_fft, hop_length=hop_length, power=power) - melspect_transform = torchaudio.transforms.MelSpectrogram( - sample_rate=sample_rate, window_fn=torch.hann_window, - hop_length=hop_length, n_mels=n_mels, n_fft=n_fft, norm=norm, mel_scale=mel_scale) - librosa_mel = librosa.feature.melspectrogram( - y=sound_librosa, sr=sample_rate, n_fft=n_fft, - hop_length=hop_length, n_mels=n_mels, htk=mel_scale == "htk", norm=norm) - - power_to_db_transform = torchaudio.transforms.AmplitudeToDB('power', 80.) - power_to_db_torch = power_to_db_transform(spect_transform(sound)).squeeze().cpu() - power_to_db_librosa = librosa.core.spectrum.power_to_db(out_librosa) - self.assertEqual(power_to_db_torch, torch.from_numpy(power_to_db_librosa), atol=5e-3, rtol=1e-5) - - mag_to_db_transform = torchaudio.transforms.AmplitudeToDB('magnitude', 80.) - mag_to_db_torch = mag_to_db_transform(torch.abs(sound)).squeeze().cpu() - mag_to_db_librosa = librosa.core.spectrum.amplitude_to_db(sound_librosa) - self.assertEqual(mag_to_db_torch, torch.from_numpy(mag_to_db_librosa), atol=5e-3, rtol=1e-5) - - power_to_db_torch = power_to_db_transform(melspect_transform(sound)).squeeze().cpu() - db_librosa = librosa.core.spectrum.power_to_db(librosa_mel) - db_librosa_tensor = torch.from_numpy(db_librosa) - self.assertEqual( - power_to_db_torch.type(db_librosa_tensor.dtype), db_librosa_tensor, atol=5e-3, rtol=1e-5) - - @parameterized.expand([ - param(n_fft=400, hop_length=200, n_mels=128, n_mfcc=40), - param(n_fft=600, hop_length=100, n_mels=128, n_mfcc=20), - param(n_fft=200, hop_length=50, n_mels=128, n_mfcc=50), - ]) - def test_mfcc(self, n_fft, hop_length, n_mels, n_mfcc): - sample_rate = 16000 - sound = common_utils.get_sinusoid(n_channels=1, sample_rate=sample_rate) - sound_librosa = sound.cpu().numpy().squeeze() - librosa_mel = librosa.feature.melspectrogram( - y=sound_librosa, sr=sample_rate, n_fft=n_fft, - hop_length=hop_length, n_mels=n_mels, htk=True, norm=None) - db_librosa = librosa.core.spectrum.power_to_db(librosa_mel) - - # librosa.feature.mfcc doesn't pass kwargs properly since some of the - # kwargs for melspectrogram and mfcc are the same. We just follow the - # function body in - # https://librosa.github.io/librosa/_modules/librosa/feature/spectral.html#melspectrogram - # to mirror this function call with correct args: - # - # librosa_mfcc = librosa.feature.mfcc( - # y=sound_librosa, sr=sample_rate, n_mfcc = n_mfcc, - # hop_length=hop_length, n_fft=n_fft, htk=True, norm=None, n_mels=n_mels) - - librosa_mfcc = scipy.fftpack.dct(db_librosa, axis=0, type=2, norm='ortho')[:n_mfcc] - librosa_mfcc_tensor = torch.from_numpy(librosa_mfcc) - - melkwargs = {'hop_length': hop_length, 'n_fft': n_fft} - mfcc_transform = torchaudio.transforms.MFCC( - sample_rate=sample_rate, n_mfcc=n_mfcc, norm='ortho', melkwargs=melkwargs) - torch_mfcc = mfcc_transform(sound).squeeze().cpu() - - self.assertEqual( - torch_mfcc.type(librosa_mfcc_tensor.dtype), librosa_mfcc_tensor, atol=5e-3, rtol=1e-5) - - @parameterized.expand([ - param(n_fft=400, hop_length=200), - param(n_fft=600, hop_length=100), - param(n_fft=200, hop_length=50), - ]) - def test_spectral_centroid(self, n_fft, hop_length): - sample_rate = 16000 - sound = common_utils.get_sinusoid(n_channels=1, sample_rate=sample_rate) - sound_librosa = sound.cpu().numpy().squeeze() - spect_centroid = torchaudio.transforms.SpectralCentroid( - sample_rate=sample_rate, n_fft=n_fft, hop_length=hop_length) - out_torch = spect_centroid(sound).squeeze().cpu() - - out_librosa = librosa.feature.spectral_centroid( - y=sound_librosa, sr=sample_rate, n_fft=n_fft, hop_length=hop_length) - out_librosa = torch.from_numpy(out_librosa)[0] - - self.assertEqual(out_torch.type(out_librosa.dtype), out_librosa, atol=1e-5, rtol=1e-5) - - def test_MelScale(self): - """MelScale transform is comparable to that of librosa""" - n_fft = 2048 - n_mels = 256 - hop_length = n_fft // 4 - sample_rate = 44100 - sound = common_utils.get_whitenoise(sample_rate=sample_rate, duration=60) - sound = sound.mean(dim=0, keepdim=True) - spec_ta = F.spectrogram( - sound, pad=0, window=torch.hann_window(n_fft), n_fft=n_fft, - hop_length=hop_length, win_length=n_fft, power=2, normalized=False) - spec_lr = spec_ta.cpu().numpy().squeeze() - # Perform MelScale with torchaudio and librosa - melspec_ta = torchaudio.transforms.MelScale(n_mels=n_mels, sample_rate=sample_rate)(spec_ta) - melspec_lr = librosa.feature.melspectrogram( - S=spec_lr, sr=sample_rate, n_fft=n_fft, hop_length=hop_length, - win_length=n_fft, center=True, window='hann', n_mels=n_mels, htk=True, norm=None) - # Note: Using relaxed rtol instead of atol - self.assertEqual(melspec_ta, torch.from_numpy(melspec_lr[None, ...]), atol=1e-8, rtol=1e-3) - - def test_InverseMelScale(self): - """InverseMelScale transform is comparable to that of librosa""" - n_fft = 2048 - n_mels = 256 - n_stft = n_fft // 2 + 1 - hop_length = n_fft // 4 - - # Prepare mel spectrogram input. We use torchaudio to compute one. - path = common_utils.get_asset_path('steam-train-whistle-daniel_simon.wav') - sound, sample_rate = common_utils.load_wav(path) - sound = sound[:, 2**10:2**10 + 2**14] - sound = sound.mean(dim=0, keepdim=True) - spec_orig = F.spectrogram( - sound, pad=0, window=torch.hann_window(n_fft), n_fft=n_fft, - hop_length=hop_length, win_length=n_fft, power=2, normalized=False) - melspec_ta = torchaudio.transforms.MelScale(n_mels=n_mels, sample_rate=sample_rate)(spec_orig) - melspec_lr = melspec_ta.cpu().numpy().squeeze() - # Perform InverseMelScale with torch audio and librosa - spec_ta = torchaudio.transforms.InverseMelScale( - n_stft, n_mels=n_mels, sample_rate=sample_rate)(melspec_ta) - spec_lr = librosa.feature.inverse.mel_to_stft( - melspec_lr, sr=sample_rate, n_fft=n_fft, power=2.0, htk=True, norm=None) - spec_lr = torch.from_numpy(spec_lr[None, ...]) - - # Align dimensions - # librosa does not return power spectrogram while torchaudio returns power spectrogram - spec_orig = spec_orig.sqrt() - spec_ta = spec_ta.sqrt() - - threshold = 2.0 - # This threshold was chosen empirically, based on the following observation - # - # torch.dist(spec_lr, spec_ta, p=float('inf')) - # >>> tensor(1.9666) - # - # The spectrograms reconstructed by librosa and torchaudio are not comparable elementwise. - # This is because they use different approximation algorithms and resulting values can live - # in different magnitude. (although most of them are very close) - # See - # https://github.com/pytorch/audio/pull/366 for the discussion of the choice of algorithm - # https://github.com/pytorch/audio/pull/448/files#r385747021 for the distribution of P-inf - # distance over frequencies. - self.assertEqual(spec_ta, spec_lr, atol=threshold, rtol=1e-5) - - threshold = 1700.0 - # This threshold was chosen empirically, based on the following observations - # - # torch.dist(spec_orig, spec_ta, p=1) - # >>> tensor(1644.3516) - # torch.dist(spec_orig, spec_lr, p=1) - # >>> tensor(1420.7103) - # torch.dist(spec_lr, spec_ta, p=1) - # >>> tensor(943.2759) - assert torch.dist(spec_orig, spec_ta, p=1) < threshold diff --git a/test/torchaudio_unittest/transforms/librosa_compatibility_test_impl.py b/test/torchaudio_unittest/transforms/librosa_compatibility_test_impl.py new file mode 100644 index 0000000000..9bc8edbb20 --- /dev/null +++ b/test/torchaudio_unittest/transforms/librosa_compatibility_test_impl.py @@ -0,0 +1,141 @@ +import unittest + +import torch +import torchaudio.transforms as T +from torchaudio._internal.module_utils import is_module_available +from parameterized import param, parameterized + +from torchaudio_unittest.common_utils import ( + TestBaseMixin, + get_whitenoise, + get_sinusoid, + get_spectrogram, + nested_params, +) + +LIBROSA_AVAILABLE = is_module_available('librosa') + +if LIBROSA_AVAILABLE: + import librosa + + +@unittest.skipIf(not LIBROSA_AVAILABLE, "Librosa not available") +class TransformsTestBase(TestBaseMixin): + @parameterized.expand([ + param(n_fft=400, hop_length=200, power=2.0), + param(n_fft=600, hop_length=100, power=2.0), + param(n_fft=400, hop_length=200, power=3.0), + param(n_fft=200, hop_length=50, power=2.0), + ]) + def test_Spectrogram(self, n_fft, hop_length, power): + sample_rate = 16000 + waveform = get_whitenoise( + sample_rate=sample_rate, n_channels=1, + ).to(self.device, self.dtype) + + expected = librosa.core.spectrum._spectrogram( + y=waveform[0].cpu().numpy(), + n_fft=n_fft, hop_length=hop_length, power=power)[0] + + result = T.Spectrogram( + n_fft=n_fft, hop_length=hop_length, power=power, + ).to(self.device, self.dtype)(waveform)[0] + self.assertEqual(result, torch.from_numpy(expected), atol=1e-5, rtol=1e-5) + + def test_Spectrogram_complex(self): + n_fft = 400 + hop_length = 200 + sample_rate = 16000 + waveform = get_whitenoise( + sample_rate=sample_rate, n_channels=1, + ).to(self.device, self.dtype) + + expected = librosa.core.spectrum._spectrogram( + y=waveform[0].cpu().numpy(), + n_fft=n_fft, hop_length=hop_length, power=1)[0] + + result = T.Spectrogram( + n_fft=n_fft, hop_length=hop_length, power=None, return_complex=True, + ).to(self.device, self.dtype)(waveform)[0] + self.assertEqual(result.abs(), torch.from_numpy(expected), atol=1e-5, rtol=1e-5) + + @nested_params( + [ + param(n_fft=400, hop_length=200, n_mels=64), + param(n_fft=600, hop_length=100, n_mels=128), + param(n_fft=200, hop_length=50, n_mels=32), + ], + [param(norm=norm) for norm in [None, 'slaney']], + [param(mel_scale=mel_scale) for mel_scale in ['htk', 'slaney']], + ) + def test_MelSpectrogram(self, n_fft, hop_length, n_mels, norm, mel_scale): + sample_rate = 16000 + waveform = get_sinusoid( + sample_rate=sample_rate, n_channels=1, + ).to(self.device, self.dtype) + + expected = librosa.feature.melspectrogram( + y=waveform[0].cpu().numpy(), + sr=sample_rate, n_fft=n_fft, + hop_length=hop_length, n_mels=n_mels, norm=norm, + htk=mel_scale == "htk") + result = T.MelSpectrogram( + sample_rate=sample_rate, window_fn=torch.hann_window, + hop_length=hop_length, n_mels=n_mels, + n_fft=n_fft, norm=norm, mel_scale=mel_scale, + ).to(self.device, self.dtype)(waveform)[0] + self.assertEqual(result, torch.from_numpy(expected), atol=5e-4, rtol=1e-5) + + def test_magnitude_to_db(self): + spectrogram = get_spectrogram( + get_whitenoise(), n_fft=400, power=2).to(self.device, self.dtype) + result = T.AmplitudeToDB('magnitude', 80.).to(self.device, self.dtype)(spectrogram)[0] + expected = librosa.core.spectrum.amplitude_to_db(spectrogram[0].cpu().numpy()) + self.assertEqual(result, torch.from_numpy(expected)) + + def test_power_to_db(self): + spectrogram = get_spectrogram( + get_whitenoise(), n_fft=400, power=2).to(self.device, self.dtype) + result = T.AmplitudeToDB('power', 80.).to(self.device, self.dtype)(spectrogram)[0] + expected = librosa.core.spectrum.power_to_db(spectrogram[0].cpu().numpy()) + self.assertEqual(result, torch.from_numpy(expected)) + + @nested_params([ + param(n_fft=400, hop_length=200, n_mels=64, n_mfcc=40), + param(n_fft=600, hop_length=100, n_mels=128, n_mfcc=20), + param(n_fft=200, hop_length=50, n_mels=32, n_mfcc=25), + ]) + def test_mfcc(self, n_fft, hop_length, n_mels, n_mfcc): + sample_rate = 16000 + waveform = get_whitenoise( + sample_rate=sample_rate, n_channels=1).to(self.device, self.dtype) + result = T.MFCC( + sample_rate=sample_rate, n_mfcc=n_mfcc, norm='ortho', + melkwargs={'hop_length': hop_length, 'n_fft': n_fft, 'n_mels': n_mels}, + ).to(self.device, self.dtype)(waveform)[0] + + melspec = librosa.feature.melspectrogram( + y=waveform[0].cpu().numpy(), sr=sample_rate, n_fft=n_fft, + win_length=n_fft, hop_length=hop_length, + n_mels=n_mels, htk=True, norm=None) + expected = librosa.feature.mfcc( + S=librosa.core.spectrum.power_to_db(melspec), + n_mfcc=n_mfcc, dct_type=2, norm='ortho') + self.assertEqual(result, torch.from_numpy(expected), atol=5e-4, rtol=1e-5) + + @parameterized.expand([ + param(n_fft=400, hop_length=200), + param(n_fft=600, hop_length=100), + param(n_fft=200, hop_length=50), + ]) + def test_spectral_centroid(self, n_fft, hop_length): + sample_rate = 16000 + waveform = get_whitenoise( + sample_rate=sample_rate, n_channels=1).to(self.device, self.dtype) + + result = T.SpectralCentroid( + sample_rate=sample_rate, n_fft=n_fft, hop_length=hop_length, + ).to(self.device, self.dtype)(waveform) + expected = librosa.feature.spectral_centroid( + y=waveform[0].cpu().numpy(), sr=sample_rate, n_fft=n_fft, hop_length=hop_length) + self.assertEqual(result, torch.from_numpy(expected), atol=5e-4, rtol=1e-5) diff --git a/test/torchaudio_unittest/transforms/torchscript_consistency_cpu_test.py b/test/torchaudio_unittest/transforms/torchscript_consistency_cpu_test.py index 9092f3a64b..4de32a57bb 100644 --- a/test/torchaudio_unittest/transforms/torchscript_consistency_cpu_test.py +++ b/test/torchaudio_unittest/transforms/torchscript_consistency_cpu_test.py @@ -1,7 +1,7 @@ import torch from torchaudio_unittest.common_utils import PytorchTestCase -from .torchscript_consistency_impl import Transforms +from .torchscript_consistency_impl import Transforms, TransformsComplex class TestTransformsFloat32(Transforms, PytorchTestCase): @@ -12,3 +12,15 @@ class TestTransformsFloat32(Transforms, PytorchTestCase): class TestTransformsFloat64(Transforms, PytorchTestCase): dtype = torch.float64 device = torch.device('cpu') + + +class TestTransformsComplex64(TransformsComplex, PytorchTestCase): + complex_dtype = torch.complex64 + real_dtype = torch.float32 + device = torch.device('cpu') + + +class TestTransformsComplex128(TransformsComplex, PytorchTestCase): + complex_dtype = torch.complex128 + real_dtype = torch.float64 + device = torch.device('cpu') diff --git a/test/torchaudio_unittest/transforms/torchscript_consistency_cuda_test.py b/test/torchaudio_unittest/transforms/torchscript_consistency_cuda_test.py index 7425647bab..2435b82589 100644 --- a/test/torchaudio_unittest/transforms/torchscript_consistency_cuda_test.py +++ b/test/torchaudio_unittest/transforms/torchscript_consistency_cuda_test.py @@ -1,7 +1,7 @@ import torch from torchaudio_unittest.common_utils import skipIfNoCuda, PytorchTestCase -from .torchscript_consistency_impl import Transforms +from .torchscript_consistency_impl import Transforms, TransformsComplex @skipIfNoCuda @@ -14,3 +14,17 @@ class TestTransformsFloat32(Transforms, PytorchTestCase): class TestTransformsFloat64(Transforms, PytorchTestCase): dtype = torch.float64 device = torch.device('cuda') + + +@skipIfNoCuda +class TestTransformsComplex64(TransformsComplex, PytorchTestCase): + complex_dtype = torch.complex64 + real_dtype = torch.float32 + device = torch.device('cuda') + + +@skipIfNoCuda +class TestTransformsComplex128(TransformsComplex, PytorchTestCase): + complex_dtype = torch.complex128 + real_dtype = torch.float64 + device = torch.device('cuda') diff --git a/test/torchaudio_unittest/transforms/torchscript_consistency_impl.py b/test/torchaudio_unittest/transforms/torchscript_consistency_impl.py index 492e1e4a92..64ecbe53f7 100644 --- a/test/torchaudio_unittest/transforms/torchscript_consistency_impl.py +++ b/test/torchaudio_unittest/transforms/torchscript_consistency_impl.py @@ -2,17 +2,26 @@ import torch import torchaudio.transforms as T +from parameterized import parameterized from torchaudio_unittest import common_utils +from torchaudio_unittest.common_utils import ( + skipIfRocm, + TempDirMixin, + TestBaseMixin, +) -class Transforms(common_utils.TestBaseMixin): +class Transforms(TempDirMixin, TestBaseMixin): """Implements test for Transforms that are performed for different devices""" def _assert_consistency(self, transform, tensor): tensor = tensor.to(device=self.device, dtype=self.dtype) transform = transform.to(device=self.device, dtype=self.dtype) - ts_transform = torch.jit.script(transform) + path = self.get_temp_path('transform.zip') + torch.jit.script(transform).save(path) + ts_transform = torch.jit.load(path) + output = transform(tensor) ts_output = ts_transform(tensor) self.assertEqual(ts_output, output) @@ -21,6 +30,11 @@ def test_Spectrogram(self): tensor = torch.rand((1, 1000)) self._assert_consistency(T.Spectrogram(), tensor) + def test_Spectrogram_return_complex(self): + tensor = torch.rand((1, 1000)) + self._assert_consistency(T.Spectrogram(power=None, return_complex=True), tensor) + + @skipIfRocm def test_GriffinLim(self): tensor = torch.rand((1, 201, 6)) self._assert_consistency(T.GriffinLim(length=1000, rand_init=False), tensor) @@ -30,8 +44,8 @@ def test_AmplitudeToDB(self): self._assert_consistency(T.AmplitudeToDB(), spec) def test_MelScale(self): - spec_f = torch.rand((1, 6, 201)) - self._assert_consistency(T.MelScale(), spec_f) + spec_f = torch.rand((1, 201, 6)) + self._assert_consistency(T.MelScale(n_stft=201), spec_f) def test_MelSpectrogram(self): tensor = torch.rand((1, 1000)) @@ -58,16 +72,6 @@ def test_MuLawDecoding(self): tensor = torch.rand((1, 10)) self._assert_consistency(T.MuLawDecoding(), tensor) - def test_TimeStretch(self): - n_freq = 400 - hop_length = 512 - fixed_rate = 1.3 - tensor = torch.rand((10, 2, n_freq, 10, 2)) - self._assert_consistency( - T.TimeStretch(n_freq=n_freq, hop_length=hop_length, fixed_rate=fixed_rate), - tensor, - ) - def test_Fade(self): waveform = common_utils.get_whitenoise() fade_in_len = 3000 @@ -99,3 +103,37 @@ def test_SpectralCentroid(self): sample_rate = 44100 waveform = common_utils.get_whitenoise(sample_rate=sample_rate) self._assert_consistency(T.SpectralCentroid(sample_rate=sample_rate), waveform) + + +class TransformsComplex(TempDirMixin, TestBaseMixin): + complex_dtype = None + real_dtype = None + device = None + + def _assert_consistency(self, transform, tensor, test_pseudo_complex=False): + assert tensor.is_complex() + tensor = tensor.to(device=self.device, dtype=self.complex_dtype) + transform = transform.to(device=self.device, dtype=self.real_dtype) + + path = self.get_temp_path('transform.zip') + torch.jit.script(transform).save(path) + ts_transform = torch.jit.load(path) + + if test_pseudo_complex: + tensor = torch.view_as_real(tensor) + + output = transform(tensor) + ts_output = ts_transform(tensor) + self.assertEqual(ts_output, output) + + @parameterized.expand([(True, ), (False, )]) + def test_TimeStretch(self, test_pseudo_complex): + n_freq = 400 + hop_length = 512 + fixed_rate = 1.3 + tensor = torch.view_as_complex(torch.rand((10, 2, n_freq, 10, 2))) + self._assert_consistency( + T.TimeStretch(n_freq=n_freq, hop_length=hop_length, fixed_rate=fixed_rate), + tensor, + test_pseudo_complex + ) diff --git a/test/torchaudio_unittest/transforms/transforms_cpu_test.py b/test/torchaudio_unittest/transforms/transforms_cpu_test.py new file mode 100644 index 0000000000..5177b9a455 --- /dev/null +++ b/test/torchaudio_unittest/transforms/transforms_cpu_test.py @@ -0,0 +1,14 @@ +import torch + +from torchaudio_unittest.common_utils import PytorchTestCase +from . transforms_test_impl import TransformsTestBase + + +class TransformsCPUFloat32Test(TransformsTestBase, PytorchTestCase): + device = 'cpu' + dtype = torch.float32 + + +class TransformsCPUFloat64Test(TransformsTestBase, PytorchTestCase): + device = 'cpu' + dtype = torch.float64 diff --git a/test/torchaudio_unittest/transforms/transforms_cuda_test.py b/test/torchaudio_unittest/transforms/transforms_cuda_test.py new file mode 100644 index 0000000000..9489660384 --- /dev/null +++ b/test/torchaudio_unittest/transforms/transforms_cuda_test.py @@ -0,0 +1,19 @@ +import torch + +from torchaudio_unittest.common_utils import ( + PytorchTestCase, + skipIfNoCuda, +) +from . transforms_test_impl import TransformsTestBase + + +@skipIfNoCuda +class TransformsCUDAFloat32Test(TransformsTestBase, PytorchTestCase): + device = 'cuda' + dtype = torch.float32 + + +@skipIfNoCuda +class TransformsCUDAFloat64Test(TransformsTestBase, PytorchTestCase): + device = 'cuda' + dtype = torch.float64 diff --git a/test/torchaudio_unittest/transforms/transforms_test_impl.py b/test/torchaudio_unittest/transforms/transforms_test_impl.py new file mode 100644 index 0000000000..8a92662200 --- /dev/null +++ b/test/torchaudio_unittest/transforms/transforms_test_impl.py @@ -0,0 +1,61 @@ +import torch +import torchaudio.transforms as T + +from torchaudio_unittest.common_utils import ( + TestBaseMixin, + get_whitenoise, + get_spectrogram, +) + + +def _get_ratio(mat): + return (mat.sum() / mat.numel()).item() + + +class TransformsTestBase(TestBaseMixin): + def test_InverseMelScale(self): + """Gauge the quality of InverseMelScale transform. + + As InverseMelScale is currently implemented with + random initialization + iterative optimization, + it is not practically possible to assert the difference between + the estimated spectrogram and the original spectrogram as a whole. + Estimated spectrogram has very huge descrepency locally. + Thus in this test we gauge what percentage of elements are bellow + certain tolerance. + At the moment, the quality of estimated spectrogram is not good. + When implementation is changed in a way it makes the quality even worse, + this test will fail. + """ + n_fft = 400 + power = 1 + n_mels = 64 + sample_rate = 8000 + + n_stft = n_fft // 2 + 1 + + # Generate reference spectrogram and input mel-scaled spectrogram + expected = get_spectrogram( + get_whitenoise(sample_rate=sample_rate, duration=1, n_channels=2), + n_fft=n_fft, power=power).to(self.device, self.dtype) + input = T.MelScale( + n_mels=n_mels, sample_rate=sample_rate + ).to(self.device, self.dtype)(expected) + + # Run transform + transform = T.InverseMelScale( + n_stft, n_mels=n_mels, sample_rate=sample_rate).to(self.device, self.dtype) + torch.random.manual_seed(0) + result = transform(input) + + # Compare + epsilon = 1e-60 + relative_diff = torch.abs((result - expected) / (expected + epsilon)) + + for tol in [1e-1, 1e-3, 1e-5, 1e-10]: + print( + f"Ratio of relative diff smaller than {tol:e} is " + f"{_get_ratio(relative_diff < tol)}") + assert _get_ratio(relative_diff < 1e-1) > 0.2 + assert _get_ratio(relative_diff < 1e-3) > 5e-3 + assert _get_ratio(relative_diff < 1e-5) > 1e-5 diff --git a/torchaudio/datasets/utils.py b/torchaudio/datasets/utils.py index 189866374f..b9f3b14360 100644 --- a/torchaudio/datasets/utils.py +++ b/torchaudio/datasets/utils.py @@ -29,7 +29,8 @@ def stream_url(url: str, # If we already have the whole file, there is no need to download it again req = urllib.request.Request(url, method="HEAD") - url_size = int(urllib.request.urlopen(req).info().get("Content-Length", -1)) + with urllib.request.urlopen(req) as response: + url_size = int(response.info().get("Content-Length", -1)) if url_size == start_byte: return diff --git a/torchaudio/functional/filtering.py b/torchaudio/functional/filtering.py index 82d9727876..ad594350d3 100644 --- a/torchaudio/functional/filtering.py +++ b/torchaudio/functional/filtering.py @@ -73,8 +73,8 @@ def allpass_biquad( Args: waveform(torch.Tensor): audio waveform of dimension of `(..., time)` sample_rate (int): sampling rate of the waveform, e.g. 44100 (Hz) - central_freq (float): central frequency (in Hz) - Q (float, optional): https://en.wikipedia.org/wiki/Q_factor (Default: ``0.707``) + central_freq (float or torch.Tensor): central frequency (in Hz) + Q (float or torch.Tensor, optional): https://en.wikipedia.org/wiki/Q_factor (Default: ``0.707``) Returns: Tensor: Waveform of dimension of `(..., time)` @@ -83,14 +83,20 @@ def allpass_biquad( http://sox.sourceforge.net/sox.html https://www.w3.org/2011/audio/audio-eq-cookbook.html#APF """ + dtype = waveform.dtype + device = waveform.device + central_freq = torch.as_tensor(central_freq, dtype=dtype, device=device) + Q = torch.as_tensor(Q, dtype=dtype, device=device) + w0 = 2 * math.pi * central_freq / sample_rate - alpha = math.sin(w0) / 2 / Q + + alpha = torch.sin(w0) / 2 / Q b0 = 1 - alpha - b1 = -2 * math.cos(w0) + b1 = -2 * torch.cos(w0) b2 = 1 + alpha a0 = 1 + alpha - a1 = -2 * math.cos(w0) + a1 = -2 * torch.cos(w0) a2 = 1 - alpha return biquad(waveform, b0, b1, b2, a0, a1, a2) @@ -107,8 +113,8 @@ def band_biquad( Args: waveform (Tensor): audio waveform of dimension of `(..., time)` sample_rate (int): sampling rate of the waveform, e.g. 44100 (Hz) - central_freq (float): central frequency (in Hz) - Q (float, optional): https://en.wikipedia.org/wiki/Q_factor (Default: ``0.707``). + central_freq (float or torch.Tensor): central frequency (in Hz) + Q (float or torch.Tensor, optional): https://en.wikipedia.org/wiki/Q_factor (Default: ``0.707``). noise (bool, optional) : If ``True``, uses the alternate mode for un-pitched audio (e.g. percussion). If ``False``, uses mode oriented to pitched audio, i.e. voice, singing, or instrumental music (Default: ``False``). @@ -120,18 +126,23 @@ def band_biquad( http://sox.sourceforge.net/sox.html https://www.w3.org/2011/audio/audio-eq-cookbook.html#APF """ + dtype = waveform.dtype + device = waveform.device + central_freq = torch.as_tensor(central_freq, dtype=dtype, device=device) + Q = torch.as_tensor(Q, dtype=dtype, device=device) + w0 = 2 * math.pi * central_freq / sample_rate bw_Hz = central_freq / Q a0 = 1.0 - a2 = math.exp(-2 * math.pi * bw_Hz / sample_rate) - a1 = -4 * a2 / (1 + a2) * math.cos(w0) + a2 = torch.exp(-2 * math.pi * bw_Hz / sample_rate) + a1 = -4 * a2 / (1 + a2) * torch.cos(w0) - b0 = math.sqrt(1 - a1 * a1 / (4 * a2)) * (1 - a2) + b0 = torch.sqrt(1 - a1 * a1 / (4 * a2)) * (1 - a2) if noise: - mult = math.sqrt(((1 + a2) * (1 + a2) - a1 * a1) * (1 - a2) / (1 + a2)) / b0 - b0 *= mult + mult = torch.sqrt(((1 + a2) * (1 + a2) - a1 * a1) * (1 - a2) / (1 + a2)) / b0 + b0 = mult * b0 b1 = 0.0 b2 = 0.0 @@ -151,8 +162,8 @@ def bandpass_biquad( Args: waveform (Tensor): audio waveform of dimension of `(..., time)` sample_rate (int): sampling rate of the waveform, e.g. 44100 (Hz) - central_freq (float): central frequency (in Hz) - Q (float, optional): https://en.wikipedia.org/wiki/Q_factor (Default: ``0.707``) + central_freq (float or torch.Tensor): central frequency (in Hz) + Q (float or torch.Tensor, optional): https://en.wikipedia.org/wiki/Q_factor (Default: ``0.707``) const_skirt_gain (bool, optional) : If ``True``, uses a constant skirt gain (peak gain = Q). If ``False``, uses a constant 0dB peak gain. (Default: ``False``) @@ -163,15 +174,20 @@ def bandpass_biquad( http://sox.sourceforge.net/sox.html https://www.w3.org/2011/audio/audio-eq-cookbook.html#APF """ + dtype = waveform.dtype + device = waveform.device + central_freq = torch.as_tensor(central_freq, dtype=dtype, device=device) + Q = torch.as_tensor(Q, dtype=dtype, device=device) + w0 = 2 * math.pi * central_freq / sample_rate - alpha = math.sin(w0) / 2 / Q + alpha = torch.sin(w0) / 2 / Q - temp = math.sin(w0) / 2 if const_skirt_gain else alpha + temp = torch.sin(w0) / 2 if const_skirt_gain else alpha b0 = temp b1 = 0.0 b2 = -temp a0 = 1 + alpha - a1 = -2 * math.cos(w0) + a1 = -2 * torch.cos(w0) a2 = 1 - alpha return biquad(waveform, b0, b1, b2, a0, a1, a2) @@ -184,8 +200,8 @@ def bandreject_biquad( Args: waveform (Tensor): audio waveform of dimension of `(..., time)` sample_rate (int): sampling rate of the waveform, e.g. 44100 (Hz) - central_freq (float): central frequency (in Hz) - Q (float, optional): https://en.wikipedia.org/wiki/Q_factor (Default: ``0.707``) + central_freq (float or torch.Tensor): central frequency (in Hz) + Q (float or torch.Tensor, optional): https://en.wikipedia.org/wiki/Q_factor (Default: ``0.707``) Returns: Tensor: Waveform of dimension of `(..., time)` @@ -194,14 +210,19 @@ def bandreject_biquad( http://sox.sourceforge.net/sox.html https://www.w3.org/2011/audio/audio-eq-cookbook.html#APF """ + dtype = waveform.dtype + device = waveform.device + central_freq = torch.as_tensor(central_freq, dtype=dtype, device=device) + Q = torch.as_tensor(Q, dtype=dtype, device=device) + w0 = 2 * math.pi * central_freq / sample_rate - alpha = math.sin(w0) / 2 / Q + alpha = torch.sin(w0) / 2 / Q b0 = 1.0 - b1 = -2 * math.cos(w0) + b1 = -2 * torch.cos(w0) b2 = 1.0 a0 = 1 + alpha - a1 = -2 * math.cos(w0) + a1 = -2 * torch.cos(w0) a2 = 1 - alpha return biquad(waveform, b0, b1, b2, a0, a1, a2) @@ -218,9 +239,9 @@ def bass_biquad( Args: waveform (Tensor): audio waveform of dimension of `(..., time)` sample_rate (int): sampling rate of the waveform, e.g. 44100 (Hz) - gain (float): desired gain at the boost (or attenuation) in dB. - central_freq (float, optional): central frequency (in Hz). (Default: ``100``) - Q (float, optional): https://en.wikipedia.org/wiki/Q_factor (Default: ``0.707``). + gain (float or torch.Tensor): desired gain at the boost (or attenuation) in dB. + central_freq (float or torch.Tensor, optional): central frequency (in Hz). (Default: ``100``) + Q (float or torch.Tensor, optional): https://en.wikipedia.org/wiki/Q_factor (Default: ``0.707``). Returns: Tensor: Waveform of dimension of `(..., time)` @@ -229,13 +250,19 @@ def bass_biquad( http://sox.sourceforge.net/sox.html https://www.w3.org/2011/audio/audio-eq-cookbook.html#APF """ + dtype = waveform.dtype + device = waveform.device + central_freq = torch.as_tensor(central_freq, dtype=dtype, device=device) + Q = torch.as_tensor(Q, dtype=dtype, device=device) + gain = torch.as_tensor(gain, dtype=dtype, device=device) + w0 = 2 * math.pi * central_freq / sample_rate - alpha = math.sin(w0) / 2 / Q - A = math.exp(gain / 40 * math.log(10)) + alpha = torch.sin(w0) / 2 / Q + A = torch.exp(gain / 40 * math.log(10)) - temp1 = 2 * math.sqrt(A) * alpha - temp2 = (A - 1) * math.cos(w0) - temp3 = (A + 1) * math.cos(w0) + temp1 = 2 * torch.sqrt(A) * alpha + temp2 = (A - 1) * torch.cos(w0) + temp3 = (A + 1) * torch.cos(w0) b0 = A * ((A + 1) - temp2 + temp1) b1 = 2 * A * ((A - 1) - temp3) @@ -255,12 +282,12 @@ def biquad( Args: waveform (Tensor): audio waveform of dimension of `(..., time)` - b0 (float): numerator coefficient of current input, x[n] - b1 (float): numerator coefficient of input one time step ago x[n-1] - b2 (float): numerator coefficient of input two time steps ago x[n-2] - a0 (float): denominator coefficient of current output y[n], typically 1 - a1 (float): denominator coefficient of current output y[n-1] - a2 (float): denominator coefficient of current output y[n-2] + b0 (float or torch.Tensor): numerator coefficient of current input, x[n] + b1 (float or torch.Tensor): numerator coefficient of input one time step ago x[n-1] + b2 (float or torch.Tensor): numerator coefficient of input two time steps ago x[n-2] + a0 (float or torch.Tensor): denominator coefficient of current output y[n], typically 1 + a1 (float or torch.Tensor): denominator coefficient of current output y[n-1] + a2 (float or torch.Tensor): denominator coefficient of current output y[n-2] Returns: Tensor: Waveform with dimension of `(..., time)` @@ -269,10 +296,17 @@ def biquad( device = waveform.device dtype = waveform.dtype + b0 = torch.as_tensor(b0, dtype=dtype, device=device).view(1) + b1 = torch.as_tensor(b1, dtype=dtype, device=device).view(1) + b2 = torch.as_tensor(b2, dtype=dtype, device=device).view(1) + a0 = torch.as_tensor(a0, dtype=dtype, device=device).view(1) + a1 = torch.as_tensor(a1, dtype=dtype, device=device).view(1) + a2 = torch.as_tensor(a2, dtype=dtype, device=device).view(1) + output_waveform = lfilter( waveform, - torch.tensor([a0, a1, a2], dtype=dtype, device=device), - torch.tensor([b0, b1, b2], dtype=dtype, device=device), + torch.cat([a0, a1, a2]), + torch.cat([b0, b1, b2]), ) return output_waveform @@ -584,21 +618,27 @@ def equalizer_biquad( waveform (Tensor): audio waveform of dimension of `(..., time)` sample_rate (int): sampling rate of the waveform, e.g. 44100 (Hz) center_freq (float): filter's central frequency - gain (float): desired gain at the boost (or attenuation) in dB - Q (float, optional): https://en.wikipedia.org/wiki/Q_factor (Default: ``0.707``) + gain (float or torch.Tensor): desired gain at the boost (or attenuation) in dB + Q (float or torch.Tensor, optional): https://en.wikipedia.org/wiki/Q_factor (Default: ``0.707``) Returns: Tensor: Waveform of dimension of `(..., time)` """ + dtype = waveform.dtype + device = waveform.device + center_freq = torch.as_tensor(center_freq, dtype=dtype, device=device) + Q = torch.as_tensor(Q, dtype=dtype, device=device) + gain = torch.as_tensor(gain, dtype=dtype, device=device) + w0 = 2 * math.pi * center_freq / sample_rate - A = math.exp(gain / 40.0 * math.log(10)) - alpha = math.sin(w0) / 2 / Q + A = torch.exp(gain / 40.0 * math.log(10)) + alpha = torch.sin(w0) / 2 / Q b0 = 1 + alpha * A - b1 = -2 * math.cos(w0) + b1 = -2 * torch.cos(w0) b2 = 1 - alpha * A a0 = 1 + alpha / A - a1 = -2 * math.cos(w0) + a1 = -2 * torch.cos(w0) a2 = 1 - alpha / A return biquad(waveform, b0, b1, b2, a0, a1, a2) @@ -790,20 +830,25 @@ def highpass_biquad( Args: waveform (Tensor): audio waveform of dimension of `(..., time)` sample_rate (int): sampling rate of the waveform, e.g. 44100 (Hz) - cutoff_freq (float): filter cutoff frequency - Q (float, optional): https://en.wikipedia.org/wiki/Q_factor (Default: ``0.707``) + cutoff_freq (float or torch.Tensor): filter cutoff frequency + Q (float or torch.Tensor, optional): https://en.wikipedia.org/wiki/Q_factor (Default: ``0.707``) Returns: Tensor: Waveform dimension of `(..., time)` """ + dtype = waveform.dtype + device = waveform.device + cutoff_freq = torch.as_tensor(cutoff_freq, dtype=dtype, device=device) + Q = torch.as_tensor(Q, dtype=dtype, device=device) + w0 = 2 * math.pi * cutoff_freq / sample_rate - alpha = math.sin(w0) / 2.0 / Q + alpha = torch.sin(w0) / 2.0 / Q - b0 = (1 + math.cos(w0)) / 2 - b1 = -1 - math.cos(w0) + b0 = (1 + torch.cos(w0)) / 2 + b1 = -1 - torch.cos(w0) b2 = b0 a0 = 1 + alpha - a1 = -2 * math.cos(w0) + a1 = -2 * torch.cos(w0) a2 = 1 - alpha return biquad(waveform, b0, b1, b2, a0, a1, a2) @@ -924,20 +969,25 @@ def lowpass_biquad( Args: waveform (torch.Tensor): audio waveform of dimension of `(..., time)` sample_rate (int): sampling rate of the waveform, e.g. 44100 (Hz) - cutoff_freq (float): filter cutoff frequency - Q (float, optional): https://en.wikipedia.org/wiki/Q_factor (Default: ``0.707``) + cutoff_freq (float or torch.Tensor): filter cutoff frequency + Q (float or torch.Tensor, optional): https://en.wikipedia.org/wiki/Q_factor (Default: ``0.707``) Returns: Tensor: Waveform of dimension of `(..., time)` """ + dtype = waveform.dtype + device = waveform.device + cutoff_freq = torch.as_tensor(cutoff_freq, dtype=dtype, device=device) + Q = torch.as_tensor(Q, dtype=dtype, device=device) + w0 = 2 * math.pi * cutoff_freq / sample_rate - alpha = math.sin(w0) / 2 / Q + alpha = torch.sin(w0) / 2 / Q - b0 = (1 - math.cos(w0)) / 2 - b1 = 1 - math.cos(w0) + b0 = (1 - torch.cos(w0)) / 2 + b1 = 1 - torch.cos(w0) b2 = b0 a0 = 1 + alpha - a1 = -2 * math.cos(w0) + a1 = -2 * torch.cos(w0) a2 = 1 - alpha return biquad(waveform, b0, b1, b2, a0, a1, a2) @@ -1176,9 +1226,9 @@ def treble_biquad( Args: waveform (Tensor): audio waveform of dimension of `(..., time)` sample_rate (int): sampling rate of the waveform, e.g. 44100 (Hz) - gain (float): desired gain at the boost (or attenuation) in dB. - central_freq (float, optional): central frequency (in Hz). (Default: ``3000``) - Q (float, optional): https://en.wikipedia.org/wiki/Q_factor (Default: ``0.707``). + gain (float or torch.Tensor): desired gain at the boost (or attenuation) in dB. + central_freq (float or torch.Tensor, optional): central frequency (in Hz). (Default: ``3000``) + Q (float or torch.Tensor, optional): https://en.wikipedia.org/wiki/Q_factor (Default: ``0.707``). Returns: Tensor: Waveform of dimension of `(..., time)` @@ -1187,13 +1237,19 @@ def treble_biquad( http://sox.sourceforge.net/sox.html https://www.w3.org/2011/audio/audio-eq-cookbook.html#APF """ + dtype = waveform.dtype + device = waveform.device + central_freq = torch.as_tensor(central_freq, dtype=dtype, device=device) + Q = torch.as_tensor(Q, dtype=dtype, device=device) + gain = torch.as_tensor(gain, dtype=dtype, device=device) + w0 = 2 * math.pi * central_freq / sample_rate - alpha = math.sin(w0) / 2 / Q - A = math.exp(gain / 40 * math.log(10)) + alpha = torch.sin(w0) / 2 / Q + A = torch.exp(gain / 40 * math.log(10)) - temp1 = 2 * math.sqrt(A) * alpha - temp2 = (A - 1) * math.cos(w0) - temp3 = (A + 1) * math.cos(w0) + temp1 = 2 * torch.sqrt(A) * alpha + temp2 = (A - 1) * torch.cos(w0) + temp3 = (A + 1) * torch.cos(w0) b0 = A * ((A + 1) + temp2 + temp1) b1 = -2 * A * ((A - 1) + temp3) diff --git a/torchaudio/functional/functional.py b/torchaudio/functional/functional.py index 73496bf4cc..9d23a2cace 100644 --- a/torchaudio/functional/functional.py +++ b/torchaudio/functional/functional.py @@ -48,7 +48,8 @@ def spectrogram( normalized: bool, center: bool = True, pad_mode: str = "reflect", - onesided: bool = True + onesided: bool = True, + return_complex: bool = False, ) -> Tensor: r"""Create a spectrogram or a batch of spectrograms from a raw audio signal. The spectrogram can be either magnitude-only or complex. @@ -71,12 +72,30 @@ def spectrogram( :attr:`center` is ``True``. Default: ``"reflect"`` onesided (bool, optional): controls whether to return half of results to avoid redundancy. Default: ``True`` + return_complex (bool, optional): + ``return_complex = True``, this function returns the resulting Tensor in + complex dtype, otherwise it returns the resulting Tensor in real dtype with extra + dimension for real and imaginary parts. (see ``torch.view_as_real``). + When ``power`` is provided, the value must be False, as the resulting + Tensor represents real-valued power. Returns: Tensor: Dimension (..., freq, time), freq is ``n_fft // 2 + 1`` and ``n_fft`` is the number of Fourier bins, and time is the number of window hops (n_frame). """ + if power is None and not return_complex: + warnings.warn( + "The use of pseudo complex type in spectrogram is now deprecated." + "Please migrate to native complex type by providing `return_complex=True`. " + "Please refer to https://github.com/pytorch/audio/issues/1337 " + "for more details about torchaudio's plan to migrate to native complex type." + ) + + if power is not None and return_complex: + raise ValueError( + 'When `power` is provided, the return value is real-valued. ' + 'Therefore, `return_complex` must be False.') if pad > 0: # TODO add "with torch.no_grad():" back when JIT supports it @@ -109,7 +128,19 @@ def spectrogram( if power == 1.0: return spec_f.abs() return spec_f.abs().pow(power) - return torch.view_as_real(spec_f) + if not return_complex: + return torch.view_as_real(spec_f) + return spec_f + + +def _get_complex_dtype(real_dtype: torch.dtype): + if real_dtype == torch.double: + return torch.cdouble + if real_dtype == torch.float: + return torch.cfloat + if real_dtype == torch.half: + return torch.complex32 + raise ValueError(f'Unexpected dtype {real_dtype}') def griffinlim( @@ -167,52 +198,49 @@ def griffinlim( specgram = specgram.pow(1 / power) - # randomly initialize the phase - batch, freq, frames = specgram.size() + # initialize the phase if rand_init: - angles = 2 * math.pi * torch.rand(batch, freq, frames) + angles = torch.rand( + specgram.size(), + dtype=_get_complex_dtype(specgram.dtype), device=specgram.device) else: - angles = torch.zeros(batch, freq, frames) - angles = torch.stack([angles.cos(), angles.sin()], dim=-1) \ - .to(dtype=specgram.dtype, device=specgram.device) - specgram = specgram.unsqueeze(-1).expand_as(angles) + angles = torch.full( + specgram.size(), 1, + dtype=_get_complex_dtype(specgram.dtype), device=specgram.device) # And initialize the previous iterate to 0 - rebuilt = torch.tensor(0.) - + tprev = torch.tensor(0., dtype=specgram.dtype, device=specgram.device) for _ in range(n_iter): - # Store the previous iterate - tprev = rebuilt - # Invert with our current estimate of the phases inverse = torch.istft(specgram * angles, n_fft=n_fft, hop_length=hop_length, win_length=win_length, window=window, - length=length).float() + length=length) # Rebuild the spectrogram - rebuilt = torch.view_as_real( - torch.stft( - input=inverse, - n_fft=n_fft, - hop_length=hop_length, - win_length=win_length, - window=window, - center=True, - pad_mode='reflect', - normalized=False, - onesided=True, - return_complex=True, - ) + rebuilt = torch.stft( + input=inverse, + n_fft=n_fft, + hop_length=hop_length, + win_length=win_length, + window=window, + center=True, + pad_mode='reflect', + normalized=False, + onesided=True, + return_complex=True, ) # Update our phase estimates angles = rebuilt if momentum: angles = angles - tprev.mul_(momentum / (1 + momentum)) - angles = angles.div(complex_norm(angles).add(1e-16).unsqueeze(-1).expand_as(angles)) + angles = angles.div(angles.abs().add(1e-16)) + + # Store the previous iterate + tprev = rebuilt # Return the final phase estimates waveform = torch.istft(specgram * angles, @@ -505,6 +533,12 @@ def mu_law_decoding( return x +@_mod_utils.deprecated( + "Please convert the input Tensor to complex type with `torch.view_as_complex` then " + "use `torch.abs`. " + "Please refer to https://github.com/pytorch/audio/issues/1337 " + "for more details about torchaudio's plan to migrate to native complex type." +) def complex_norm( complex_tensor: Tensor, power: float = 1.0 @@ -524,6 +558,12 @@ def complex_norm( return complex_tensor.pow(2.).sum(-1).pow(0.5 * power) +@_mod_utils.deprecated( + "Please convert the input Tensor to complex type with `torch.view_as_complex` then " + "use `torch.angle`. " + "Please refer to https://github.com/pytorch/audio/issues/1337 " + "for more details about torchaudio's plan to migrate to native complex type." +) def angle( complex_tensor: Tensor ) -> Tensor: @@ -565,14 +605,29 @@ def phase_vocoder( factor of ``rate``. Args: - complex_specgrams (Tensor): Dimension of `(..., freq, time, complex=2)` + complex_specgrams (Tensor): + Either a real tensor of dimension of ``(..., freq, num_frame, complex=2)`` + or a tensor of dimension ``(..., freq, num_frame)`` with complex dtype. rate (float): Speed-up factor phase_advance (Tensor): Expected phase advance in each bin. Dimension of (freq, 1) Returns: - Tensor: Complex Specgrams Stretch with dimension of `(..., freq, ceil(time/rate), complex=2)` + Tensor: + Stretched spectrogram. The resulting tensor is of the same dtype as the input + spectrogram, but the number of frames is changed to ``ceil(num_frame / rate)``. - Example + Example - With Tensor of complex dtype + >>> freq, hop_length = 1025, 512 + >>> # (channel, freq, time) + >>> complex_specgrams = torch.randn(2, freq, 300, dtype=torch.cfloat) + >>> rate = 1.3 # Speed up by 30% + >>> phase_advance = torch.linspace( + >>> 0, math.pi * hop_length, freq)[..., None] + >>> x = phase_vocoder(complex_specgrams, rate, phase_advance) + >>> x.shape # with 231 == ceil(300 / 1.3) + torch.Size([2, 1025, 231]) + + Example - With Tensor of real dtype and extra dimension for complex field >>> freq, hop_length = 1025, 512 >>> # (channel, freq, time, complex=2) >>> complex_specgrams = torch.randn(2, freq, 300, 2) @@ -583,32 +638,57 @@ def phase_vocoder( >>> x.shape # with 231 == ceil(300 / 1.3) torch.Size([2, 1025, 231, 2]) """ + if rate == 1.0: + return complex_specgrams + + if not complex_specgrams.is_complex(): + warnings.warn( + "The use of pseudo complex type in `torchaudio.functional.phase_vocoder` and " + "`torchaudio.transforms.TimeStretch` is now deprecated." + "Please migrate to native complex type by converting the input tensor with " + "`torch.view_as_complex`. " + "Please refer to https://github.com/pytorch/audio/issues/1337 " + "for more details about torchaudio's plan to migrate to native complex type." + ) + if complex_specgrams.size(-1) != 2: + raise ValueError( + "complex_specgrams must be either native complex tensors or " + "real valued tensors with shape (..., 2)") + + is_complex = complex_specgrams.is_complex() + + if not is_complex: + complex_specgrams = torch.view_as_complex(complex_specgrams) # pack batch shape = complex_specgrams.size() - complex_specgrams = complex_specgrams.reshape([-1] + list(shape[-3:])) - - time_steps = torch.arange(0, - complex_specgrams.size(-2), - rate, - device=complex_specgrams.device, - dtype=complex_specgrams.dtype) + complex_specgrams = complex_specgrams.reshape([-1] + list(shape[-2:])) + + # Figures out the corresponding real dtype, i.e. complex128 -> float64, complex64 -> float32 + # Note torch.real is a view so it does not incur any memory copy. + real_dtype = torch.real(complex_specgrams).dtype + time_steps = torch.arange( + 0, + complex_specgrams.size(-1), + rate, + device=complex_specgrams.device, + dtype=real_dtype) alphas = time_steps % 1.0 - phase_0 = angle(complex_specgrams[..., :1, :]) + phase_0 = complex_specgrams[..., :1].angle() # Time Padding - complex_specgrams = torch.nn.functional.pad(complex_specgrams, [0, 0, 0, 2]) + complex_specgrams = torch.nn.functional.pad(complex_specgrams, [0, 2]) # (new_bins, freq, 2) - complex_specgrams_0 = complex_specgrams.index_select(-2, time_steps.long()) - complex_specgrams_1 = complex_specgrams.index_select(-2, (time_steps + 1).long()) + complex_specgrams_0 = complex_specgrams.index_select(-1, time_steps.long()) + complex_specgrams_1 = complex_specgrams.index_select(-1, (time_steps + 1).long()) - angle_0 = angle(complex_specgrams_0) - angle_1 = angle(complex_specgrams_1) + angle_0 = complex_specgrams_0.angle() + angle_1 = complex_specgrams_1.angle() - norm_0 = torch.norm(complex_specgrams_0, p=2, dim=-1) - norm_1 = torch.norm(complex_specgrams_1, p=2, dim=-1) + norm_0 = complex_specgrams_0.abs() + norm_1 = complex_specgrams_1.abs() phase = angle_1 - angle_0 - phase_advance phase = phase - 2 * math.pi * torch.round(phase / (2 * math.pi)) @@ -620,14 +700,13 @@ def phase_vocoder( mag = alphas * norm_1 + (1 - alphas) * norm_0 - real_stretch = mag * torch.cos(phase_acc) - imag_stretch = mag * torch.sin(phase_acc) - - complex_specgrams_stretch = torch.stack([real_stretch, imag_stretch], dim=-1) + complex_specgrams_stretch = torch.polar(mag, phase_acc) # unpack batch - complex_specgrams_stretch = complex_specgrams_stretch.reshape(shape[:-3] + complex_specgrams_stretch.shape[1:]) + complex_specgrams_stretch = complex_specgrams_stretch.reshape(shape[:-2] + complex_specgrams_stretch.shape[1:]) + if not is_complex: + return torch.view_as_real(complex_specgrams_stretch) return complex_specgrams_stretch diff --git a/torchaudio/transforms.py b/torchaudio/transforms.py index 6f3ea1b6e1..96832167d2 100644 --- a/torchaudio/transforms.py +++ b/torchaudio/transforms.py @@ -52,6 +52,12 @@ class Spectrogram(torch.nn.Module): :attr:`center` is ``True``. Default: ``"reflect"`` onesided (bool, optional): controls whether to return half of results to avoid redundancy Default: ``True`` + return_complex (bool, optional): + ``return_complex = True``, this function returns the resulting Tensor in + complex dtype, otherwise it returns the resulting Tensor in real dtype with extra + dimension for real and imaginary parts. (see ``torch.view_as_real``). + When ``power`` is provided, the value must be False, as the resulting + Tensor represents real-valued power. """ __constants__ = ['n_fft', 'win_length', 'hop_length', 'pad', 'power', 'normalized'] @@ -66,7 +72,8 @@ def __init__(self, wkwargs: Optional[dict] = None, center: bool = True, pad_mode: str = "reflect", - onesided: bool = True) -> None: + onesided: bool = True, + return_complex: bool = False) -> None: super(Spectrogram, self).__init__() self.n_fft = n_fft # number of FFT bins. the returned STFT result will have n_fft // 2 + 1 @@ -81,6 +88,7 @@ def __init__(self, self.center = center self.pad_mode = pad_mode self.onesided = onesided + self.return_complex = return_complex def forward(self, waveform: Tensor) -> Tensor: r""" @@ -103,7 +111,8 @@ def forward(self, waveform: Tensor) -> Tensor: self.normalized, self.center, self.pad_mode, - self.onesided + self.onesided, + self.return_complex, ) @@ -146,7 +155,7 @@ class GriffinLim(torch.nn.Module): | "Signal estimation from modified short-time Fourier transform," | IEEE Trans. ASSP, vol.32, no.2, pp.236โ€“243, Apr. 1984. """ - __constants__ = ['n_fft', 'n_iter', 'win_length', 'hop_length', 'power', 'normalized', + __constants__ = ['n_fft', 'n_iter', 'win_length', 'hop_length', 'power', 'length', 'momentum', 'rand_init'] def __init__(self, @@ -163,7 +172,7 @@ def __init__(self, super(GriffinLim, self).__init__() assert momentum < 1, 'momentum={} > 1 can be unstable'.format(momentum) - assert momentum > 0, 'momentum={} < 0'.format(momentum) + assert momentum >= 0, 'momentum={} < 0'.format(momentum) self.n_fft = n_fft self.n_iter = n_iter @@ -729,26 +738,24 @@ def __init__(self, def forward(self, complex_specgrams: Tensor, overriding_rate: Optional[float] = None) -> Tensor: r""" Args: - complex_specgrams (Tensor): complex spectrogram (..., freq, time, complex=2). + complex_specgrams (Tensor): + Either a real tensor of dimension of ``(..., freq, num_frame, complex=2)`` + or a tensor of dimension ``(..., freq, num_frame)`` with complex dtype. overriding_rate (float or None, optional): speed up to apply to this batch. If no rate is passed, use ``self.fixed_rate``. (Default: ``None``) Returns: - Tensor: Stretched complex spectrogram of dimension (..., freq, ceil(time/rate), complex=2). + Tensor: + Stretched spectrogram. The resulting tensor is of the same dtype as the input + spectrogram, but the number of frames is changed to ``ceil(num_frame / rate)``. """ - assert complex_specgrams.size(-1) == 2, "complex_specgrams should be a complex tensor, shape (..., complex=2)" - if overriding_rate is None: + if self.fixed_rate is None: + raise ValueError( + "If no fixed_rate is specified, must pass a valid rate to the forward method.") rate = self.fixed_rate - if rate is None: - raise ValueError("If no fixed_rate is specified" - ", must pass a valid rate to the forward method.") else: rate = overriding_rate - - if rate == 1.0: - return complex_specgrams - return F.phase_vocoder(complex_specgrams, rate, self.phase_advance) @@ -761,6 +768,7 @@ class Fade(torch.nn.Module): fade_shape (str, optional): Shape of fade. Must be one of: "quarter_sine", "half_sine", "linear", "logarithmic", "exponential". (Default: ``"linear"``) """ + def __init__(self, fade_in_len: int = 0, fade_out_len: int = 0, @@ -870,6 +878,7 @@ class FrequencyMasking(_AxisMasking): example/channel in the batch. (Default: ``False``) This option is applicable only when the input tensor is 4D. """ + def __init__(self, freq_mask_param: int, iid_masks: bool = False) -> None: super(FrequencyMasking, self).__init__(freq_mask_param, 1, iid_masks) @@ -884,6 +893,7 @@ class TimeMasking(_AxisMasking): example/channel in the batch. (Default: ``False``) This option is applicable only when the input tensor is 4D. """ + def __init__(self, time_mask_param: int, iid_masks: bool = False) -> None: super(TimeMasking, self).__init__(time_mask_param, 2, iid_masks) From 93fb018a30cbb761deecf7fc83c1e2f0b5f8ee8d Mon Sep 17 00:00:00 2001 From: Moto Hira Date: Fri, 16 Apr 2021 07:44:03 -0700 Subject: [PATCH 38/73] Remove CI script that is removed in GitHub Summary: `run-clang-format.py` has been renamed to `run_clang_format.py` in github.com/pytorch/audio but there exists two of them in fbcode. Removing the unneeded one. Reviewed By: carolineechen Differential Revision: D27822084 fbshipit-source-id: 132de34b85b866342757bf4648cc1b6b81ff12be --- .../linux/scripts/run-clang-format.py | 340 ------------------ 1 file changed, 340 deletions(-) delete mode 100755 .circleci/unittest/linux/scripts/run-clang-format.py diff --git a/.circleci/unittest/linux/scripts/run-clang-format.py b/.circleci/unittest/linux/scripts/run-clang-format.py deleted file mode 100755 index fd2913bd70..0000000000 --- a/.circleci/unittest/linux/scripts/run-clang-format.py +++ /dev/null @@ -1,340 +0,0 @@ -#!/usr/bin/env python -"""A wrapper script around clang-format, suitable for linting multiple files -and to use for continuous integration. - -This is an alternative API for the clang-format command line. -It runs over multiple files and directories in parallel. -A diff output is produced and a sensible exit code is returned. - -""" - -import argparse -import codecs -import difflib -import fnmatch -import io -import multiprocessing -import os -import signal -import subprocess -import sys -import traceback - -from functools import partial - -try: - from subprocess import DEVNULL # py3k -except ImportError: - DEVNULL = open(os.devnull, "wb") - - -DEFAULT_EXTENSIONS = 'c,h,C,H,cpp,hpp,cc,hh,c++,h++,cxx,hxx,cu' - - -class ExitStatus: - SUCCESS = 0 - DIFF = 1 - TROUBLE = 2 - - -def list_files(files, recursive=False, extensions=None, exclude=None): - if extensions is None: - extensions = [] - if exclude is None: - exclude = [] - - out = [] - for file in files: - if recursive and os.path.isdir(file): - for dirpath, dnames, fnames in os.walk(file): - fpaths = [os.path.join(dirpath, fname) for fname in fnames] - for pattern in exclude: - # os.walk() supports trimming down the dnames list - # by modifying it in-place, - # to avoid unnecessary directory listings. - dnames[:] = [ - x for x in dnames - if - not fnmatch.fnmatch(os.path.join(dirpath, x), pattern) - ] - fpaths = [ - x for x in fpaths if not fnmatch.fnmatch(x, pattern) - ] - for f in fpaths: - ext = os.path.splitext(f)[1][1:] - if ext in extensions: - out.append(f) - else: - out.append(file) - return out - - -def make_diff(file, original, reformatted): - return list( - difflib.unified_diff( - original, - reformatted, - fromfile='{}\t(original)'.format(file), - tofile='{}\t(reformatted)'.format(file), - n=3)) - - -class DiffError(Exception): - def __init__(self, message, errs=None): - super(DiffError, self).__init__(message) - self.errs = errs or [] - - -class UnexpectedError(Exception): - def __init__(self, message, exc=None): - super(UnexpectedError, self).__init__(message) - self.formatted_traceback = traceback.format_exc() - self.exc = exc - - -def run_clang_format_diff_wrapper(args, file): - try: - ret = run_clang_format_diff(args, file) - return ret - except DiffError: - raise - except Exception as e: - raise UnexpectedError('{}: {}: {}'.format(file, e.__class__.__name__, - e), e) - - -def run_clang_format_diff(args, file): - try: - with io.open(file, 'r', encoding='utf-8') as f: - original = f.readlines() - except IOError as exc: - raise DiffError(str(exc)) - invocation = [args.clang_format_executable, file] - - # Use of utf-8 to decode the process output. - # - # Hopefully, this is the correct thing to do. - # - # It's done due to the following assumptions (which may be incorrect): - # - clang-format will returns the bytes read from the files as-is, - # without conversion, and it is already assumed that the files use utf-8. - # - if the diagnostics were internationalized, they would use utf-8: - # > Adding Translations to Clang - # > - # > Not possible yet! - # > Diagnostic strings should be written in UTF-8, - # > the client can translate to the relevant code page if needed. - # > Each translation completely replaces the format string - # > for the diagnostic. - # > -- http://clang.llvm.org/docs/InternalsManual.html#internals-diag-translation - - try: - proc = subprocess.Popen( - invocation, - stdout=subprocess.PIPE, - stderr=subprocess.PIPE, - universal_newlines=True, - encoding='utf-8') - except OSError as exc: - raise DiffError( - "Command '{}' failed to start: {}".format( - subprocess.list2cmdline(invocation), exc - ) - ) - proc_stdout = proc.stdout - proc_stderr = proc.stderr - - # hopefully the stderr pipe won't get full and block the process - outs = list(proc_stdout.readlines()) - errs = list(proc_stderr.readlines()) - proc.wait() - if proc.returncode: - raise DiffError( - "Command '{}' returned non-zero exit status {}".format( - subprocess.list2cmdline(invocation), proc.returncode - ), - errs, - ) - return make_diff(file, original, outs), errs - - -def bold_red(s): - return '\x1b[1m\x1b[31m' + s + '\x1b[0m' - - -def colorize(diff_lines): - def bold(s): - return '\x1b[1m' + s + '\x1b[0m' - - def cyan(s): - return '\x1b[36m' + s + '\x1b[0m' - - def green(s): - return '\x1b[32m' + s + '\x1b[0m' - - def red(s): - return '\x1b[31m' + s + '\x1b[0m' - - for line in diff_lines: - if line[:4] in ['--- ', '+++ ']: - yield bold(line) - elif line.startswith('@@ '): - yield cyan(line) - elif line.startswith('+'): - yield green(line) - elif line.startswith('-'): - yield red(line) - else: - yield line - - -def print_diff(diff_lines, use_color): - if use_color: - diff_lines = colorize(diff_lines) - sys.stdout.writelines(diff_lines) - - -def print_trouble(prog, message, use_colors): - error_text = 'error:' - if use_colors: - error_text = bold_red(error_text) - print("{}: {} {}".format(prog, error_text, message), file=sys.stderr) - - -def main(): - parser = argparse.ArgumentParser(description=__doc__) - parser.add_argument( - '--clang-format-executable', - metavar='EXECUTABLE', - help='path to the clang-format executable', - default='clang-format') - parser.add_argument( - '--extensions', - help='comma separated list of file extensions (default: {})'.format( - DEFAULT_EXTENSIONS), - default=DEFAULT_EXTENSIONS) - parser.add_argument( - '-r', - '--recursive', - action='store_true', - help='run recursively over directories') - parser.add_argument('files', metavar='file', nargs='+') - parser.add_argument( - '-q', - '--quiet', - action='store_true') - parser.add_argument( - '-j', - metavar='N', - type=int, - default=0, - help='run N clang-format jobs in parallel' - ' (default number of cpus + 1)') - parser.add_argument( - '--color', - default='auto', - choices=['auto', 'always', 'never'], - help='show colored diff (default: auto)') - parser.add_argument( - '-e', - '--exclude', - metavar='PATTERN', - action='append', - default=[], - help='exclude paths matching the given glob-like pattern(s)' - ' from recursive search') - - args = parser.parse_args() - - # use default signal handling, like diff return SIGINT value on ^C - # https://bugs.python.org/issue14229#msg156446 - signal.signal(signal.SIGINT, signal.SIG_DFL) - try: - signal.SIGPIPE - except AttributeError: - # compatibility, SIGPIPE does not exist on Windows - pass - else: - signal.signal(signal.SIGPIPE, signal.SIG_DFL) - - colored_stdout = False - colored_stderr = False - if args.color == 'always': - colored_stdout = True - colored_stderr = True - elif args.color == 'auto': - colored_stdout = sys.stdout.isatty() - colored_stderr = sys.stderr.isatty() - - version_invocation = [args.clang_format_executable, str("--version")] - try: - subprocess.check_call(version_invocation, stdout=DEVNULL) - except subprocess.CalledProcessError as e: - print_trouble(parser.prog, str(e), use_colors=colored_stderr) - return ExitStatus.TROUBLE - except OSError as e: - print_trouble( - parser.prog, - "Command '{}' failed to start: {}".format( - subprocess.list2cmdline(version_invocation), e - ), - use_colors=colored_stderr, - ) - return ExitStatus.TROUBLE - - retcode = ExitStatus.SUCCESS - files = list_files( - args.files, - recursive=args.recursive, - exclude=args.exclude, - extensions=args.extensions.split(',')) - - if not files: - return - - njobs = args.j - if njobs == 0: - njobs = multiprocessing.cpu_count() + 1 - njobs = min(len(files), njobs) - - if njobs == 1: - # execute directly instead of in a pool, - # less overhead, simpler stacktraces - it = (run_clang_format_diff_wrapper(args, file) for file in files) - pool = None - else: - pool = multiprocessing.Pool(njobs) - it = pool.imap_unordered( - partial(run_clang_format_diff_wrapper, args), files) - while True: - try: - outs, errs = next(it) - except StopIteration: - break - except DiffError as e: - print_trouble(parser.prog, str(e), use_colors=colored_stderr) - retcode = ExitStatus.TROUBLE - sys.stderr.writelines(e.errs) - except UnexpectedError as e: - print_trouble(parser.prog, str(e), use_colors=colored_stderr) - sys.stderr.write(e.formatted_traceback) - retcode = ExitStatus.TROUBLE - # stop at the first unexpected error, - # something could be very wrong, - # don't process all files unnecessarily - if pool: - pool.terminate() - break - else: - sys.stderr.writelines(errs) - if outs == []: - continue - if not args.quiet: - print_diff(outs, use_color=colored_stdout) - if retcode == ExitStatus.SUCCESS: - retcode = ExitStatus.DIFF - return retcode - - -if __name__ == '__main__': - sys.exit(main()) From dfb4943515480be512a717491d08ca839d860767 Mon Sep 17 00:00:00 2001 From: Artyom Astafurov Date: Thu, 22 Apr 2021 08:39:10 -0700 Subject: [PATCH 39/73] Import torchaudio #1466 9d50acf Reviewed By: vincentqb, mthrok Differential Revision: D27922742 fbshipit-source-id: 6fa96728171687089abe6d734c23fc98bd29430b --- .circleci/config.yml | 26 +-- .circleci/config.yml.in | 26 +-- .circleci/unittest/linux/scripts/install.sh | 2 +- .circleci/unittest/linux/scripts/run_test.sh | 1 + .circleci/unittest/windows/scripts/install.sh | 2 +- .../unittest/windows/scripts/run_test.sh | 1 + docs/source/conf.py | 3 +- examples/pipeline_wav2letter/README.md | 6 +- examples/pipeline_wavernn/main.py | 10 +- examples/pipeline_wavernn/processing.py | 27 +-- .../functional/functional_cpu_test.py | 207 +----------------- .../functional/functional_cuda_test.py | 18 +- .../functional/functional_impl.py | 169 +++++++++++++- .../transforms/autograd_test_impl.py | 7 + third_party/sox/CMakeLists.txt | 1 + torchaudio/_internal/misc_ops.py | 30 --- torchaudio/functional/filtering.py | 2 +- torchaudio/transforms.py | 2 + 18 files changed, 227 insertions(+), 313 deletions(-) delete mode 100644 torchaudio/_internal/misc_ops.py diff --git a/.circleci/config.yml b/.circleci/config.yml index 3bf72c3a6d..2cbddf2e3c 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -424,12 +424,10 @@ jobs: - run: name: Run tests command: .circleci/unittest/linux/scripts/run_test.sh - - run: - name: Post process - command: .circleci/unittest/linux/scripts/post_process.sh - store_test_results: path: test-results - + - store_artifacts: + path: test/htmlcov unittest_linux_gpu: <<: *binary_common machine: @@ -456,11 +454,10 @@ jobs: - run: name: Run tests command: docker run -t --gpus all -v $PWD:$PWD -w $PWD "${image_name}" .circleci/unittest/linux/scripts/run_test.sh - - run: - name: Post Process - command: docker run -t --gpus all -v $PWD:$PWD -w $PWD "${image_name}" .circleci/unittest/linux/scripts/post_process.sh - store_test_results: path: test-results + - store_artifacts: + path: test/htmlcov unittest_windows_cpu: <<: *binary_common @@ -479,11 +476,10 @@ jobs: - run: name: Run tests command: .circleci/unittest/windows/scripts/run_test.sh - - run: - name: Post process - command: .circleci/unittest/windows/scripts/post_process.sh - store_test_results: path: test-results + - store_artifacts: + path: test/htmlcov unittest_windows_gpu: <<: *binary_common @@ -505,11 +501,10 @@ jobs: - run: name: Run tests command: .circleci/unittest/windows/scripts/run_test.sh - - run: - name: Post process - command: .circleci/unittest/windows/scripts/post_process.sh - store_test_results: path: test-results + - store_artifacts: + path: test/htmlcov unittest_macos_cpu: <<: *binary_common @@ -532,11 +527,10 @@ jobs: - run: name: Run tests command: .circleci/unittest/linux/scripts/run_test.sh - - run: - name: Post process - command: .circleci/unittest/linux/scripts/post_process.sh - store_test_results: path: test-results + - store_artifacts: + path: test/htmlcov stylecheck: <<: *binary_common diff --git a/.circleci/config.yml.in b/.circleci/config.yml.in index 8e01b1da56..f15767041e 100644 --- a/.circleci/config.yml.in +++ b/.circleci/config.yml.in @@ -424,12 +424,10 @@ jobs: - run: name: Run tests command: .circleci/unittest/linux/scripts/run_test.sh - - run: - name: Post process - command: .circleci/unittest/linux/scripts/post_process.sh - store_test_results: path: test-results - + - store_artifacts: + path: test/htmlcov unittest_linux_gpu: <<: *binary_common machine: @@ -456,11 +454,10 @@ jobs: - run: name: Run tests command: docker run -t --gpus all -v $PWD:$PWD -w $PWD "${image_name}" .circleci/unittest/linux/scripts/run_test.sh - - run: - name: Post Process - command: docker run -t --gpus all -v $PWD:$PWD -w $PWD "${image_name}" .circleci/unittest/linux/scripts/post_process.sh - store_test_results: path: test-results + - store_artifacts: + path: test/htmlcov unittest_windows_cpu: <<: *binary_common @@ -479,11 +476,10 @@ jobs: - run: name: Run tests command: .circleci/unittest/windows/scripts/run_test.sh - - run: - name: Post process - command: .circleci/unittest/windows/scripts/post_process.sh - store_test_results: path: test-results + - store_artifacts: + path: test/htmlcov unittest_windows_gpu: <<: *binary_common @@ -505,11 +501,10 @@ jobs: - run: name: Run tests command: .circleci/unittest/windows/scripts/run_test.sh - - run: - name: Post process - command: .circleci/unittest/windows/scripts/post_process.sh - store_test_results: path: test-results + - store_artifacts: + path: test/htmlcov unittest_macos_cpu: <<: *binary_common @@ -532,11 +527,10 @@ jobs: - run: name: Run tests command: .circleci/unittest/linux/scripts/run_test.sh - - run: - name: Post process - command: .circleci/unittest/linux/scripts/post_process.sh - store_test_results: path: test-results + - store_artifacts: + path: test/htmlcov stylecheck: <<: *binary_common diff --git a/.circleci/unittest/linux/scripts/install.sh b/.circleci/unittest/linux/scripts/install.sh index 5638a28850..3b0cd4bc4c 100755 --- a/.circleci/unittest/linux/scripts/install.sh +++ b/.circleci/unittest/linux/scripts/install.sh @@ -56,5 +56,5 @@ fi ( set -x conda install -y -c conda-forge ${NUMBA_DEV_CHANNEL} 'librosa>=0.8.0' parameterized 'requests>=2.20' - pip install kaldi-io SoundFile codecov pytest pytest-cov scipy + pip install kaldi-io SoundFile coverage pytest pytest-cov scipy ) diff --git a/.circleci/unittest/linux/scripts/run_test.sh b/.circleci/unittest/linux/scripts/run_test.sh index e083743630..4e8d24748b 100755 --- a/.circleci/unittest/linux/scripts/run_test.sh +++ b/.circleci/unittest/linux/scripts/run_test.sh @@ -24,3 +24,4 @@ declare -a args=( cd test pytest "${args[@]}" torchaudio_unittest +coverage html diff --git a/.circleci/unittest/windows/scripts/install.sh b/.circleci/unittest/windows/scripts/install.sh index be0c890614..9ed4f203ad 100644 --- a/.circleci/unittest/windows/scripts/install.sh +++ b/.circleci/unittest/windows/scripts/install.sh @@ -44,5 +44,5 @@ fi ( set -x conda install -y -c conda-forge ${NUMBA_DEV_CHANNEL} 'librosa>=0.8.0' parameterized 'requests>=2.20' - pip install kaldi-io SoundFile codecov pytest pytest-cov scipy + pip install kaldi-io SoundFile coverage pytest pytest-cov scipy ) diff --git a/.circleci/unittest/windows/scripts/run_test.sh b/.circleci/unittest/windows/scripts/run_test.sh index 7fdd1d4c6d..c6e7ffd37f 100644 --- a/.circleci/unittest/windows/scripts/run_test.sh +++ b/.circleci/unittest/windows/scripts/run_test.sh @@ -8,3 +8,4 @@ conda activate ./env python -m torch.utils.collect_env cd test pytest --cov=torchaudio --junitxml=../test-results/junit.xml -v --durations 20 torchaudio_unittest +coverage html diff --git a/docs/source/conf.py b/docs/source/conf.py index 3bc89e999d..f78858e381 100644 --- a/docs/source/conf.py +++ b/docs/source/conf.py @@ -123,7 +123,8 @@ 'collapse_navigation': False, 'display_version': True, 'logo_only': True, - 'navigation_with_keys': True + 'navigation_with_keys': True, + 'analytics_id': 'UA-117752657-2', } html_logo = '_static/img/pytorch-logo-dark.svg' diff --git a/examples/pipeline_wav2letter/README.md b/examples/pipeline_wav2letter/README.md index 8117d19c91..49cca3c83d 100644 --- a/examples/pipeline_wav2letter/README.md +++ b/examples/pipeline_wav2letter/README.md @@ -4,8 +4,13 @@ This is an example pipeline for speech recognition using a greedy or Viterbi CTC More information about each command line parameters is available with the `--help` option. An example can be invoked as follows. ``` +DATASET_ROOT = // +DATASET_FOLDER_IN_ARCHIVE = 'LibriSpeech' + python main.py \ --reduce-lr-valid \ + --dataset-root "${DATASET_ROOT}" \ + --dataset-folder-in-archive "${DATASET_FOLDER_IN_ARCHIVE}" \ --dataset-train train-clean-100 train-clean-360 train-other-500 \ --dataset-valid dev-clean \ --batch-size 128 \ @@ -15,7 +20,6 @@ python main.py \ --clip-grad 0. \ --gamma .99 \ --hop-length 160 \ - --n-hidden-channels 2000 \ --win-length 400 \ --n-bins 13 \ --normalize \ diff --git a/examples/pipeline_wavernn/main.py b/examples/pipeline_wavernn/main.py index 28ecb76fb9..2c67059cae 100644 --- a/examples/pipeline_wavernn/main.py +++ b/examples/pipeline_wavernn/main.py @@ -17,7 +17,7 @@ from datasets import collate_factory, split_process_dataset from losses import LongCrossEntropyLoss, MoLLoss -from processing import LinearToMel, NormalizeDB +from processing import NormalizeDB from utils import MetricLogger, count_parameters, save_checkpoint @@ -269,12 +269,12 @@ def main(args): } transforms = torch.nn.Sequential( - torchaudio.transforms.Spectrogram(**melkwargs), - LinearToMel( + torchaudio.transforms.MelSpectrogram( sample_rate=args.sample_rate, - n_fft=args.n_fft, n_mels=args.n_freq, - fmin=args.f_min, + f_min=args.f_min, + mel_scale='slaney', + **melkwargs, ), NormalizeDB(min_level_db=args.min_level_db, normalization=args.normalization), ) diff --git a/examples/pipeline_wavernn/processing.py b/examples/pipeline_wavernn/processing.py index dca45e97f4..9b06ea6d48 100644 --- a/examples/pipeline_wavernn/processing.py +++ b/examples/pipeline_wavernn/processing.py @@ -1,32 +1,7 @@ -import librosa import torch import torch.nn as nn -# TODO Replace by torchaudio, once https://github.com/pytorch/audio/pull/593 is resolved -class LinearToMel(nn.Module): - def __init__(self, sample_rate, n_fft, n_mels, fmin, htk=False, norm="slaney"): - super().__init__() - self.sample_rate = sample_rate - self.n_fft = n_fft - self.n_mels = n_mels - self.fmin = fmin - self.htk = htk - self.norm = norm - - def forward(self, specgram): - specgram = librosa.feature.melspectrogram( - S=specgram.squeeze(0).numpy(), - sr=self.sample_rate, - n_fft=self.n_fft, - n_mels=self.n_mels, - fmin=self.fmin, - htk=self.htk, - norm=self.norm, - ) - return torch.from_numpy(specgram) - - class NormalizeDB(nn.Module): r"""Normalize the spectrogram with a minimum db value """ @@ -37,7 +12,7 @@ def __init__(self, min_level_db, normalization): self.normalization = normalization def forward(self, specgram): - specgram = torch.log10(torch.clamp(specgram, min=1e-5)) + specgram = torch.log10(torch.clamp(specgram.squeeze(0), min=1e-5)) if self.normalization: return torch.clamp( (self.min_level_db - 20 * specgram) / self.min_level_db, min=0, max=1 diff --git a/test/torchaudio_unittest/functional/functional_cpu_test.py b/test/torchaudio_unittest/functional/functional_cpu_test.py index b9c5a6f64e..6f497a3193 100644 --- a/test/torchaudio_unittest/functional/functional_cpu_test.py +++ b/test/torchaudio_unittest/functional/functional_cpu_test.py @@ -1,23 +1,13 @@ -import math -import warnings - import torch -import torchaudio import torchaudio.functional as F -from parameterized import parameterized -import itertools import unittest +from parameterized import parameterized -from torchaudio_unittest import common_utils -from torchaudio_unittest.common_utils import ( - TorchaudioTestCase, - skipIfNoSox, -) - -from .functional_impl import Functional, FunctionalComplex +from torchaudio_unittest.common_utils import PytorchTestCase, TorchaudioTestCase, skipIfNoSox +from .functional_impl import Functional, FunctionalComplex, FunctionalCPUOnly -class TestFunctionalFloat32(Functional, common_utils.PytorchTestCase): +class TestFunctionalFloat32(Functional, FunctionalCPUOnly, PytorchTestCase): dtype = torch.float32 device = torch.device('cpu') @@ -26,206 +16,23 @@ def test_lfilter_9th_order_filter_stability(self): super().test_lfilter_9th_order_filter_stability() -class TestFunctionalFloat64(Functional, common_utils.PytorchTestCase): +class TestFunctionalFloat64(Functional, FunctionalCPUOnly, PytorchTestCase): dtype = torch.float64 device = torch.device('cpu') -class TestFunctionalComplex64(FunctionalComplex, common_utils.PytorchTestCase): +class TestFunctionalComplex64(FunctionalComplex, FunctionalCPUOnly, PytorchTestCase): complex_dtype = torch.complex64 real_dtype = torch.float32 device = torch.device('cpu') -class TestFunctionalComplex128(FunctionalComplex, common_utils.PytorchTestCase): +class TestFunctionalComplex128(FunctionalComplex, FunctionalCPUOnly, PytorchTestCase): complex_dtype = torch.complex128 real_dtype = torch.float64 device = torch.device('cpu') -class TestCreateFBMatrix(common_utils.TorchaudioTestCase): - def test_no_warning_high_n_freq(self): - with warnings.catch_warnings(record=True) as w: - warnings.simplefilter("always") - F.create_fb_matrix(288, 0, 8000, 128, 16000) - assert len(w) == 0 - - def test_no_warning_low_n_mels(self): - with warnings.catch_warnings(record=True) as w: - warnings.simplefilter("always") - F.create_fb_matrix(201, 0, 8000, 89, 16000) - assert len(w) == 0 - - def test_warning(self): - with warnings.catch_warnings(record=True) as w: - warnings.simplefilter("always") - F.create_fb_matrix(201, 0, 8000, 128, 16000) - assert len(w) == 1 - - -class TestComputeDeltas(common_utils.TorchaudioTestCase): - """Test suite for correctness of compute_deltas""" - - def test_one_channel(self): - specgram = torch.tensor([[[1.0, 2.0, 3.0, 4.0]]]) - expected = torch.tensor([[[0.5, 1.0, 1.0, 0.5]]]) - computed = F.compute_deltas(specgram, win_length=3) - self.assertEqual(computed, expected) - - def test_two_channels(self): - specgram = torch.tensor([[[1.0, 2.0, 3.0, 4.0], - [1.0, 2.0, 3.0, 4.0]]]) - expected = torch.tensor([[[0.5, 1.0, 1.0, 0.5], - [0.5, 1.0, 1.0, 0.5]]]) - computed = F.compute_deltas(specgram, win_length=3) - self.assertEqual(computed, expected) - - -class TestDetectPitchFrequency(common_utils.TorchaudioTestCase): - @parameterized.expand([(100,), (440,)]) - def test_pitch(self, frequency): - sample_rate = 44100 - test_sine_waveform = common_utils.get_sinusoid( - frequency=frequency, sample_rate=sample_rate, duration=5, - ) - - freq = torchaudio.functional.detect_pitch_frequency(test_sine_waveform, sample_rate) - - threshold = 1 - s = ((freq - frequency).abs() > threshold).sum() - self.assertFalse(s) - - -class Testamplitude_to_DB(common_utils.TorchaudioTestCase): - @parameterized.expand([ - ([100, 100],), - ([2, 100, 100],), - ([2, 2, 100, 100],), - ]) - def test_reversible(self, shape): - """Round trip between amplitude and db should return the original for various shape - - This implicitly also tests `DB_to_amplitude`. - - """ - amplitude_mult = 20. - power_mult = 10. - amin = 1e-10 - ref = 1.0 - db_mult = math.log10(max(amin, ref)) - - torch.manual_seed(0) - spec = torch.rand(*shape) * 200 - - # Spectrogram amplitude -> DB -> amplitude - db = F.amplitude_to_DB(spec, amplitude_mult, amin, db_mult, top_db=None) - x2 = F.DB_to_amplitude(db, ref, 0.5) - - self.assertEqual(x2, spec, atol=5e-5, rtol=1e-5) - - # Spectrogram power -> DB -> power - db = F.amplitude_to_DB(spec, power_mult, amin, db_mult, top_db=None) - x2 = F.DB_to_amplitude(db, ref, 1.) - - self.assertEqual(x2, spec) - - @parameterized.expand([ - ([100, 100],), - ([2, 100, 100],), - ([2, 2, 100, 100],), - ]) - def test_top_db_clamp(self, shape): - """Ensure values are properly clamped when `top_db` is supplied.""" - amplitude_mult = 20. - amin = 1e-10 - ref = 1.0 - db_mult = math.log10(max(amin, ref)) - top_db = 40. - - torch.manual_seed(0) - # A random tensor is used for increased entropy, but the max and min for - # each spectrogram still need to be predictable. The max determines the - # decibel cutoff, and the distance from the min must be large enough - # that it triggers a clamp. - spec = torch.rand(*shape) - # Ensure each spectrogram has a min of 0 and a max of 1. - spec -= spec.amin([-2, -1])[..., None, None] - spec /= spec.amax([-2, -1])[..., None, None] - # Expand the range to (0, 200) - wide enough to properly test clamping. - spec *= 200 - - decibels = F.amplitude_to_DB(spec, amplitude_mult, amin, - db_mult, top_db=top_db) - # Ensure the clamp was applied - below_limit = decibels < 6.0205 - assert not below_limit.any(), ( - "{} decibel values were below the expected cutoff:\n{}".format( - below_limit.sum().item(), decibels - ) - ) - # Ensure it didn't over-clamp - close_to_limit = decibels < 6.0207 - assert close_to_limit.any(), ( - f"No values were close to the limit. Did it over-clamp?\n{decibels}" - ) - - -class TestComplexNorm(common_utils.TorchaudioTestCase): - @parameterized.expand(list(itertools.product( - [(1, 2, 1025, 400, 2), (1025, 400, 2)], - [1, 2, 0.7] - ))) - def test_complex_norm(self, shape, power): - torch.random.manual_seed(42) - complex_tensor = torch.randn(*shape) - expected_norm_tensor = complex_tensor.pow(2).sum(-1).pow(power / 2) - norm_tensor = F.complex_norm(complex_tensor, power) - self.assertEqual(norm_tensor, expected_norm_tensor, atol=1e-5, rtol=1e-5) - - -class TestMaskAlongAxis(common_utils.TorchaudioTestCase): - @parameterized.expand(list(itertools.product( - [(2, 1025, 400), (1, 201, 100)], - [100], - [0., 30.], - [1, 2] - ))) - def test_mask_along_axis(self, shape, mask_param, mask_value, axis): - torch.random.manual_seed(42) - specgram = torch.randn(*shape) - mask_specgram = F.mask_along_axis(specgram, mask_param, mask_value, axis) - - other_axis = 1 if axis == 2 else 2 - - masked_columns = (mask_specgram == mask_value).sum(other_axis) - num_masked_columns = (masked_columns == mask_specgram.size(other_axis)).sum() - num_masked_columns //= mask_specgram.size(0) - - assert mask_specgram.size() == specgram.size() - assert num_masked_columns < mask_param - - -class TestMaskAlongAxisIID(common_utils.TorchaudioTestCase): - @parameterized.expand(list(itertools.product( - [100], - [0., 30.], - [2, 3] - ))) - def test_mask_along_axis_iid(self, mask_param, mask_value, axis): - torch.random.manual_seed(42) - specgrams = torch.randn(4, 2, 1025, 400) - - mask_specgrams = F.mask_along_axis_iid(specgrams, mask_param, mask_value, axis) - - other_axis = 2 if axis == 3 else 3 - - masked_columns = (mask_specgrams == mask_value).sum(other_axis) - num_masked_columns = (masked_columns == mask_specgrams.size(other_axis)).sum(-1) - - assert mask_specgrams.size() == specgrams.size() - assert (num_masked_columns < mask_param).sum() == num_masked_columns.numel() - - @skipIfNoSox class TestApplyCodec(TorchaudioTestCase): backend = "sox_io" diff --git a/test/torchaudio_unittest/functional/functional_cuda_test.py b/test/torchaudio_unittest/functional/functional_cuda_test.py index ebf8cd8326..054e2c3e4f 100644 --- a/test/torchaudio_unittest/functional/functional_cuda_test.py +++ b/test/torchaudio_unittest/functional/functional_cuda_test.py @@ -1,12 +1,12 @@ import torch import unittest -from torchaudio_unittest import common_utils +from torchaudio_unittest.common_utils import PytorchTestCase, skipIfNoCuda from .functional_impl import Functional, FunctionalComplex -@common_utils.skipIfNoCuda -class TestFunctionalloat32(Functional, common_utils.PytorchTestCase): +@skipIfNoCuda +class TestFunctionalFloat32(Functional, PytorchTestCase): dtype = torch.float32 device = torch.device('cuda') @@ -15,21 +15,21 @@ def test_lfilter_9th_order_filter_stability(self): super().test_lfilter_9th_order_filter_stability() -@common_utils.skipIfNoCuda -class TestLFilterFloat64(Functional, common_utils.PytorchTestCase): +@skipIfNoCuda +class TestLFilterFloat64(Functional, PytorchTestCase): dtype = torch.float64 device = torch.device('cuda') -@common_utils.skipIfNoCuda -class TestFunctionalComplex64(FunctionalComplex, common_utils.PytorchTestCase): +@skipIfNoCuda +class TestFunctionalComplex64(FunctionalComplex, PytorchTestCase): complex_dtype = torch.complex64 real_dtype = torch.float32 device = torch.device('cuda') -@common_utils.skipIfNoCuda -class TestFunctionalComplex128(FunctionalComplex, common_utils.PytorchTestCase): +@skipIfNoCuda +class TestFunctionalComplex128(FunctionalComplex, PytorchTestCase): complex_dtype = torch.complex64 real_dtype = torch.float32 device = torch.device('cuda') diff --git a/test/torchaudio_unittest/functional/functional_impl.py b/test/torchaudio_unittest/functional/functional_impl.py index 8b890e9563..3c78ee3e90 100644 --- a/test/torchaudio_unittest/functional/functional_impl.py +++ b/test/torchaudio_unittest/functional/functional_impl.py @@ -1,15 +1,18 @@ -"""Test defintion common to CPU and CUDA""" +"""Test definition common to CPU and CUDA""" +import math +import itertools +import warnings + +import numpy as np import torch import torchaudio.functional as F from parameterized import parameterized -import numpy as np from scipy import signal -from torchaudio_unittest import common_utils -from torchaudio_unittest.common_utils import nested_params +from torchaudio_unittest.common_utils import TestBaseMixin, get_sinusoid, nested_params -class Functional(common_utils.TestBaseMixin): +class Functional(TestBaseMixin): def test_lfilter_simple(self): """ Create a very basic signal, @@ -91,7 +94,7 @@ def test_spectogram_grad_at_zero(self, power): assert not x.grad.isnan().sum() -class FunctionalComplex(common_utils.TestBaseMixin): +class FunctionalComplex(TestBaseMixin): complex_dtype = None real_dtype = None device = None @@ -125,3 +128,157 @@ def test_phase_vocoder_shape(self, rate, test_pseudo_complex): expected_shape = torch.Size([batch_size, num_freq, int(np.ceil(num_frames / rate))]) output_shape = (torch.view_as_complex(spec_stretch) if test_pseudo_complex else spec_stretch).shape assert output_shape == expected_shape + + +class FunctionalCPUOnly(TestBaseMixin): + def test_create_fb_matrix_no_warning_high_n_freq(self): + with warnings.catch_warnings(record=True) as w: + warnings.simplefilter("always") + F.create_fb_matrix(288, 0, 8000, 128, 16000) + assert len(w) == 0 + + def test_create_fb_matrix_no_warning_low_n_mels(self): + with warnings.catch_warnings(record=True) as w: + warnings.simplefilter("always") + F.create_fb_matrix(201, 0, 8000, 89, 16000) + assert len(w) == 0 + + def test_create_fb_matrix_warning(self): + with warnings.catch_warnings(record=True) as w: + warnings.simplefilter("always") + F.create_fb_matrix(201, 0, 8000, 128, 16000) + assert len(w) == 1 + + def test_compute_deltas_one_channel(self): + specgram = torch.tensor([[[1.0, 2.0, 3.0, 4.0]]]) + expected = torch.tensor([[[0.5, 1.0, 1.0, 0.5]]]) + computed = F.compute_deltas(specgram, win_length=3) + self.assertEqual(computed, expected) + + def test_compute_deltas_two_channels(self): + specgram = torch.tensor([[[1.0, 2.0, 3.0, 4.0], + [1.0, 2.0, 3.0, 4.0]]]) + expected = torch.tensor([[[0.5, 1.0, 1.0, 0.5], + [0.5, 1.0, 1.0, 0.5]]]) + computed = F.compute_deltas(specgram, win_length=3) + self.assertEqual(computed, expected) + + @parameterized.expand([(100,), (440,)]) + def test_detect_pitch_frequency_pitch(self, frequency): + sample_rate = 44100 + test_sine_waveform = get_sinusoid( + frequency=frequency, sample_rate=sample_rate, duration=5 + ) + + freq = F.detect_pitch_frequency(test_sine_waveform, sample_rate) + + threshold = 1 + s = ((freq - frequency).abs() > threshold).sum() + self.assertFalse(s) + + @parameterized.expand([([100, 100],), ([2, 100, 100],), ([2, 2, 100, 100],)]) + def test_amplitude_to_DB_reversible(self, shape): + """Round trip between amplitude and db should return the original for various shape + + This implicitly also tests `DB_to_amplitude`. + + """ + amplitude_mult = 20. + power_mult = 10. + amin = 1e-10 + ref = 1.0 + db_mult = math.log10(max(amin, ref)) + + torch.manual_seed(0) + spec = torch.rand(*shape) * 200 + + # Spectrogram amplitude -> DB -> amplitude + db = F.amplitude_to_DB(spec, amplitude_mult, amin, db_mult, top_db=None) + x2 = F.DB_to_amplitude(db, ref, 0.5) + + self.assertEqual(x2, spec, atol=5e-5, rtol=1e-5) + + # Spectrogram power -> DB -> power + db = F.amplitude_to_DB(spec, power_mult, amin, db_mult, top_db=None) + x2 = F.DB_to_amplitude(db, ref, 1.) + + self.assertEqual(x2, spec) + + @parameterized.expand([([100, 100],), ([2, 100, 100],), ([2, 2, 100, 100],)]) + def test_amplitude_to_DB_top_db_clamp(self, shape): + """Ensure values are properly clamped when `top_db` is supplied.""" + amplitude_mult = 20. + amin = 1e-10 + ref = 1.0 + db_mult = math.log10(max(amin, ref)) + top_db = 40. + + torch.manual_seed(0) + # A random tensor is used for increased entropy, but the max and min for + # each spectrogram still need to be predictable. The max determines the + # decibel cutoff, and the distance from the min must be large enough + # that it triggers a clamp. + spec = torch.rand(*shape) + # Ensure each spectrogram has a min of 0 and a max of 1. + spec -= spec.amin([-2, -1])[..., None, None] + spec /= spec.amax([-2, -1])[..., None, None] + # Expand the range to (0, 200) - wide enough to properly test clamping. + spec *= 200 + + decibels = F.amplitude_to_DB(spec, amplitude_mult, amin, + db_mult, top_db=top_db) + # Ensure the clamp was applied + below_limit = decibels < 6.0205 + assert not below_limit.any(), ( + "{} decibel values were below the expected cutoff:\n{}".format( + below_limit.sum().item(), decibels + ) + ) + # Ensure it didn't over-clamp + close_to_limit = decibels < 6.0207 + assert close_to_limit.any(), ( + f"No values were close to the limit. Did it over-clamp?\n{decibels}" + ) + + @parameterized.expand( + list(itertools.product([(1, 2, 1025, 400, 2), (1025, 400, 2)], [1, 2, 0.7])) + ) + def test_complex_norm(self, shape, power): + torch.random.manual_seed(42) + complex_tensor = torch.randn(*shape) + expected_norm_tensor = complex_tensor.pow(2).sum(-1).pow(power / 2) + norm_tensor = F.complex_norm(complex_tensor, power) + self.assertEqual(norm_tensor, expected_norm_tensor, atol=1e-5, rtol=1e-5) + + @parameterized.expand( + list(itertools.product([(2, 1025, 400), (1, 201, 100)], [100], [0., 30.], [1, 2])) + ) + def test_mask_along_axis(self, shape, mask_param, mask_value, axis): + torch.random.manual_seed(42) + specgram = torch.randn(*shape) + mask_specgram = F.mask_along_axis(specgram, mask_param, mask_value, axis) + + other_axis = 1 if axis == 2 else 2 + + masked_columns = (mask_specgram == mask_value).sum(other_axis) + num_masked_columns = (masked_columns == mask_specgram.size(other_axis)).sum() + num_masked_columns = torch.div( + num_masked_columns, mask_specgram.size(0), rounding_mode='floor') + + assert mask_specgram.size() == specgram.size() + assert num_masked_columns < mask_param + + @parameterized.expand(list(itertools.product([100], [0., 30.], [2, 3]))) + def test_mask_along_axis_iid(self, mask_param, mask_value, axis): + torch.random.manual_seed(42) + specgrams = torch.randn(4, 2, 1025, 400) + + mask_specgrams = F.mask_along_axis_iid(specgrams, mask_param, mask_value, axis) + + other_axis = 2 if axis == 3 else 3 + + masked_columns = (mask_specgrams == mask_value).sum(other_axis) + num_masked_columns = (masked_columns == mask_specgrams.size(other_axis)).sum(-1) + + assert mask_specgrams.size() == specgrams.size() + assert (num_masked_columns < mask_param).sum() == num_masked_columns.numel() diff --git a/test/torchaudio_unittest/transforms/autograd_test_impl.py b/test/torchaudio_unittest/transforms/autograd_test_impl.py index 438f623855..7c368445a8 100644 --- a/test/torchaudio_unittest/transforms/autograd_test_impl.py +++ b/test/torchaudio_unittest/transforms/autograd_test_impl.py @@ -137,6 +137,13 @@ def test_amplitude_to_db(self): waveform = get_whitenoise(sample_rate=sample_rate, duration=0.05, n_channels=2) self.assert_grad(transform, [waveform]) + @parameterized.expand([(1.5, "amplitude"), (2, "power"), (10, "db")]) + def test_vol(self, gain, gain_type): + sample_rate = 8000 + transform = T.Vol(gain=gain, gain_type=gain_type) + waveform = get_whitenoise(sample_rate=sample_rate, duration=0.05, n_channels=2) + self.assert_grad(transform, [waveform]) + @unittest.expectedFailure def test_timestretch_zeros_fail(self): """Test that ``T.TimeStretch`` fails gradcheck at 0 diff --git a/third_party/sox/CMakeLists.txt b/third_party/sox/CMakeLists.txt index 7bbad0e99e..42d9d06bfb 100644 --- a/third_party/sox/CMakeLists.txt +++ b/third_party/sox/CMakeLists.txt @@ -172,6 +172,7 @@ set(SOX_OPTIONS --without-sndio --without-sunaudio --without-waveaudio + --without-wavpack --without-twolame ) diff --git a/torchaudio/_internal/misc_ops.py b/torchaudio/_internal/misc_ops.py deleted file mode 100644 index b67b8d1598..0000000000 --- a/torchaudio/_internal/misc_ops.py +++ /dev/null @@ -1,30 +0,0 @@ -from typing import Union, Callable - -import torch -from torch import Tensor - - -def normalize_audio(signal: Tensor, normalization: Union[bool, float, Callable]) -> None: - """Audio normalization of a tensor in-place. The normalization can be a bool, - a number, or a callable that takes the audio tensor as an input. SoX uses - 32-bit signed integers internally, thus bool normalizes based on that assumption. - """ - - if not normalization: - return - - if isinstance(normalization, bool): - normalization = 1 << 31 - - if isinstance(normalization, (float, int)): - # normalize with custom value - signal /= normalization - elif callable(normalization): - signal /= normalization(signal) - - -def check_input(src: Tensor) -> None: - if not torch.is_tensor(src): - raise TypeError('Expected a tensor, got %s' % type(src)) - if src.is_cuda: - raise TypeError('Expected a CPU based tensor, got %s' % type(src)) diff --git a/torchaudio/functional/filtering.py b/torchaudio/functional/filtering.py index ad594350d3..93da27493b 100644 --- a/torchaudio/functional/filtering.py +++ b/torchaudio/functional/filtering.py @@ -46,7 +46,7 @@ def _generate_wave_table( d = (torch.sin(point.to(torch.float64) / table_size * 2 * math.pi) + 1) / 2 elif wave_type == "TRIANGLE": d = point.to(torch.float64) * 2 / table_size - value = 4 * point // table_size + value = torch.div(4 * point, table_size, rounding_mode='floor') d[value == 0] = d[value == 0] + 0.5 d[value == 1] = 1.5 - d[value == 1] d[value == 2] = 1.5 - d[value == 2] diff --git a/torchaudio/transforms.py b/torchaudio/transforms.py index 96832167d2..a04592f2c4 100644 --- a/torchaudio/transforms.py +++ b/torchaudio/transforms.py @@ -27,6 +27,8 @@ 'SlidingWindowCmn', 'Vad', 'SpectralCentroid', + 'Vol', + 'ComputeDeltas', ] From b866c06dc8047e42cd7813453ea188d112d01a68 Mon Sep 17 00:00:00 2001 From: Christian Puhrsch Date: Thu, 29 Apr 2021 15:24:02 -0700 Subject: [PATCH 40/73] Import torchaudio #1475 b5d8027 Reviewed By: mthrok Differential Revision: D28098981 fbshipit-source-id: 48231fc919f3fda2bf946a9a6f0c666f9a417017 --- .circleci/config.yml | 2 +- .circleci/config.yml.in | 2 +- examples/pipeline_wav2letter/README.md | 21 +-- examples/pipeline_wav2letter/main.py | 20 +-- .../functional/functional_cpu_test.py | 6 +- .../functional/functional_impl.py | 130 +++++++++--------- .../transforms/autograd_test_impl.py | 10 ++ torchaudio/functional/functional.py | 2 +- torchaudio/sox_effects/sox_effects.py | 5 +- 9 files changed, 107 insertions(+), 91 deletions(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index 2cbddf2e3c..7bba9977fd 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -16,7 +16,7 @@ executors: windows-gpu: machine: resource_class: windows.gpu.nvidia.medium - image: windows-server-2019-nvidia:stable + image: windows-server-2019-nvidia:previous shell: bash.exe commands: diff --git a/.circleci/config.yml.in b/.circleci/config.yml.in index f15767041e..cc4c391ea1 100644 --- a/.circleci/config.yml.in +++ b/.circleci/config.yml.in @@ -16,7 +16,7 @@ executors: windows-gpu: machine: resource_class: windows.gpu.nvidia.medium - image: windows-server-2019-nvidia:stable + image: windows-server-2019-nvidia:previous shell: bash.exe commands: diff --git a/examples/pipeline_wav2letter/README.md b/examples/pipeline_wav2letter/README.md index 49cca3c83d..afecf5c204 100644 --- a/examples/pipeline_wav2letter/README.md +++ b/examples/pipeline_wav2letter/README.md @@ -3,7 +3,7 @@ This is an example pipeline for speech recognition using a greedy or Viterbi CTC ### Usage More information about each command line parameters is available with the `--help` option. An example can be invoked as follows. -``` +```bash DATASET_ROOT = // DATASET_FOLDER_IN_ARCHIVE = 'LibriSpeech' @@ -25,19 +25,20 @@ python main.py \ --normalize \ --optimizer adadelta \ --scheduler reduceonplateau \ - --epochs 30 + --epochs 40 ``` -With these default parameters, we get a character error rate of 13.8% on dev-clean after 30 epochs. -### Output +With these default parameters, we get 13.3 %CER and 41.9 %WER on dev-clean after 40 epochs (character and word error rates, respectively) while training on train-clean. The tail of the output is the following. -The information reported at each iteration and epoch (e.g. loss, character error rate, word error rate) is printed to standard output in the form of one json per line, e.g. -```python -{"name": "train", "epoch": 0, "cer over target length": 1.0, "cumulative cer": 23317.0, "total chars": 23317.0, "cer": 0.0, "cumulative cer over target length": 0.0, "wer over target length": 1.0, "cumulative wer": 4446.0, "total words": 4446.0, "wer": 0.0, "cumulative wer over target length": 0.0, "lr": 0.6, "batch size": 128, "n_channel": 13, "n_time": 2453, "dataset length": 128.0, "iteration": 1.0, "loss": 8.712121963500977, "cumulative loss": 8.712121963500977, "average loss": 8.712121963500977, "iteration time": 41.46276903152466, "epoch time": 41.46276903152466} -{"name": "train", "epoch": 0, "cer over target length": 1.0, "cumulative cer": 46005.0, "total chars": 46005.0, "cer": 0.0, "cumulative cer over target length": 0.0, "wer over target length": 1.0, "cumulative wer": 8762.0, "total words": 8762.0, "wer": 0.0, "cumulative wer over target length": 0.0, "lr": 0.6, "batch size": 128, "n_channel": 13, "n_time": 1703, "dataset length": 256.0, "iteration": 2.0, "loss": 8.918599128723145, "cumulative loss": 17.63072109222412, "average loss": 8.81536054611206, "iteration time": 1.2905676364898682, "epoch time": 42.753336668014526} -{"name": "train", "epoch": 0, "cer over target length": 1.0, "cumulative cer": 70030.0, "total chars": 70030.0, "cer": 0.0, "cumulative cer over target length": 0.0, "wer over target length": 1.0, "cumulative wer": 13348.0, "total words": 13348.0, "wer": 0.0, "cumulative wer over target length": 0.0, "lr": 0.6, "batch size": 128, "n_channel": 13, "n_time": 1713, "dataset length": 384.0, "iteration": 3.0, "loss": 8.550191879272461, "cumulative loss": 26.180912971496582, "average loss": 8.726970990498861, "iteration time": 1.2109291553497314, "epoch time": 43.96426582336426} +```json +... +{"name": "train", "epoch": 40, "batch char error": 925, "batch char total": 22563, "batch char error rate": 0.040996321411159865, "epoch char error": 1135098.0, "epoch char total": 23857713.0, "epoch char error rate": 0.047577821059378154, "batch word error": 791, "batch word total": 4308, "batch word error rate": 0.18361188486536675, "epoch word error": 942906.0, "epoch word total": 4569507.0, "epoch word error rate": 0.20634742435015418, "lr": 0.06, "batch size": 128, "n_channel": 13, "n_time": 1685, "dataset length": 132096.0, "iteration": 1032.0, "loss": 0.07428030669689178, "cumulative loss": 90.47326805442572, "average loss": 0.08766789540157531, "iteration time": 1.9895553588867188, "epoch time": 2036.8874564170837} +{"name": "train", "epoch": 40, "batch char error": 1131, "batch char total": 24260, "batch char error rate": 0.0466199505358615, "epoch char error": 1136229.0, "epoch char total": 23881973.0, "epoch char error rate": 0.04757684802675223, "batch word error": 957, "batch word total": 4657, "batch word error rate": 0.2054971011380717, "epoch word error": 943863.0, "epoch word total": 4574164.0, "epoch word error rate": 0.20634655862798099, "lr": 0.06, "batch size": 128, "n_channel": 13, "n_time": 1641, "dataset length": 132224.0, "iteration": 1033.0, "loss": 0.08775319904088974, "cumulative loss": 90.5610212534666, "average loss": 0.08766797798012256, "iteration time": 2.108018159866333, "epoch time": 2038.99547457695} +{"name": "train", "epoch": 40, "batch char error": 1099, "batch char total": 23526, "batch char error rate": 0.0467142735696676, "epoch char error": 1137328.0, "epoch char total": 23905499.0, "epoch char error rate": 0.04757599914563591, "batch word error": 936, "batch word total": 4544, "batch word error rate": 0.20598591549295775, "epoch word error": 944799.0, "epoch word total": 4578708.0, "epoch word error rate": 0.20634620071863066, "lr": 0.06, "batch size": 128, "n_channel": 13, "n_time": 1682, "dataset length": 132352.0, "iteration": 1034.0, "loss": 0.0791337713599205, "cumulative loss": 90.64015502482653, "average loss": 0.08765972439538348, "iteration time": 2.0329701900482178, "epoch time": 2041.0284447669983} +{"name": "train", "epoch": 40, "batch char error": 1023, "batch char total": 22399, "batch char error rate": 0.045671681771507655, "epoch char error": 1138351.0, "epoch char total": 23927898.0, "epoch char error rate": 0.04757421650660664, "batch word error": 863, "batch word total": 4318, "batch word error rate": 0.1998610467809171, "epoch word error": 945662.0, "epoch word total": 4583026.0, "epoch word error rate": 0.20634009058643787, "lr": 0.06, "batch size": 128, "n_channel": 13, "n_time": 1644, "dataset length": 132480.0, "iteration": 1035.0, "loss": 0.07874362915754318, "cumulative loss": 90.71889865398407, "average loss": 0.08765110981061262, "iteration time": 1.9106628894805908, "epoch time": 2042.9391076564789} +{"name": "validation", "epoch": 40, "cumulative loss": 12.095281183719635, "dataset length": 2688.0, "iteration": 21.0, "batch char error": 1867, "batch char total": 14792, "batch char error rate": 0.12621687398593834, "epoch char error": 37119.0, "epoch char total": 280923.0, "epoch char error rate": 0.13213229247872194, "batch word error": 1155, "batch word total": 2841, "batch word error rate": 0.4065469904963041, "epoch word error": 22601.0, "epoch word total": 54008.0, "epoch word error rate": 0.418475040734706, "average loss": 0.575965770653316, "validation time": 24.185853481292725} ``` -One way to import the output in python with pandas is by saving the standard output to a file, and then using `pandas.read_json(filename, lines=True)`. +As can be seen in the output above, the information reported at each iteration and epoch (e.g. loss, character error rate, word error rate) is printed to standard output in the form of one json per line. One way to import the output in python with pandas is by saving the standard output to a file, and then using `pandas.read_json(filename, lines=True)`. ## Structure of pipeline diff --git a/examples/pipeline_wav2letter/main.py b/examples/pipeline_wav2letter/main.py index 549f3dcdeb..f771fa8fce 100644 --- a/examples/pipeline_wav2letter/main.py +++ b/examples/pipeline_wav2letter/main.py @@ -220,10 +220,12 @@ def compute_error_rates(outputs, targets, decoder, language_model, metric): cers = [levenshtein_distance(t, o) for t, o in zip(target, output)] cers = sum(cers) n = sum(len(t) for t in target) - metric["cer over target length"] = cers / n - metric["cumulative cer"] += cers - metric["total chars"] += n - metric["cumulative cer over target length"] = metric["cer"] / metric["total chars"] + metric["batch char error"] = cers + metric["batch char total"] = n + metric["batch char error rate"] = cers / n + metric["epoch char error"] += cers + metric["epoch char total"] += n + metric["epoch char error rate"] = metric["epoch char error"] / metric["epoch char total"] # Compute WER @@ -233,10 +235,12 @@ def compute_error_rates(outputs, targets, decoder, language_model, metric): wers = [levenshtein_distance(t, o) for t, o in zip(target, output)] wers = sum(wers) n = sum(len(t) for t in target) - metric["wer over target length"] = wers / n - metric["cumulative wer"] += wers - metric["total words"] += n - metric["cumulative wer over target length"] = metric["wer"] / metric["total words"] + metric["batch word error"] = wers + metric["batch word total"] = n + metric["batch word error rate"] = wers / n + metric["epoch word error"] += wers + metric["epoch word total"] += n + metric["epoch word error rate"] = metric["epoch word error"] / metric["epoch word total"] def train_one_epoch( diff --git a/test/torchaudio_unittest/functional/functional_cpu_test.py b/test/torchaudio_unittest/functional/functional_cpu_test.py index 6f497a3193..73cc8662fa 100644 --- a/test/torchaudio_unittest/functional/functional_cpu_test.py +++ b/test/torchaudio_unittest/functional/functional_cpu_test.py @@ -16,18 +16,18 @@ def test_lfilter_9th_order_filter_stability(self): super().test_lfilter_9th_order_filter_stability() -class TestFunctionalFloat64(Functional, FunctionalCPUOnly, PytorchTestCase): +class TestFunctionalFloat64(Functional, PytorchTestCase): dtype = torch.float64 device = torch.device('cpu') -class TestFunctionalComplex64(FunctionalComplex, FunctionalCPUOnly, PytorchTestCase): +class TestFunctionalComplex64(FunctionalComplex, PytorchTestCase): complex_dtype = torch.complex64 real_dtype = torch.float32 device = torch.device('cpu') -class TestFunctionalComplex128(FunctionalComplex, FunctionalCPUOnly, PytorchTestCase): +class TestFunctionalComplex128(FunctionalComplex, PytorchTestCase): complex_dtype = torch.complex128 real_dtype = torch.float64 device = torch.device('cpu') diff --git a/test/torchaudio_unittest/functional/functional_impl.py b/test/torchaudio_unittest/functional/functional_impl.py index 3c78ee3e90..f4cc94f806 100644 --- a/test/torchaudio_unittest/functional/functional_impl.py +++ b/test/torchaudio_unittest/functional/functional_impl.py @@ -93,73 +93,17 @@ def test_spectogram_grad_at_zero(self, power): spec.sum().backward() assert not x.grad.isnan().sum() - -class FunctionalComplex(TestBaseMixin): - complex_dtype = None - real_dtype = None - device = None - - @nested_params( - [0.5, 1.01, 1.3], - [True, False], - ) - def test_phase_vocoder_shape(self, rate, test_pseudo_complex): - """Verify the output shape of phase vocoder""" - hop_length = 256 - num_freq = 1025 - num_frames = 400 - batch_size = 2 - - torch.random.manual_seed(42) - spec = torch.randn( - batch_size, num_freq, num_frames, dtype=self.complex_dtype, device=self.device) - if test_pseudo_complex: - spec = torch.view_as_real(spec) - - phase_advance = torch.linspace( - 0, - np.pi * hop_length, - num_freq, - dtype=self.real_dtype, device=self.device)[..., None] - - spec_stretch = F.phase_vocoder(spec, rate=rate, phase_advance=phase_advance) - - assert spec.dim() == spec_stretch.dim() - expected_shape = torch.Size([batch_size, num_freq, int(np.ceil(num_frames / rate))]) - output_shape = (torch.view_as_complex(spec_stretch) if test_pseudo_complex else spec_stretch).shape - assert output_shape == expected_shape - - -class FunctionalCPUOnly(TestBaseMixin): - def test_create_fb_matrix_no_warning_high_n_freq(self): - with warnings.catch_warnings(record=True) as w: - warnings.simplefilter("always") - F.create_fb_matrix(288, 0, 8000, 128, 16000) - assert len(w) == 0 - - def test_create_fb_matrix_no_warning_low_n_mels(self): - with warnings.catch_warnings(record=True) as w: - warnings.simplefilter("always") - F.create_fb_matrix(201, 0, 8000, 89, 16000) - assert len(w) == 0 - - def test_create_fb_matrix_warning(self): - with warnings.catch_warnings(record=True) as w: - warnings.simplefilter("always") - F.create_fb_matrix(201, 0, 8000, 128, 16000) - assert len(w) == 1 - def test_compute_deltas_one_channel(self): - specgram = torch.tensor([[[1.0, 2.0, 3.0, 4.0]]]) - expected = torch.tensor([[[0.5, 1.0, 1.0, 0.5]]]) + specgram = torch.tensor([[[1.0, 2.0, 3.0, 4.0]]], dtype=self.dtype, device=self.device) + expected = torch.tensor([[[0.5, 1.0, 1.0, 0.5]]], dtype=self.dtype, device=self.device) computed = F.compute_deltas(specgram, win_length=3) self.assertEqual(computed, expected) def test_compute_deltas_two_channels(self): specgram = torch.tensor([[[1.0, 2.0, 3.0, 4.0], - [1.0, 2.0, 3.0, 4.0]]]) + [1.0, 2.0, 3.0, 4.0]]], dtype=self.dtype, device=self.device) expected = torch.tensor([[[0.5, 1.0, 1.0, 0.5], - [0.5, 1.0, 1.0, 0.5]]]) + [0.5, 1.0, 1.0, 0.5]]], dtype=self.dtype, device=self.device) computed = F.compute_deltas(specgram, win_length=3) self.assertEqual(computed, expected) @@ -190,7 +134,7 @@ def test_amplitude_to_DB_reversible(self, shape): db_mult = math.log10(max(amin, ref)) torch.manual_seed(0) - spec = torch.rand(*shape) * 200 + spec = torch.rand(*shape, dtype=self.dtype, device=self.device) * 200 # Spectrogram amplitude -> DB -> amplitude db = F.amplitude_to_DB(spec, amplitude_mult, amin, db_mult, top_db=None) @@ -218,7 +162,7 @@ def test_amplitude_to_DB_top_db_clamp(self, shape): # each spectrogram still need to be predictable. The max determines the # decibel cutoff, and the distance from the min must be large enough # that it triggers a clamp. - spec = torch.rand(*shape) + spec = torch.rand(*shape, dtype=self.dtype, device=self.device) # Ensure each spectrogram has a min of 0 and a max of 1. spec -= spec.amin([-2, -1])[..., None, None] spec /= spec.amax([-2, -1])[..., None, None] @@ -245,7 +189,7 @@ def test_amplitude_to_DB_top_db_clamp(self, shape): ) def test_complex_norm(self, shape, power): torch.random.manual_seed(42) - complex_tensor = torch.randn(*shape) + complex_tensor = torch.randn(*shape, dtype=self.dtype, device=self.device) expected_norm_tensor = complex_tensor.pow(2).sum(-1).pow(power / 2) norm_tensor = F.complex_norm(complex_tensor, power) self.assertEqual(norm_tensor, expected_norm_tensor, atol=1e-5, rtol=1e-5) @@ -255,7 +199,7 @@ def test_complex_norm(self, shape, power): ) def test_mask_along_axis(self, shape, mask_param, mask_value, axis): torch.random.manual_seed(42) - specgram = torch.randn(*shape) + specgram = torch.randn(*shape, dtype=self.dtype, device=self.device) mask_specgram = F.mask_along_axis(specgram, mask_param, mask_value, axis) other_axis = 1 if axis == 2 else 2 @@ -271,7 +215,7 @@ def test_mask_along_axis(self, shape, mask_param, mask_value, axis): @parameterized.expand(list(itertools.product([100], [0., 30.], [2, 3]))) def test_mask_along_axis_iid(self, mask_param, mask_value, axis): torch.random.manual_seed(42) - specgrams = torch.randn(4, 2, 1025, 400) + specgrams = torch.randn(4, 2, 1025, 400, dtype=self.dtype, device=self.device) mask_specgrams = F.mask_along_axis_iid(specgrams, mask_param, mask_value, axis) @@ -282,3 +226,59 @@ def test_mask_along_axis_iid(self, mask_param, mask_value, axis): assert mask_specgrams.size() == specgrams.size() assert (num_masked_columns < mask_param).sum() == num_masked_columns.numel() + + +class FunctionalComplex(TestBaseMixin): + complex_dtype = None + real_dtype = None + device = None + + @nested_params( + [0.5, 1.01, 1.3], + [True, False], + ) + def test_phase_vocoder_shape(self, rate, test_pseudo_complex): + """Verify the output shape of phase vocoder""" + hop_length = 256 + num_freq = 1025 + num_frames = 400 + batch_size = 2 + + torch.random.manual_seed(42) + spec = torch.randn( + batch_size, num_freq, num_frames, dtype=self.complex_dtype, device=self.device) + if test_pseudo_complex: + spec = torch.view_as_real(spec) + + phase_advance = torch.linspace( + 0, + np.pi * hop_length, + num_freq, + dtype=self.real_dtype, device=self.device)[..., None] + + spec_stretch = F.phase_vocoder(spec, rate=rate, phase_advance=phase_advance) + + assert spec.dim() == spec_stretch.dim() + expected_shape = torch.Size([batch_size, num_freq, int(np.ceil(num_frames / rate))]) + output_shape = (torch.view_as_complex(spec_stretch) if test_pseudo_complex else spec_stretch).shape + assert output_shape == expected_shape + + +class FunctionalCPUOnly(TestBaseMixin): + def test_create_fb_matrix_no_warning_high_n_freq(self): + with warnings.catch_warnings(record=True) as w: + warnings.simplefilter("always") + F.create_fb_matrix(288, 0, 8000, 128, 16000) + assert len(w) == 0 + + def test_create_fb_matrix_no_warning_low_n_mels(self): + with warnings.catch_warnings(record=True) as w: + warnings.simplefilter("always") + F.create_fb_matrix(201, 0, 8000, 89, 16000) + assert len(w) == 0 + + def test_create_fb_matrix_warning(self): + with warnings.catch_warnings(record=True) as w: + warnings.simplefilter("always") + F.create_fb_matrix(201, 0, 8000, 128, 16000) + assert len(w) == 1 diff --git a/test/torchaudio_unittest/transforms/autograd_test_impl.py b/test/torchaudio_unittest/transforms/autograd_test_impl.py index 7c368445a8..b8fe6c1863 100644 --- a/test/torchaudio_unittest/transforms/autograd_test_impl.py +++ b/test/torchaudio_unittest/transforms/autograd_test_impl.py @@ -137,6 +137,16 @@ def test_amplitude_to_db(self): waveform = get_whitenoise(sample_rate=sample_rate, duration=0.05, n_channels=2) self.assert_grad(transform, [waveform]) + def test_melscale(self): + sample_rate = 8000 + n_fft = 400 + n_mels = n_fft // 2 + 1 + transform = T.MelScale(sample_rate=sample_rate, n_mels=n_mels) + spec = get_spectrogram( + get_whitenoise(sample_rate=sample_rate, duration=0.05, n_channels=2), + n_fft=n_fft, power=1) + self.assert_grad(transform, [spec]) + @parameterized.expand([(1.5, "amplitude"), (2, "power"), (10, "db")]) def test_vol(self, gain, gain_type): sample_rate = 8000 diff --git a/torchaudio/functional/functional.py b/torchaudio/functional/functional.py index 9d23a2cace..cef2553d82 100644 --- a/torchaudio/functional/functional.py +++ b/torchaudio/functional/functional.py @@ -1160,7 +1160,7 @@ def apply_codec( When True, both the input and output Tensor have dimension ``[channel, time]``. Otherwise, they have dimension ``[time, channel]``. compression (float): Used for formats other than WAV. - For mor details see :py:func:`torchaudio.backend.sox_io_backend.save`. + For more details see :py:func:`torchaudio.backend.sox_io_backend.save`. encoding (str, optional): Changes the encoding for the supported formats. For more details see :py:func:`torchaudio.backend.sox_io_backend.save`. bits_per_sample (int, optional): Changes the bit depth for the supported formats. diff --git a/torchaudio/sox_effects/sox_effects.py b/torchaudio/sox_effects/sox_effects.py index 26fc0659e6..05cd860a7f 100644 --- a/torchaudio/sox_effects/sox_effects.py +++ b/torchaudio/sox_effects/sox_effects.py @@ -61,14 +61,15 @@ def apply_effects_tensor( """Apply sox effects to given Tensor Note: + This function only works on CPU Tensors. This function works in the way very similar to ``sox`` command, however there are slight differences. For example, ``sox`` command adds certain effects automatically (such as ``rate`` effect after ``speed`` and ``pitch`` and other effects), but this function does only applies the given effects. (Therefore, to actually apply ``speed`` effect, you also - need to give ``rate`` effect with desired sampling rate.) + need to give ``rate`` effect with desired sampling rate.). Args: - tensor (torch.Tensor): Input 2D Tensor. + tensor (torch.Tensor): Input 2D CPU Tensor. sample_rate (int): Sample rate effects (List[List[str]]): List of effects. channels_first (bool): Indicates if the input Tensor's dimension is From 1f9b7e7d3e2ed9339b010505d5eb4e96fabe60e3 Mon Sep 17 00:00:00 2001 From: Caroline Chen Date: Fri, 30 Apr 2021 12:53:14 -0700 Subject: [PATCH 41/73] Replace prototype RNNTL with PySpeech RNNTL Summary: - bind RNNTL to `torchaudio` - remove previous version of RNNTL, including submodule - replace references to previous RNNTL with new PySpeech RNNTL Reviewed By: vincentqb Differential Revision: D27973417 fbshipit-source-id: 992eab9f82edc7fdec18851c7a393c9bb3169f30 --- .gitmodules | 4 - test/torchaudio_unittest/transducer_test.py | 26 ++-- third_party/CMakeLists.txt | 8 -- third_party/transducer/CMakeLists.txt | 3 - torchaudio/csrc/transducer.cpp | 132 -------------------- torchaudio/prototype/transducer.py | 119 ------------------ 6 files changed, 12 insertions(+), 280 deletions(-) delete mode 100755 third_party/transducer/CMakeLists.txt delete mode 100644 torchaudio/csrc/transducer.cpp delete mode 100644 torchaudio/prototype/transducer.py diff --git a/.gitmodules b/.gitmodules index dd47fc1e91..724846120c 100644 --- a/.gitmodules +++ b/.gitmodules @@ -1,7 +1,3 @@ -[submodule "third_party/warp_transducer/submodule"] - path = third_party/transducer/submodule - url = https://github.com/HawkAaron/warp-transducer - ignore = dirty [submodule "kaldi"] path = third_party/kaldi/submodule url = https://github.com/kaldi-asr/kaldi diff --git a/test/torchaudio_unittest/transducer_test.py b/test/torchaudio_unittest/transducer_test.py index 209794a5b5..305da970ed 100644 --- a/test/torchaudio_unittest/transducer_test.py +++ b/test/torchaudio_unittest/transducer_test.py @@ -1,6 +1,6 @@ import unittest import torch -from torchaudio.prototype.transducer import RNNTLoss +from torchaudio.facebook.transducer import TransducerLoss from torchaudio_unittest.common_utils import TorchaudioTestCase @@ -228,11 +228,11 @@ def grad_hook(grad): def compute_with_pytorch_transducer(data): - costs = RNNTLoss(blank=data["blank"], reduction="none")( - acts=data["logits"], - labels=data["targets"], - act_lens=data["src_lengths"], - label_lens=data["tgt_lengths"], + costs = TransducerLoss(blank=data["blank"])( + logits=data["logits"], + targets=data["targets"], + src_lengths=data["src_lengths"], + tgt_lengths=data["tgt_lengths"], ) loss = torch.sum(costs) @@ -244,24 +244,22 @@ def compute_with_pytorch_transducer(data): def skipIfNoTransducer(test_item): try: - torch.ops.torchaudio.rnnt_loss + torch.ops.torchaudio.compute return test_item except RuntimeError: return unittest.skip("torchaudio C++ extension is not compiled with RNN transducer loss")(test_item) class TransducerTester: - def test_basic_fp16_error(self): - rnnt_loss = RNNTLoss() + def test_basic_fp16_no_error(self): + # Test that fp16 is supported + rnnt_loss = TransducerLoss() acts, labels, act_length, label_length = get_data_basic(self.device) acts = acts.to(torch.float16) - # RuntimeError raised by log_softmax before reaching transducer's bindings - self.assertRaises( - RuntimeError, rnnt_loss, acts, labels, act_length, label_length - ) + rnnt_loss(acts, labels, act_length, label_length) def test_basic_backward(self): - rnnt_loss = RNNTLoss() + rnnt_loss = TransducerLoss() acts, labels, act_length, label_length = get_data_basic(self.device) loss = rnnt_loss(acts, labels, act_length, label_length) loss.backward() diff --git a/third_party/CMakeLists.txt b/third_party/CMakeLists.txt index bb3a469055..ef984d57b6 100644 --- a/third_party/CMakeLists.txt +++ b/third_party/CMakeLists.txt @@ -21,12 +21,4 @@ if (BUILD_KALDI) list(APPEND TORCHAUDIO_THIRD_PARTIES kaldi) endif() -################################################################################ -# transducer -################################################################################ -if (BUILD_TRANSDUCER) - add_subdirectory(transducer) - list(APPEND TORCHAUDIO_THIRD_PARTIES warprnnt) -endif() - set_property(GLOBAL PROPERTY TORCHAUDIO_THIRD_PARTIES "${TORCHAUDIO_THIRD_PARTIES}") diff --git a/third_party/transducer/CMakeLists.txt b/third_party/transducer/CMakeLists.txt deleted file mode 100755 index 359af3e3e3..0000000000 --- a/third_party/transducer/CMakeLists.txt +++ /dev/null @@ -1,3 +0,0 @@ -add_library(warprnnt STATIC submodule/src/rnnt_entrypoint.cpp) -target_compile_definitions(warprnnt PRIVATE RNNT_DISABLE_OMP) -target_include_directories(warprnnt PUBLIC submodule/include) diff --git a/torchaudio/csrc/transducer.cpp b/torchaudio/csrc/transducer.cpp deleted file mode 100644 index 00fa49b4b5..0000000000 --- a/torchaudio/csrc/transducer.cpp +++ /dev/null @@ -1,132 +0,0 @@ -#include -#include -#include -#include - -#include -#include "rnnt.h" - -namespace { - -int64_t cpu_rnnt_loss( - torch::Tensor acts, - torch::Tensor labels, - torch::Tensor input_lengths, - torch::Tensor label_lengths, - torch::Tensor costs, - torch::Tensor grads, - int64_t blank_label, - int64_t num_threads) { - TORCH_CHECK(labels.dtype() == torch::kInt32, "labels must be int32 type"); - TORCH_CHECK( - label_lengths.dtype() == torch::kInt32, - "label_lengths must be int32 type"); - TORCH_CHECK( - input_lengths.dtype() == torch::kInt32, "lengths must be int32 type"); - TORCH_CHECK(acts.is_contiguous(), "acts must be contiguous"); - TORCH_CHECK(labels.is_contiguous(), "labels must be contiguous"); - TORCH_CHECK( - label_lengths.is_contiguous(), "label_lengths must be contiguous"); - TORCH_CHECK(input_lengths.is_contiguous(), "lengths must be contiguous"); - TORCH_CHECK( - input_lengths.size(0) == acts.size(0), - "batch dimension mismatch between acts and input_lengths: each example must have a length"); - TORCH_CHECK( - label_lengths.size(0) == acts.size(0), - "batch dimension mismatch between acts and label_lengths: each example must have a label length"); - TORCH_CHECK(acts.dim() == 4, "acts must be 4-D (batch, time, label, class)"); - TORCH_CHECK( - labels.dim() == 2, "labels must be 2-D (batch, max label length)"); - TORCH_CHECK(input_lengths.dim() == 1, "input_lengths must be 1-D"); - TORCH_CHECK(label_lengths.dim() == 1, "label_lengths must be 1-D"); - - int maxT = acts.size(1); - int maxU = acts.size(2); - int minibatch_size = acts.size(0); - int alphabet_size = acts.size(3); - - TORCH_CHECK( - at::max(input_lengths).item().toInt() == maxT, "input length mismatch"); - TORCH_CHECK( - at::max(label_lengths).item().toInt() + 1 == maxU, - "output length mismatch"); - - rnntOptions options; - memset(&options, 0, sizeof(options)); - options.maxT = maxT; - options.maxU = maxU; - options.blank_label = blank_label; - options.batch_first = true; - options.loc = RNNT_CPU; - options.num_threads = num_threads; - - // have to use at least one - options.num_threads = std::max(options.num_threads, (unsigned int)1); - - size_t cpu_size_bytes = 0; - switch (acts.scalar_type()) { - case torch::ScalarType::Float: { - get_workspace_size(maxT, maxU, minibatch_size, false, &cpu_size_bytes); - - std::vector cpu_workspace(cpu_size_bytes / sizeof(float), 0); - - compute_rnnt_loss( - acts.data_ptr(), - grads.data_ptr(), - labels.data_ptr(), - label_lengths.data_ptr(), - input_lengths.data_ptr(), - alphabet_size, - minibatch_size, - costs.data_ptr(), - cpu_workspace.data(), - options); - - return 0; - } - case torch::ScalarType::Double: { - get_workspace_size( - maxT, maxU, minibatch_size, false, &cpu_size_bytes, sizeof(double)); - - std::vector cpu_workspace(cpu_size_bytes / sizeof(double), 0); - - compute_rnnt_loss_fp64( - acts.data_ptr(), - grads.data_ptr(), - labels.data_ptr(), - label_lengths.data_ptr(), - input_lengths.data_ptr(), - alphabet_size, - minibatch_size, - costs.data_ptr(), - cpu_workspace.data(), - options); - - return 0; - } - default: - TORCH_CHECK( - false, - std::string(__func__) + " not implemented for '" + - toString(acts.scalar_type()) + "'"); - } - return -1; -} - -} // namespace - -TORCH_LIBRARY_IMPL(torchaudio, CPU, m) { - m.impl("rnnt_loss", &cpu_rnnt_loss); -} - -TORCH_LIBRARY_FRAGMENT(torchaudio, m) { - m.def( - "rnnt_loss(Tensor acts," - "Tensor labels," - "Tensor input_lengths," - "Tensor label_lengths," - "Tensor costs," - "Tensor grads," - "int blank_label," - "int num_threads) -> int"); -} diff --git a/torchaudio/prototype/transducer.py b/torchaudio/prototype/transducer.py deleted file mode 100644 index 99c1e9877e..0000000000 --- a/torchaudio/prototype/transducer.py +++ /dev/null @@ -1,119 +0,0 @@ -import torch -from torch.autograd import Function -from torch.nn import Module -from torchaudio._internal import ( - module_utils as _mod_utils, -) - -__all__ = [ - "rnnt_loss", - "RNNTLoss", -] - - -class _RNNT(Function): - @staticmethod - def forward(ctx, acts, labels, act_lens, label_lens, blank, reduction): - """ - See documentation for RNNTLoss. - """ - - device = acts.device - - acts = acts.to("cpu") - labels = labels.to("cpu") - act_lens = act_lens.to("cpu") - label_lens = label_lens.to("cpu") - - loss_func = torch.ops.torchaudio.rnnt_loss - - grads = torch.zeros_like(acts) - minibatch_size = acts.size(0) - costs = torch.zeros(minibatch_size, dtype=acts.dtype) - - loss_func(acts, labels, act_lens, label_lens, costs, grads, blank, 0) - - if reduction in ["sum", "mean"]: - costs = costs.sum().unsqueeze_(-1) - if reduction == "mean": - costs /= minibatch_size - grads /= minibatch_size - - costs = costs.to(device) - ctx.grads = grads.to(device) - - return costs - - @staticmethod - def backward(ctx, grad_output): - grad_output = grad_output.view(-1, 1, 1, 1).to(ctx.grads) - return ctx.grads.mul_(grad_output), None, None, None, None, None - - -@_mod_utils.requires_module("torchaudio._torchaudio") -def rnnt_loss(acts, labels, act_lens, label_lens, blank=0, reduction="mean"): - """Compute the RNN Transducer Loss. - - The RNN Transducer loss (`Graves 2012 `__) extends the CTC loss by defining - a distribution over output sequences of all lengths, and by jointly modelling both input-output and output-output - dependencies. - - The implementation uses `warp-transducer `__. - - Args: - acts (Tensor): Tensor of dimension (batch, time, label, class) containing output from network - before applying ``torch.nn.functional.log_softmax``. - labels (Tensor): Tensor of dimension (batch, max label length) containing the labels padded by zero - act_lens (Tensor): Tensor of dimension (batch) containing the length of each output sequence - label_lens (Tensor): Tensor of dimension (batch) containing the length of each output sequence - blank (int): blank label. (Default: ``0``) - reduction (string): If ``'sum'``, the output losses will be summed. - If ``'mean'``, the output losses will be divided by the target lengths and - then the mean over the batch is taken. If ``'none'``, no reduction will be applied. - (Default: ``'mean'``) - """ - - # NOTE manually done log_softmax for CPU version, - # log_softmax is computed within GPU version. - acts = torch.nn.functional.log_softmax(acts, -1) - return _RNNT.apply(acts, labels, act_lens, label_lens, blank, reduction) - - -@_mod_utils.requires_module("torchaudio._torchaudio") -class RNNTLoss(Module): - """Compute the RNN Transducer Loss. - - The RNN Transducer loss (`Graves 2012 `__) extends the CTC loss by defining - a distribution over output sequences of all lengths, and by jointly modelling both input-output and output-output - dependencies. - - The implementation uses `warp-transducer `__. - - Args: - blank (int): blank label. (Default: ``0``) - reduction (string): If ``'sum'``, the output losses will be summed. - If ``'mean'``, the output losses will be divided by the target lengths and - then the mean over the batch is taken. If ``'none'``, no reduction will be applied. - (Default: ``'mean'``) - """ - - def __init__(self, blank=0, reduction="mean"): - super(RNNTLoss, self).__init__() - self.blank = blank - self.reduction = reduction - self.loss = _RNNT.apply - - def forward(self, acts, labels, act_lens, label_lens): - """ - Args: - acts (Tensor): Tensor of dimension (batch, time, label, class) containing output from network - before applying ``torch.nn.functional.log_softmax``. - labels (Tensor): Tensor of dimension (batch, max label length) containing the labels padded by zero - act_lens (Tensor): Tensor of dimension (batch) containing the length of each output sequence - label_lens (Tensor): Tensor of dimension (batch) containing the length of each output sequence - """ - - # NOTE manually done log_softmax for CPU version, - # log_softmax is computed within GPU version. - acts = torch.nn.functional.log_softmax(acts, -1) - return self.loss(acts, labels, act_lens, label_lens, self.blank, self.reduction) From 97f354e0e2c4977d5ed3521dc9535719fb208ad1 Mon Sep 17 00:00:00 2001 From: Caroline Chen Date: Fri, 30 Apr 2021 12:53:14 -0700 Subject: [PATCH 42/73] Combine old and new RNNTL tests Summary: - remove unused code from `numpy_transducer` - merge prototype transducer loss tests into internal transducer loss tests Reviewed By: vincentqb Differential Revision: D27973416 fbshipit-source-id: cc8f3b566c48dd584cd0400dceb406f3c84471ac --- test/torchaudio_unittest/transducer_test.py | 283 -------------------- 1 file changed, 283 deletions(-) delete mode 100644 test/torchaudio_unittest/transducer_test.py diff --git a/test/torchaudio_unittest/transducer_test.py b/test/torchaudio_unittest/transducer_test.py deleted file mode 100644 index 305da970ed..0000000000 --- a/test/torchaudio_unittest/transducer_test.py +++ /dev/null @@ -1,283 +0,0 @@ -import unittest -import torch -from torchaudio.facebook.transducer import TransducerLoss - -from torchaudio_unittest.common_utils import TorchaudioTestCase - - -def get_data_basic(device): - # Example provided - # in 6f73a2513dc784c59eec153a45f40bc528355b18 - # of https://github.com/HawkAaron/warp-transducer - - acts = torch.tensor( - [ - [ - [ - [0.1, 0.6, 0.1, 0.1, 0.1], - [0.1, 0.1, 0.6, 0.1, 0.1], - [0.1, 0.1, 0.2, 0.8, 0.1], - ], - [ - [0.1, 0.6, 0.1, 0.1, 0.1], - [0.1, 0.1, 0.2, 0.1, 0.1], - [0.7, 0.1, 0.2, 0.1, 0.1], - ], - ] - ], - dtype=torch.float, - ) - labels = torch.tensor([[1, 2]], dtype=torch.int) - act_length = torch.tensor([2], dtype=torch.int) - label_length = torch.tensor([2], dtype=torch.int) - - acts = acts.to(device) - labels = labels.to(device) - act_length = act_length.to(device) - label_length = label_length.to(device) - - acts.requires_grad_(True) - - return acts, labels, act_length, label_length - - -def get_data_B2_T4_U3_D3(dtype=torch.float32, device="cpu"): - # Test from D21322854 - - logits = torch.tensor( - [ - 0.065357, - 0.787530, - 0.081592, - 0.529716, - 0.750675, - 0.754135, - 0.609764, - 0.868140, - 0.622532, - 0.668522, - 0.858039, - 0.164539, - 0.989780, - 0.944298, - 0.603168, - 0.946783, - 0.666203, - 0.286882, - 0.094184, - 0.366674, - 0.736168, - 0.166680, - 0.714154, - 0.399400, - 0.535982, - 0.291821, - 0.612642, - 0.324241, - 0.800764, - 0.524106, - 0.779195, - 0.183314, - 0.113745, - 0.240222, - 0.339470, - 0.134160, - 0.505562, - 0.051597, - 0.640290, - 0.430733, - 0.829473, - 0.177467, - 0.320700, - 0.042883, - 0.302803, - 0.675178, - 0.569537, - 0.558474, - 0.083132, - 0.060165, - 0.107958, - 0.748615, - 0.943918, - 0.486356, - 0.418199, - 0.652408, - 0.024243, - 0.134582, - 0.366342, - 0.295830, - 0.923670, - 0.689929, - 0.741898, - 0.250005, - 0.603430, - 0.987289, - 0.592606, - 0.884672, - 0.543450, - 0.660770, - 0.377128, - 0.358021, - ], - dtype=dtype, - ).reshape(2, 4, 3, 3) - - targets = torch.tensor([[1, 2], [1, 1]], dtype=torch.int32) - src_lengths = torch.tensor([4, 4], dtype=torch.int32) - tgt_lengths = torch.tensor([2, 2], dtype=torch.int32) - - blank = 0 - - ref_costs = torch.tensor([4.2806528590890736, 3.9384369822503591], dtype=dtype) - - ref_gradients = torch.tensor( - [ - -0.186844, - -0.062555, - 0.249399, - -0.203377, - 0.202399, - 0.000977, - -0.141016, - 0.079123, - 0.061893, - -0.011552, - -0.081280, - 0.092832, - -0.154257, - 0.229433, - -0.075176, - -0.246593, - 0.146405, - 0.100188, - -0.012918, - -0.061593, - 0.074512, - -0.055986, - 0.219831, - -0.163845, - -0.497627, - 0.209240, - 0.288387, - 0.013605, - -0.030220, - 0.016615, - 0.113925, - 0.062781, - -0.176706, - -0.667078, - 0.367659, - 0.299419, - -0.356344, - -0.055347, - 0.411691, - -0.096922, - 0.029459, - 0.067463, - -0.063518, - 0.027654, - 0.035863, - -0.154499, - -0.073942, - 0.228441, - -0.166790, - -0.000088, - 0.166878, - -0.172370, - 0.105565, - 0.066804, - 0.023875, - -0.118256, - 0.094381, - -0.104707, - -0.108934, - 0.213642, - -0.369844, - 0.180118, - 0.189726, - 0.025714, - -0.079462, - 0.053748, - 0.122328, - -0.238789, - 0.116460, - -0.598687, - 0.302203, - 0.296484, - ], - dtype=dtype, - ).reshape(2, 4, 3, 3) - - logits.requires_grad_(True) - logits = logits.to(device) - - def grad_hook(grad): - logits.saved_grad = grad.clone() - - logits.register_hook(grad_hook) - - data = { - "logits": logits, - "targets": targets, - "src_lengths": src_lengths, - "tgt_lengths": tgt_lengths, - "blank": blank, - } - - return data, ref_costs, ref_gradients - - -def compute_with_pytorch_transducer(data): - costs = TransducerLoss(blank=data["blank"])( - logits=data["logits"], - targets=data["targets"], - src_lengths=data["src_lengths"], - tgt_lengths=data["tgt_lengths"], - ) - - loss = torch.sum(costs) - loss.backward() - costs = costs.cpu() - gradients = data["logits"].saved_grad.cpu() - return costs, gradients - - -def skipIfNoTransducer(test_item): - try: - torch.ops.torchaudio.compute - return test_item - except RuntimeError: - return unittest.skip("torchaudio C++ extension is not compiled with RNN transducer loss")(test_item) - - -class TransducerTester: - def test_basic_fp16_no_error(self): - # Test that fp16 is supported - rnnt_loss = TransducerLoss() - acts, labels, act_length, label_length = get_data_basic(self.device) - acts = acts.to(torch.float16) - rnnt_loss(acts, labels, act_length, label_length) - - def test_basic_backward(self): - rnnt_loss = TransducerLoss() - acts, labels, act_length, label_length = get_data_basic(self.device) - loss = rnnt_loss(acts, labels, act_length, label_length) - loss.backward() - - def test_costs_and_gradients_B2_T4_U3_D3_fp32(self): - - data, ref_costs, ref_gradients = get_data_B2_T4_U3_D3( - dtype=torch.float32, device=self.device - ) - logits_shape = data["logits"].shape - costs, gradients = compute_with_pytorch_transducer(data=data) - - atol, rtol = 1e-6, 1e-2 - self.assertEqual(costs, ref_costs, atol=atol, rtol=rtol) - self.assertEqual(logits_shape, gradients.shape) - self.assertEqual(gradients, ref_gradients, atol=atol, rtol=rtol) - - -@skipIfNoTransducer -class CPUTransducerTester(TransducerTester, TorchaudioTestCase): - device = "cpu" From e1c06ebdb0adabee34d6570921d8b1a514b305bc Mon Sep 17 00:00:00 2001 From: Caroline Chen Date: Fri, 30 Apr 2021 12:53:14 -0700 Subject: [PATCH 43/73] Move rnnt files externally Summary: move rnnt files out of internal-only folders - `csrc/facebook/transducer` --> `csrc/rnnt` - `torchaudio_unittest/facebook/transducer` --> `torchaudio_unittest/rnnt` - `torchaudio/facebook/transducer` --> `torchaudio/rnnt` Reviewed By: vincentqb Differential Revision: D28072192 fbshipit-source-id: 9d01736d37a3eb7110fb2adc8bda5544d3340e7d --- test/torchaudio_unittest/rnnt/__init__.py | 0 .../rnnt/numpy_transducer.py | 406 +++++++++ .../rnnt/rnnt_loss_cpu_test.py | 9 + .../rnnt/rnnt_loss_cuda_test.py | 16 + .../rnnt/rnnt_loss_impl.py | 535 +++++++++++ test/torchaudio_unittest/rnnt/utils.py | 542 ++++++++++++ torchaudio/csrc/rnnt/compute.cpp | 15 + torchaudio/csrc/rnnt/compute_alphas.cpp | 13 + torchaudio/csrc/rnnt/compute_betas.cpp | 13 + .../csrc/rnnt/cpu/alignment_restrictions.cpp | 98 +++ .../csrc/rnnt/cpu/alignment_restrictions.h | 117 +++ torchaudio/csrc/rnnt/cpu/compute.cpp | 108 +++ torchaudio/csrc/rnnt/cpu/compute_alphas.cpp | 76 ++ torchaudio/csrc/rnnt/cpu/compute_betas.cpp | 81 ++ torchaudio/csrc/rnnt/cpu/cpu_kernels.h | 677 ++++++++++++++ torchaudio/csrc/rnnt/cpu/cpu_transducer.h | 192 ++++ torchaudio/csrc/rnnt/cpu/kernel_utils.h | 117 +++ torchaudio/csrc/rnnt/cpu/kernels.h | 242 +++++ torchaudio/csrc/rnnt/cpu/math.h | 35 + torchaudio/csrc/rnnt/gpu/compute.cu | 242 +++++ torchaudio/csrc/rnnt/gpu/compute_alphas.cu | 168 ++++ torchaudio/csrc/rnnt/gpu/compute_betas.cu | 178 ++++ .../rnnt/gpu/gpu_alignment_restrictions.cuh | 551 ++++++++++++ torchaudio/csrc/rnnt/gpu/gpu_kernel_utils.cuh | 99 +++ torchaudio/csrc/rnnt/gpu/gpu_kernels.cuh | 488 +++++++++++ torchaudio/csrc/rnnt/gpu/gpu_transducer.h | 829 ++++++++++++++++++ torchaudio/csrc/rnnt/gpu/half.cuh | 38 + torchaudio/csrc/rnnt/gpu/kernel_utils.h | 117 +++ torchaudio/csrc/rnnt/gpu/kernels.h | 215 +++++ torchaudio/csrc/rnnt/gpu/math.cuh | 41 + torchaudio/csrc/rnnt/macros.cpp | 21 + torchaudio/csrc/rnnt/macros.h | 47 + torchaudio/csrc/rnnt/options.h | 99 +++ torchaudio/csrc/rnnt/transducer.h | 239 +++++ torchaudio/csrc/rnnt/types.cpp | 41 + torchaudio/csrc/rnnt/types.h | 23 + torchaudio/csrc/rnnt/workspace.cpp | 20 + torchaudio/csrc/rnnt/workspace.h | 210 +++++ torchaudio/prototype/rnnt_loss.py | 520 +++++++++++ 39 files changed, 7478 insertions(+) create mode 100644 test/torchaudio_unittest/rnnt/__init__.py create mode 100644 test/torchaudio_unittest/rnnt/numpy_transducer.py create mode 100644 test/torchaudio_unittest/rnnt/rnnt_loss_cpu_test.py create mode 100644 test/torchaudio_unittest/rnnt/rnnt_loss_cuda_test.py create mode 100644 test/torchaudio_unittest/rnnt/rnnt_loss_impl.py create mode 100644 test/torchaudio_unittest/rnnt/utils.py create mode 100644 torchaudio/csrc/rnnt/compute.cpp create mode 100644 torchaudio/csrc/rnnt/compute_alphas.cpp create mode 100644 torchaudio/csrc/rnnt/compute_betas.cpp create mode 100644 torchaudio/csrc/rnnt/cpu/alignment_restrictions.cpp create mode 100644 torchaudio/csrc/rnnt/cpu/alignment_restrictions.h create mode 100644 torchaudio/csrc/rnnt/cpu/compute.cpp create mode 100644 torchaudio/csrc/rnnt/cpu/compute_alphas.cpp create mode 100644 torchaudio/csrc/rnnt/cpu/compute_betas.cpp create mode 100644 torchaudio/csrc/rnnt/cpu/cpu_kernels.h create mode 100644 torchaudio/csrc/rnnt/cpu/cpu_transducer.h create mode 100644 torchaudio/csrc/rnnt/cpu/kernel_utils.h create mode 100644 torchaudio/csrc/rnnt/cpu/kernels.h create mode 100644 torchaudio/csrc/rnnt/cpu/math.h create mode 100644 torchaudio/csrc/rnnt/gpu/compute.cu create mode 100644 torchaudio/csrc/rnnt/gpu/compute_alphas.cu create mode 100644 torchaudio/csrc/rnnt/gpu/compute_betas.cu create mode 100644 torchaudio/csrc/rnnt/gpu/gpu_alignment_restrictions.cuh create mode 100644 torchaudio/csrc/rnnt/gpu/gpu_kernel_utils.cuh create mode 100644 torchaudio/csrc/rnnt/gpu/gpu_kernels.cuh create mode 100644 torchaudio/csrc/rnnt/gpu/gpu_transducer.h create mode 100644 torchaudio/csrc/rnnt/gpu/half.cuh create mode 100644 torchaudio/csrc/rnnt/gpu/kernel_utils.h create mode 100644 torchaudio/csrc/rnnt/gpu/kernels.h create mode 100644 torchaudio/csrc/rnnt/gpu/math.cuh create mode 100644 torchaudio/csrc/rnnt/macros.cpp create mode 100644 torchaudio/csrc/rnnt/macros.h create mode 100644 torchaudio/csrc/rnnt/options.h create mode 100644 torchaudio/csrc/rnnt/transducer.h create mode 100644 torchaudio/csrc/rnnt/types.cpp create mode 100644 torchaudio/csrc/rnnt/types.h create mode 100644 torchaudio/csrc/rnnt/workspace.cpp create mode 100644 torchaudio/csrc/rnnt/workspace.h create mode 100644 torchaudio/prototype/rnnt_loss.py diff --git a/test/torchaudio_unittest/rnnt/__init__.py b/test/torchaudio_unittest/rnnt/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/test/torchaudio_unittest/rnnt/numpy_transducer.py b/test/torchaudio_unittest/rnnt/numpy_transducer.py new file mode 100644 index 0000000000..7a26013dd7 --- /dev/null +++ b/test/torchaudio_unittest/rnnt/numpy_transducer.py @@ -0,0 +1,406 @@ +import numpy as np +import torch + + +class _NumpyTransducer(torch.autograd.Function): + @staticmethod + def forward( + ctx, + log_probs, + logit_lengths, + target_lengths, + targets, + blank=-1, + wordpiece_ends=None, + left_buffer=0, + right_buffer=0, + ): + device = log_probs.device + log_probs = log_probs.cpu().data.numpy() + logit_lengths = logit_lengths.cpu().data.numpy() + target_lengths = target_lengths.cpu().data.numpy() + targets = targets.cpu().data.numpy() + + gradients, costs, _, _ = __class__.compute( + log_probs=log_probs, + logit_lengths=logit_lengths, + target_lengths=target_lengths, + targets=targets, + blank=blank, + wordpiece_ends=wordpiece_ends, + left_buffer=left_buffer, + right_buffer=right_buffer, + ) + + costs = torch.FloatTensor(costs).to(device=device) + gradients = torch.FloatTensor(gradients).to(device=device) + ctx.grads = torch.autograd.Variable(gradients) + + return costs + + @staticmethod + def backward(ctx, output_gradients): + return ctx.grads, None, None, None, None, None, None, None, None + + @staticmethod + def compute_alpha_one_sequence(log_probs, targets, blank=-1): + max_T, max_U, D = log_probs.shape + alpha = np.zeros((max_T, max_U), dtype=np.float32) + for t in range(1, max_T): + alpha[t, 0] = alpha[t - 1, 0] + log_probs[t - 1, 0, blank] + + for u in range(1, max_U): + alpha[0, u] = alpha[0, u - 1] + log_probs[0, u - 1, targets[u - 1]] + + for t in range(1, max_T): + for u in range(1, max_U): + skip = alpha[t - 1, u] + log_probs[t - 1, u, blank] + emit = alpha[t, u - 1] + log_probs[t, u - 1, targets[u - 1]] + alpha[t, u] = np.logaddexp(skip, emit) + + cost = -(alpha[-1, -1] + log_probs[-1, -1, blank]) + return alpha, cost + + @staticmethod + def compute_alpha_one_sequence_restricted( + log_probs, targets, wordpiece_ends, blank=-1, left_buffer=0, right_buffer=0 + ): + # Note - this is a more generic case + # If we set left_buffer = right_buffer = inf this becomes same as + # `compute_alpha_one_sequence`. However keeping both versions, + # since without the checks, compute_alpha_one_sequence may be tiny + # bit faster than `compute_alpha_one_sequence_restricted` + + max_T, max_U, D = log_probs.shape + check = AlignmentRestrictionCheck( + max_U, max_T, wordpiece_ends, left_buffer, right_buffer + ) + + alpha = np.zeros((max_T, max_U), dtype=np.float32) + alpha.fill(float("-inf")) + alpha[0, 0] = 0.0 + for t in range(1, max_T): + if not check.alpha_blank_transition(t, 0): + break + alpha[t, 0] = log_probs[t - 1, 0, blank] + alpha[t - 1, 0] + + for u in range(1, max_U): + if not check.alpha_emit_transition(0, u): + break + alpha[0, u] = log_probs[0, u - 1, targets[u - 1]] + alpha[0, u - 1] + + for u in range(1, max_U): + start_t, end_t = check.valid_time_ranges(u) + for t in range(start_t, end_t + 1): + skip, emit = float("-inf"), float("-inf") + + if check.alpha_blank_transition(t, u): + skip = alpha[t - 1, u] + log_probs[t - 1, u, blank] + + if check.alpha_emit_transition(t, u): + emit = alpha[t, u - 1] + log_probs[t, u - 1, targets[u - 1]] + + if emit != float("-inf") or skip != float("-inf"): + alpha[t, u] = np.logaddexp(skip, emit) + + cost = -(alpha[-1, -1] + log_probs[-1, -1, blank]) + return alpha, cost + + @staticmethod + def compute_beta_one_sequence(log_probs, targets, blank=-1): + max_T, max_U, D = log_probs.shape + beta = np.zeros((max_T, max_U), dtype=np.float32) + beta[-1, -1] = log_probs[-1, -1, blank] + + for t in reversed(range(max_T - 1)): + beta[t, -1] = beta[t + 1, -1] + log_probs[t, -1, blank] + + for u in reversed(range(max_U - 1)): + beta[-1, u] = beta[-1, u + 1] + log_probs[-1, u, targets[u]] + + for t in reversed(range(max_T - 1)): + for u in reversed(range(max_U - 1)): + skip = beta[t + 1, u] + log_probs[t, u, blank] + emit = beta[t, u + 1] + log_probs[t, u, targets[u]] + beta[t, u] = np.logaddexp(skip, emit) + + cost = -beta[0, 0] + return beta, cost + + @staticmethod + def compute_beta_one_sequence_restricted( + log_probs, targets, wordpiece_ends, blank=-1, left_buffer=0, right_buffer=0 + ): + # Note - this is a more generic case + # If we set left_buffer = right_buffer = inf this becomes same as + # `compute_beta_one_sequence`. However keeping both versions, + # since without the checks, compute_beta_one_sequence may be tiny + # bit faster than `compute_beta_one_sequence_restricted` + max_T, max_U, D = log_probs.shape + + check = AlignmentRestrictionCheck( + max_U, max_T, wordpiece_ends, left_buffer, right_buffer + ) + beta = np.zeros((max_T, max_U), dtype=np.float32) + beta.fill(float("-inf")) + beta[-1, -1] = log_probs[-1, -1, blank] + + for t in reversed(range(max_T - 1)): + if not check.beta_blank_transition(t, max_U - 1): + break + beta[t, -1] = beta[t + 1, -1] + log_probs[t, -1, blank] + + for u in reversed(range(max_U - 1)): + if not check.beta_emit_transition(max_T - 1, u): + break + beta[-1, u] = beta[-1, u + 1] + log_probs[-1, u, targets[u]] + + for u in reversed(range(max_U - 1)): + start_t, end_t = check.valid_time_ranges(u) + for t in reversed(range(start_t, end_t + 1)): + skip, emit = float("-inf"), float("-inf") + + if check.beta_emit_transition(t, u): + emit = beta[t, u + 1] + log_probs[t, u, targets[u]] + + if check.beta_blank_transition(t, u): + skip = beta[t + 1, u] + log_probs[t, u, blank] + + if emit != float("-inf") or skip != float("-inf"): + beta[t, u] = np.logaddexp(skip, emit) + + cost = -beta[0, 0] + return beta, cost + + @staticmethod + def compute_gradients_one_sequence( + log_probs, alpha, beta, targets, blank=-1 + ): + max_T, max_U, D = log_probs.shape + gradients = np.full(log_probs.shape, float("-inf")) + cost = -beta[0, 0] + + gradients[-1, -1, blank] = alpha[-1, -1] + + gradients[:-1, :, blank] = alpha[:-1, :] + beta[1:, :] + + for u, l in enumerate(targets): + gradients[:, u, l] = alpha[:, u] + beta[:, u + 1] + + gradients = -(np.exp(gradients + log_probs + cost)) + return gradients + + @staticmethod + def compute( + log_probs, + logit_lengths, + target_lengths, + targets, + blank=-1, + wordpiece_ends=None, + left_buffer=0, + right_buffer=0, + ): + gradients = np.zeros_like(log_probs) + B_tgt, max_T, max_U, D = log_probs.shape + B_src = logit_lengths.shape[0] + + H = int(B_tgt / B_src) + + alphas = np.zeros((B_tgt, max_T, max_U)) + betas = np.zeros((B_tgt, max_T, max_U)) + betas.fill(float("-inf")) + alphas.fill(float("-inf")) + costs = np.zeros(B_tgt) + for b_tgt in range(B_tgt): + b_src = int(b_tgt / H) + T = int(logit_lengths[b_src]) + # NOTE: see https://arxiv.org/pdf/1211.3711.pdf Section 2.1 + U = int(target_lengths[b_tgt]) + 1 + + seq_log_probs = log_probs[b_tgt, :T, :U, :] + seq_targets = targets[b_tgt, : int(target_lengths[b_tgt])] + if wordpiece_ends is not None: + seq_wordpiece_ends = wordpiece_ends[b_tgt, : int(target_lengths[b_tgt]) + 1] + alpha, alpha_cost = __class__.compute_alpha_one_sequence_restricted( + log_probs=seq_log_probs, + targets=seq_targets, + blank=blank, + wordpiece_ends=seq_wordpiece_ends, + left_buffer=left_buffer, + right_buffer=right_buffer, + ) + else: + alpha, alpha_cost = __class__.compute_alpha_one_sequence( + log_probs=seq_log_probs, targets=seq_targets, blank=blank + ) + + if wordpiece_ends is not None: + seq_wordpiece_ends = wordpiece_ends[b_tgt, : int(target_lengths[b_tgt]) + 1] + beta, beta_cost = __class__.compute_beta_one_sequence_restricted( + log_probs=seq_log_probs, + targets=seq_targets, + blank=blank, + wordpiece_ends=seq_wordpiece_ends, + left_buffer=left_buffer, + right_buffer=right_buffer, + ) + else: + beta, beta_cost = __class__.compute_beta_one_sequence( + log_probs=seq_log_probs, targets=seq_targets, blank=blank + ) + + seq_gradients = __class__.compute_gradients_one_sequence( + log_probs=seq_log_probs, + alpha=alpha, + beta=beta, + targets=seq_targets, + blank=blank, + ) + np.testing.assert_almost_equal(alpha_cost, beta_cost, decimal=2) + gradients[b_tgt, :T, :U, :] = seq_gradients + costs[b_tgt] = beta_cost + alphas[b_tgt, :T, :U] = alpha + betas[b_tgt, :T, :U] = beta + + return gradients, costs, alphas, betas + + +class NumpyTransducerLoss(torch.nn.Module): + def __init__(self, blank=-1): + super().__init__() + self.blank = blank + + def forward( + self, + logits, + logit_lengths, + target_lengths, + targets, + wordpiece_ends=None, + left_buffer=0, + right_buffer=0, + ): + log_probs = torch.nn.functional.log_softmax(logits, dim=-1) + return _NumpyTransducer.apply( + log_probs, + logit_lengths, + target_lengths, + targets, + self.blank, + wordpiece_ends, + left_buffer, + right_buffer, + ) + + +class AlignmentRestrictionCheck(object): + """ + Helper class which returns locations where + blank / emit transitions are valid while + updating alpha / betas for Alignment + Restricted RNN Transducer loss. This class + will help test c++ code, the correctness has been + verified by thorough manual inspections in n268104 + + """ + + def __init__(self, U, T, wordpiece_ends, left_buffer, right_buffer): + self.U = U + self.T = T + # assume word_ends contains the ground truth end + # timestep of every word piece. + # assume 0th wordpiece_ends is and its endtime is 0 + assert wordpiece_ends[0] == 0 + assert len(wordpiece_ends) == U + self.wordpiece_ends = wordpiece_ends + self.left_buffer = left_buffer + self.right_buffer = right_buffer + + def valid_time_ranges(self, u): + # Returns ranges of valid paths which satisfy + # word boundary constraints + # For bos ranges are valid from 0 until end time of + # 1st symbol + right_buffer + start = max(self.wordpiece_ends[u] - self.left_buffer, 0) + if u == self.U - 1: + end = self.T - 1 + else: + end = min(self.wordpiece_ends[u + 1] + self.right_buffer, self.T - 1) + + return start, end + + def alpha_blank_transition(self, t, u): + # Examine if doing blank transition into (t, u) + # is allowed while updating alphas. + if u == 0 and t == 0: + return False + + # For alphas blank transitions are valid from: + # start time when current symbol is emitted + start = max(self.wordpiece_ends[u] - self.left_buffer + 1, 1) + + # For alphas blank transitions are valid until + # last timestep we can emit next symbol + if u == self.U - 1: + # for last symbol, allow blank transitions till end + end = self.T - 1 + else: + end = min(self.wordpiece_ends[u + 1] + self.right_buffer, self.T - 1) + + return start <= t and t <= end + + def alpha_emit_transition(self, t, u): + # Examine if doing emit transition into (t, u) + # is allowed while updating alphas. + if u == 0: + # emit transitions into (t, 0) for alpha are invalid + return False + + # For alphas emit are valid starting from: + # first time when current symbol can be emitted + start = max(self.wordpiece_ends[u] - self.left_buffer, 0) + + # For alphas emit are valid until: + # last timestep when current symbol can be emitted + end = min(self.wordpiece_ends[u] + self.right_buffer, self.T - 1) + + return start <= t and t <= end + + def beta_blank_transition(self, t, u): + # Examine if doing blank transition into (t, u) + # is allowed while updating betas. + + # for beta, blanks transitions are can start + # first timestep when we emit previous symbol + start = max(self.wordpiece_ends[u] - self.left_buffer, 0) + + # for beta, blanks transitions are valid until + # last timestep we can emit current symbol + # note: T-2, we init beta[-1, -1] by log_prob[-1, -1, blank] + if u == self.U - 1: + end = self.T - 2 + else: + # we cannot transition into beta for T-1 + end = min(self.wordpiece_ends[u + 1] + self.right_buffer - 1, self.T - 2) + + return start <= t and t <= end + + def beta_emit_transition(self, t, u): + # Examine if doing emit transition into (t, u) + # is allowed while updating betas + + # for last symbol, we do not allow emit transition, + # so beta into u-1, t is invalid + if u == self.U - 1: + return False + + # For betas we allow emit transition starting from + # first time we can emit next symbol + start = max(0, self.wordpiece_ends[u + 1] - self.left_buffer) + + # For betas we allow emit transitions to end with + # last time we can emit next symbol + end = min(self.wordpiece_ends[u + 1] + self.right_buffer, self.T - 1) + + return start <= t and t <= end diff --git a/test/torchaudio_unittest/rnnt/rnnt_loss_cpu_test.py b/test/torchaudio_unittest/rnnt/rnnt_loss_cpu_test.py new file mode 100644 index 0000000000..938ed7b210 --- /dev/null +++ b/test/torchaudio_unittest/rnnt/rnnt_loss_cpu_test.py @@ -0,0 +1,9 @@ +import torch +from torchaudio_unittest import common_utils +from .utils import skipIfNoTransducer +from .rnnt_loss_impl import RNNTLossTest + + +@skipIfNoTransducer +class TestRNNTLoss(RNNTLossTest, common_utils.PytorchTestCase): + device = torch.device('cpu') diff --git a/test/torchaudio_unittest/rnnt/rnnt_loss_cuda_test.py b/test/torchaudio_unittest/rnnt/rnnt_loss_cuda_test.py new file mode 100644 index 0000000000..ea6e8eb513 --- /dev/null +++ b/test/torchaudio_unittest/rnnt/rnnt_loss_cuda_test.py @@ -0,0 +1,16 @@ +import torch +from .rnnt_loss_impl import RNNTLossTest, RNNTLossCUDAOnly +from torchaudio_unittest import common_utils +from .utils import skipIfNoTransducer + + +@skipIfNoTransducer +@common_utils.skipIfNoCuda +class TestRNNTLoss(RNNTLossTest, common_utils.PytorchTestCase): + device = torch.device('cuda') + + +@skipIfNoTransducer +@common_utils.skipIfNoCuda +class TestRNNTLossCUDAOnly(RNNTLossCUDAOnly, common_utils.PytorchTestCase): + device = torch.device('cuda') diff --git a/test/torchaudio_unittest/rnnt/rnnt_loss_impl.py b/test/torchaudio_unittest/rnnt/rnnt_loss_impl.py new file mode 100644 index 0000000000..6b6e4d1d20 --- /dev/null +++ b/test/torchaudio_unittest/rnnt/rnnt_loss_impl.py @@ -0,0 +1,535 @@ +import numpy as np +import torch +from torchaudio.prototype.rnnt_loss import ( + RNNTLoss, + _rnnt_loss_alphas, + _rnnt_loss_betas, +) + +from .numpy_transducer import _NumpyTransducer + +from .utils import ( + assert_sparse_all_close, + compute_with_numpy_transducer, + compute_with_pytorch_transducer, + get_B1_T10_U3_D4_data, + get_data_basic, + get_numpy_data_B1_T2_U3_D5, + get_numpy_data_B2_T4_U3_D3, + get_numpy_random_data, + numpy_to_torch, +) + +from torchaudio_unittest.common_utils import skipIfNoCuda + + +class RNNTLossTest: + def _test_costs_and_gradients( + self, data, ref_costs, ref_gradients, atol=1e-6, rtol=1e-2 + ): + logits_shape = data["logits"].shape + for reuse_logits_for_grads in [False, True]: + with self.subTest(reuse_logits_for_grads=reuse_logits_for_grads): + costs, gradients = compute_with_pytorch_transducer( + data=data, reuse_logits_for_grads=reuse_logits_for_grads + ) + np.testing.assert_allclose(costs, ref_costs, atol=atol, rtol=rtol) + if "logits_sparse" in data: + assert_sparse_all_close( + data, gradients, ref_gradients, atol=atol, rtol=rtol + ) + else: + self.assertEqual(logits_shape, gradients.shape) + if not np.allclose(gradients, ref_gradients, atol=atol, rtol=rtol): + for b in range(len(gradients)): + T = data["logit_lengths"][b] + U = data["target_lengths"][b] + for t in range(gradients.shape[1]): + for u in range(gradients.shape[2]): + np.testing.assert_allclose( + gradients[b, t, u], + ref_gradients[b, t, u], + atol=atol, + rtol=rtol, + err_msg=f"failed on b={b}, t={t}/T={T}, u={u}/U={U}", + ) + + def test_basic_backward(self): + rnnt_loss = RNNTLoss() + logits, targets, logit_lengths, target_lengths = get_data_basic(self.device) + loss = rnnt_loss(logits, targets, logit_lengths, target_lengths) + loss.backward() + + def test_costs_and_gradients_B1_T2_U3_D5_fp32(self): + data, ref_costs, ref_gradients = get_numpy_data_B1_T2_U3_D5( + dtype=np.float32 + ) + data = numpy_to_torch(data=data, device=self.device, requires_grad=True) + self._test_costs_and_gradients( + data=data, ref_costs=ref_costs, ref_gradients=ref_gradients + ) + + def test_costs_and_gradients_B1_T2_U3_D5_fp16(self): + data, ref_costs, ref_gradients = get_numpy_data_B1_T2_U3_D5( + dtype=np.float16 + ) + data = numpy_to_torch(data=data, device=self.device, requires_grad=True) + self._test_costs_and_gradients( + data=data, + ref_costs=ref_costs, + ref_gradients=ref_gradients, + atol=1e-3, + rtol=1e-2, + ) + + def test_costs_and_gradients_B2_T4_U3_D3_fp32(self): + data, ref_costs, ref_gradients = get_numpy_data_B2_T4_U3_D3( + dtype=np.float32 + ) + data = numpy_to_torch(data=data, device=self.device, requires_grad=True) + self._test_costs_and_gradients( + data=data, ref_costs=ref_costs, ref_gradients=ref_gradients + ) + + def test_costs_and_gradients_B2_T4_U3_D3_fp16(self): + data, ref_costs, ref_gradients = get_numpy_data_B2_T4_U3_D3( + dtype=np.float16 + ) + data = numpy_to_torch(data=data, device=self.device, requires_grad=True) + self._test_costs_and_gradients( + data=data, + ref_costs=ref_costs, + ref_gradients=ref_gradients, + atol=1e-3, + rtol=1e-2, + ) + + def test_costs_and_gradients_random_data_with_numpy_fp32(self): + seed = 777 + for i in range(5): + data = get_numpy_random_data(dtype=np.float32, seed=(seed + i)) + data = numpy_to_torch(data=data, device=self.device, requires_grad=True) + ref_costs, ref_gradients = compute_with_numpy_transducer(data=data) + self._test_costs_and_gradients( + data=data, ref_costs=ref_costs, ref_gradients=ref_gradients + ) + + def test_alphas_restricted_B1_T10_U3_D4(self): + for random in [True, False]: + for left_buffer in [0, 2, 10]: + for right_buffer in [0, 1, 2, 10]: + data = get_B1_T10_U3_D4_data(random=random) + logits = torch.tensor(data["logits"]) + log_probs = torch.nn.functional.log_softmax(logits, dim=-1).numpy() + ( + np_gradients, + np_costs, + np_alphas, + np_betas, + ) = _NumpyTransducer.compute( + log_probs=log_probs, + logit_lengths=data["logit_lengths"], + target_lengths=data["target_lengths"], + targets=data["targets"], + blank=data["blank"], + wordpiece_ends=data["wordpiece_ends"], + left_buffer=left_buffer, + right_buffer=right_buffer, + ) + + data = numpy_to_torch( + data=data, device=self.device, requires_grad=True + ) + alphas = _rnnt_loss_alphas( + logits=data["logits"], + logit_lengths=data["logit_lengths"], + target_lengths=data["target_lengths"], + targets=data["targets"], + wordpiece_ends=data.get("wordpiece_ends", None), + blank=data["blank"], + left_buffer=left_buffer, + right_buffer=right_buffer, + ) + np.testing.assert_allclose( + alphas.cpu().data.numpy(), np_alphas, atol=1e-6, rtol=1e-2 + ) + + def test_betas_restricted_B1_T10_U3_D4(self): + for random in [True, False]: + for left_buffer in [0, 2, 10]: + for right_buffer in [0, 1, 2, 10]: + data = get_B1_T10_U3_D4_data(random=random) + logits = torch.tensor(data["logits"]) + log_probs = torch.nn.functional.log_softmax(logits, dim=-1).numpy() + ( + np_gradients, + np_costs, + np_alphas, + np_betas, + ) = _NumpyTransducer.compute( + log_probs=log_probs, + logit_lengths=data["logit_lengths"], + target_lengths=data["target_lengths"], + targets=data["targets"], + blank=data["blank"], + wordpiece_ends=data["wordpiece_ends"], + left_buffer=left_buffer, + right_buffer=right_buffer, + ) + + data = numpy_to_torch( + data=data, device=self.device, requires_grad=True + ) + betas = _rnnt_loss_betas( + logits=data["logits"], + logit_lengths=data["logit_lengths"], + target_lengths=data["target_lengths"], + targets=data["targets"], + wordpiece_ends=data.get("wordpiece_ends", None), + blank=data["blank"], + left_buffer=left_buffer, + right_buffer=right_buffer, + ) + np.testing.assert_allclose( + betas.cpu().data.numpy(), np_betas, atol=1e-6, rtol=1e-2 + ) + + def test_rnnt_restricted_B1_T10_U3_D4(self): + for left_buffer in [0, 1, 10]: + for right_buffer in [0, 1, 2, 5, 10]: + data = get_B1_T10_U3_D4_data(random=False) + data = numpy_to_torch( + data=data, device=self.device, requires_grad=True + ) + data["left_buffer"] = left_buffer + data["right_buffer"] = right_buffer + ref_costs, ref_gradients = compute_with_numpy_transducer( + data=data + ) + self._test_costs_and_gradients( + data=data, ref_costs=ref_costs, ref_gradients=ref_gradients + ) + + def test_rnnt_restricted_B2_T4_U3_D3(self): + # Note - this test just ensures that the numpy and c++ implementations match. + # Probably a hand constructed test for gradients will be more thorough + data, _, _ = get_numpy_data_B2_T4_U3_D3(dtype=np.float32) + data = numpy_to_torch(data=data, device=self.device, requires_grad=True) + data["wordpiece_ends"] = torch.tensor([[0, 1, 2], [0, 1, 2]]).int() + + for left_buffer in [0]: + for right_buffer in [0, 1, 2]: + data["left_buffer"] = left_buffer + data["right_buffer"] = right_buffer + ref_costs, ref_gradients = compute_with_numpy_transducer( + data=data + ) + + self._test_costs_and_gradients( + data=data, ref_costs=ref_costs, ref_gradients=ref_gradients + ) + + def test_restricted_parity_with_unrestricted_B1_T10_U3_D4(self): + for random in [False, True]: + data = get_B1_T10_U3_D4_data(random=random) + data = numpy_to_torch(data=data, device=self.device, requires_grad=True) + wordpiece_ends = data["wordpiece_ends"] + del data["wordpiece_ends"] + ref_costs, ref_gradients = compute_with_pytorch_transducer(data=data) + data["wordpiece_ends"] = wordpiece_ends + data["left_buffer"] = 100 + data["right_buffer"] = 100 + wp_costs, wp_gradients = compute_with_pytorch_transducer(data=data) + np.testing.assert_allclose(ref_costs, wp_costs, atol=1e-2, rtol=1e-2) + np.testing.assert_allclose( + ref_gradients, wp_gradients, atol=1e-2, rtol=1e-2 + ) + + def test_restricted_parity_with_unrestricted_alpha_B1_T10_U3_D4(self): + for random in [False, True]: + data = get_B1_T10_U3_D4_data(random=random) + data = numpy_to_torch(data=data, device=self.device, requires_grad=True) + + ref_alphas = _rnnt_loss_alphas( + blank=data["blank"], + logits=data["logits"], + logit_lengths=data["logit_lengths"], + target_lengths=data["target_lengths"], + targets=data["targets"], + ) + + wp_alphas = _rnnt_loss_alphas( + blank=data["blank"], + left_buffer=100, + right_buffer=100, + logits=data["logits"], + logit_lengths=data["logit_lengths"], + target_lengths=data["target_lengths"], + targets=data["targets"], + wordpiece_ends=data["wordpiece_ends"], + ) + np.testing.assert_allclose( + ref_alphas.cpu().data.numpy(), + wp_alphas.cpu().data.numpy(), + atol=1e-2, + rtol=1e-2, + ) + + def test_restricted_parity_with_unrestricted_beta_B1_T10_U3_D4(self): + for random in [False, True]: + data = get_B1_T10_U3_D4_data(random=random) + data = numpy_to_torch(data=data, device=self.device, requires_grad=True) + + ref_betas = _rnnt_loss_betas( + blank=data["blank"], + logits=data["logits"], + logit_lengths=data["logit_lengths"], + target_lengths=data["target_lengths"], + targets=data["targets"], + ) + wp_betas = _rnnt_loss_betas( + blank=data["blank"], + left_buffer=100, + right_buffer=100, + logits=data["logits"], + logit_lengths=data["logit_lengths"], + target_lengths=data["target_lengths"], + targets=data["targets"], + wordpiece_ends=data["wordpiece_ends"], + ) + np.testing.assert_allclose( + ref_betas.cpu().data.numpy(), + wp_betas.cpu().data.numpy(), + atol=1e-2, + rtol=1e-2, + ) + + +@skipIfNoCuda +class RNNTLossCUDAOnly: + def _test_costs_and_gradients( + self, data, ref_costs, ref_gradients, atol=1e-6, rtol=1e-2 + ): + logits_shape = data["logits"].shape + for reuse_logits_for_grads in [False, True]: + with self.subTest(reuse_logits_for_grads=reuse_logits_for_grads): + costs, gradients = compute_with_pytorch_transducer( + data=data, reuse_logits_for_grads=reuse_logits_for_grads + ) + np.testing.assert_allclose(costs, ref_costs, atol=atol, rtol=rtol) + if "logits_sparse" in data: + assert_sparse_all_close( + data, gradients, ref_gradients, atol=atol, rtol=rtol + ) + else: + self.assertEqual(logits_shape, gradients.shape) + if not np.allclose(gradients, ref_gradients, atol=atol, rtol=rtol): + for b in range(len(gradients)): + T = data["logit_lengths"][b] + U = data["target_lengths"][b] + for t in range(gradients.shape[1]): + for u in range(gradients.shape[2]): + np.testing.assert_allclose( + gradients[b, t, u], + ref_gradients[b, t, u], + atol=atol, + rtol=rtol, + err_msg=f"failed on b={b}, t={t}/T={T}, u={u}/U={U}", + ) + + def test_nan_logits(self): + for sparse in [False, True]: + for reuse_logits_for_grads in [False, True]: + data = get_B1_T10_U3_D4_data( + random=True, left_buffer=10, right_buffer=10, sparse=sparse, nan=True + ) + data = numpy_to_torch( + data=data, device=self.device, requires_grad=True + ) + data["left_buffer"] = 10 + data["right_buffer"] = 10 + costs, gradients = compute_with_pytorch_transducer( + data=data, reuse_logits_for_grads=reuse_logits_for_grads + ) + self.assertTrue(np.all(costs == 0)) + self.assertTrue(np.all(gradients == 0)) + + def test_rnnt_restricted_betas_with_random_data(self): + for u in range(50, 60): + data = get_numpy_random_data(max_B=5, max_T=499, max_U=u, max_D=4096) + data = numpy_to_torch( + data=data, device=self.device, requires_grad=True + ) + targets = data["targets"] + target_lengths = data["target_lengths"] + B, max_U = targets.size() + wordpiece_ends = np.zeros((B, max_U + 1), dtype=np.int32) + for b in range(B): + u = target_lengths[b] + wordpiece_ends[b, : u + 1] = np.array([0] + list(range(u)), dtype=np.int32) + wordpiece_ends = torch.from_numpy(wordpiece_ends) + _ = _rnnt_loss_betas( + logits=data["logits"], + logit_lengths=data["logit_lengths"], + target_lengths=data["target_lengths"], + targets=data["targets"], + wordpiece_ends=wordpiece_ends, + blank=4095, + sparse=False, + ) + + def test_rnnt_nonfused_log_softmax(self): + for random in [False, True]: + for sparse in [False, True]: + for left_buffer in [1, 2, 10]: + for right_buffer in [1, 2, 5, 10]: + data = get_B1_T10_U3_D4_data( + random=random, + left_buffer=left_buffer, + right_buffer=right_buffer, + sparse=sparse, + ) + data = numpy_to_torch( + data=data, device=self.device, requires_grad=True + ) + data["left_buffer"] = left_buffer + data["right_buffer"] = right_buffer + data["fused_log_softmax"] = False + ref_costs, ref_gradients = compute_with_numpy_transducer( + data=data + ) + self._test_costs_and_gradients( + data=data, ref_costs=ref_costs, ref_gradients=ref_gradients + ) + + def test_rnnt_sparse_B1_T10_U3_D4(self): + for random in [False, True]: + for left_buffer in [1, 2, 10]: + for right_buffer in [1, 2, 5, 10]: + data = get_B1_T10_U3_D4_data( + random=random, left_buffer=left_buffer, right_buffer=right_buffer, sparse=True + ) + data = numpy_to_torch( + data=data, device=self.device, requires_grad=True + ) + data["left_buffer"] = left_buffer + data["right_buffer"] = right_buffer + ref_costs, ref_gradients = compute_with_numpy_transducer( + data=data + ) + self._test_costs_and_gradients( + data=data, ref_costs=ref_costs, ref_gradients=ref_gradients + ) + + def test_rnnt_sparse_B1_T10_U3_D4_fp16(self): + for random in [False, True]: + for left_buffer in [1, 2, 10]: + for right_buffer in [1, 2, 5, 10]: + data = get_B1_T10_U3_D4_data( + random=random, + left_buffer=left_buffer, + right_buffer=right_buffer, + sparse=True, + dtype=np.float16, + ) + data = numpy_to_torch( + data=data, device=self.device, requires_grad=True + ) + data["left_buffer"] = left_buffer + data["right_buffer"] = right_buffer + ref_costs, ref_gradients = compute_with_numpy_transducer( + data=data + ) + self._test_costs_and_gradients( + data=data, + ref_costs=ref_costs, + ref_gradients=ref_gradients, + atol=1e-3, + rtol=10, + ) + + def test_rnnt_sparse_alpha_beta_B1_T10_U3_D4(self): + for random in [False, True]: + for left_buffer in [1, 2, 10]: + for right_buffer in [1, 2, 10]: + data = get_B1_T10_U3_D4_data( + random=random, left_buffer=left_buffer, right_buffer=right_buffer, sparse=True + ) + data = numpy_to_torch( + data=data, device=self.device, requires_grad=True + ) + data["left_buffer"] = left_buffer + data["right_buffer"] = right_buffer + logits = torch.tensor(data["logits"]) + log_probs = ( + torch.nn.functional.log_softmax(logits, dim=-1).cpu().numpy() + ) + ( + np_gradients, + np_costs, + np_alphas, + np_betas, + ) = _NumpyTransducer.compute( + log_probs=log_probs, + logit_lengths=data["logit_lengths"], + target_lengths=data["target_lengths"], + targets=data["targets"], + blank=data["blank"], + wordpiece_ends=data["wordpiece_ends"], + left_buffer=left_buffer, + right_buffer=right_buffer, + ) + pt_alphas = _rnnt_loss_alphas( + logits=data["logits_sparse"], + logit_lengths=data["logit_lengths"], + target_lengths=data["target_lengths"], + targets=data["targets"], + wordpiece_ends=data["wordpiece_ends"], + blank=data["blank"], + left_buffer=left_buffer, + right_buffer=right_buffer, + sparse=True, + valid_ranges=data["valid_ranges"], + cells_per_sample=data["cells_per_sample"], + ) + total_valid = torch.sum(data["cells_per_sample"]) + sparse_np_alphas = np.zeros((total_valid)).astype(np.float32) + valid_ranges = data["valid_ranges"] + offset = 0 + for b in range(2): + for u in range(3): + st, en = valid_ranges[b][u][0], valid_ranges[b][u][1] + sparse_np_alphas[ + offset : offset + (en - st) + 1 + ] = np_alphas[b, st : en + 1, u] + offset += (en - st) + 1 + np.testing.assert_allclose( + pt_alphas.cpu(), sparse_np_alphas, atol=1e-6, rtol=1e-2 + ) + + pt_betas = _rnnt_loss_betas( + logits=data["logits_sparse"], + logit_lengths=data["logit_lengths"], + target_lengths=data["target_lengths"], + targets=data["targets"], + wordpiece_ends=data["wordpiece_ends"], + blank=data["blank"], + left_buffer=left_buffer, + right_buffer=right_buffer, + sparse=True, + valid_ranges=data["valid_ranges"], + cells_per_sample=data["cells_per_sample"], + ) + sparse_np_betas = np.zeros((total_valid)).astype(np.float32) + valid_ranges = data["valid_ranges"] + offset = 0 + for b in range(2): + for u in range(3): + st, en = valid_ranges[b][u][0], valid_ranges[b][u][1] + sparse_np_betas[offset : offset + (en - st) + 1] = np_betas[ + b, st : en + 1, u + ] + offset += (en - st) + 1 + np.testing.assert_allclose( + pt_betas.cpu(), sparse_np_betas, atol=1e-6, rtol=1e-2 + ) diff --git a/test/torchaudio_unittest/rnnt/utils.py b/test/torchaudio_unittest/rnnt/utils.py new file mode 100644 index 0000000000..5763e72688 --- /dev/null +++ b/test/torchaudio_unittest/rnnt/utils.py @@ -0,0 +1,542 @@ +import unittest + +import numpy as np +import torch +from torchaudio.prototype.rnnt_loss import RNNTLoss + +from .numpy_transducer import ( + AlignmentRestrictionCheck, + NumpyTransducerLoss, +) + + +def _get_sparse(data, dense_tensor, left_buffer, right_buffer, H=1): + B, _, U, D = 2, 10, 3, 4 + total_valid = 0 + valid_ranges = np.zeros((B * H, U, 2), dtype=np.int32) + cells_per_sample = np.zeros(B * H, dtype=np.int32) + wordpiece_ends = data["wordpiece_ends"] + for b_tgt in range(B * H): + b_src = int(b_tgt / H) + src_len = int(data["logit_lengths"][b_src]) + tgt_len = int(data["target_lengths"][b_tgt]) + 1 + ar_check = AlignmentRestrictionCheck( + tgt_len, src_len, wordpiece_ends[b_tgt][:tgt_len], left_buffer, right_buffer + ) + sample_cells = 0 + for u in range(tgt_len): + v_range = ar_check.valid_time_ranges(u) + valid_ranges[b_tgt, u, 0] = v_range[0] + valid_ranges[b_tgt, u, 1] = v_range[1] + total_valid += v_range[1] - v_range[0] + 1 + sample_cells += v_range[1] - v_range[0] + 1 + cells_per_sample[b_tgt] = sample_cells + sparse_joint_enc = np.zeros((total_valid, D)).astype(dense_tensor.dtype) + offset = 0 + for b in range(B * H): + for u in range(U): + st, en = valid_ranges[b_tgt][u][0], valid_ranges[b_tgt][u][1] + sparse_joint_enc[offset : offset + (en - st) + 1, :] = dense_tensor[ + b, st : en + 1, u, : + ] + offset += (en - st) + 1 + return sparse_joint_enc, valid_ranges, cells_per_sample + + +def assert_sparse_all_close(data, gradients, ref_gradients, atol=1e-6, rtol=1e-2): + valid_ranges = data["valid_ranges"] + idx = 0 + for b in range(valid_ranges.size(0)): + for u in range(valid_ranges.size(1)): + st, en = valid_ranges[b, u, 0], valid_ranges[b, u, 1] + np.testing.assert_allclose( + gradients[idx : idx + (en - st + 1), :], + ref_gradients[b, st : en + 1, u, :], + atol=atol, + rtol=rtol, + ) + idx += (en - st) + 1 + + +def compute_with_numpy_transducer(data): + costs = NumpyTransducerLoss( + blank=data["blank"], + )( + logits=data["logits"], + logit_lengths=data["logit_lengths"], + target_lengths=data["target_lengths"], + targets=data["targets"], + wordpiece_ends=data.get("wordpiece_ends", None), + left_buffer=data.get("left_buffer", 0), + right_buffer=data.get("right_buffer", 0), + ) + + loss = torch.sum(costs) + loss.backward() + + costs = costs.cpu().data.numpy() + gradients = data["logits"].saved_grad.cpu().data.numpy() + + return costs, gradients + + +def compute_with_pytorch_transducer(data, reuse_logits_for_grads=False): + left_buffer = data.get("left_buffer", 0) + right_buffer = data.get("right_buffer", 0) + + costs = RNNTLoss( + blank=data["blank"], + left_buffer=left_buffer, + right_buffer=right_buffer, + sparse=True if "logits_sparse" in data else False, + fused_log_softmax=data.get("fused_log_softmax", True), + reuse_logits_for_grads=reuse_logits_for_grads, + )( + logits=data.get("logits_sparse", data["logits"]), + logit_lengths=data["logit_lengths"], + target_lengths=data["target_lengths"], + targets=data["targets"], + wordpiece_ends=data.get("wordpiece_ends", None), + valid_ranges=data.get("valid_ranges", None), + cells_per_sample=data["cells_per_sample"] + if "cells_per_sample" in data + else None, + ) + + loss = torch.sum(costs) + loss.backward() + costs = costs.cpu().data.numpy() + gradients = data["logits"].saved_grad.cpu().data.numpy() + return costs, gradients + + +def get_data_basic(device): + # Example provided + # in 6f73a2513dc784c59eec153a45f40bc528355b18 + # of https://github.com/HawkAaron/warp-transducer + + logits = torch.tensor( + [ + [ + [ + [0.1, 0.6, 0.1, 0.1, 0.1], + [0.1, 0.1, 0.6, 0.1, 0.1], + [0.1, 0.1, 0.2, 0.8, 0.1], + ], + [ + [0.1, 0.6, 0.1, 0.1, 0.1], + [0.1, 0.1, 0.2, 0.1, 0.1], + [0.7, 0.1, 0.2, 0.1, 0.1], + ], + ] + ], + dtype=torch.float, + ) + targets = torch.tensor([[1, 2]], dtype=torch.int) + logit_lengths = torch.tensor([2], dtype=torch.int) + target_lengths = torch.tensor([2], dtype=torch.int) + + logits = logits.to(device=device) + targets = targets.to(device=device) + logit_lengths = logit_lengths.to(device=device) + target_lengths = target_lengths.to(device=device) + + logits.requires_grad_(True) + + return logits, targets, logit_lengths, target_lengths + + +def get_B1_T10_U3_D4_data( + random=False, + left_buffer=0, + right_buffer=0, + sparse=False, + dtype=np.float32, + nan=False, +): + B, T, U, D = 2, 10, 3, 4 + data = {} + data["logits"] = np.random.rand(B, T, U, D).astype(dtype) + if not random: + data["logits"].fill(0.1) + if nan: + for i in range(B): + data["logits"][i][0][0][0] = np.nan + data["logit_lengths"] = np.array([10, 10], dtype=np.int32) + data["target_lengths"] = np.array([2, 2], dtype=np.int32) + data["targets"] = np.array([[1, 2], [1, 2]], dtype=np.int32) + data["blank"] = 0 + data["wordpiece_ends"] = np.array([[0, 2, 7], [0, 2, 7]], dtype=np.int32) + + if sparse: + sparse_joint_enc, valid_ranges, cells_per_sample = _get_sparse( + data, data["logits"], left_buffer, right_buffer + ) + data["logits_sparse"] = sparse_joint_enc + data["valid_ranges"] = valid_ranges + data["cells_per_sample"] = cells_per_sample + return data + + +def get_numpy_data_B1_T2_U3_D5(dtype=np.float32): + logits = np.array( + [ + 0.1, + 0.6, + 0.1, + 0.1, + 0.1, + 0.1, + 0.1, + 0.6, + 0.1, + 0.1, + 0.1, + 0.1, + 0.2, + 0.8, + 0.1, + 0.1, + 0.6, + 0.1, + 0.1, + 0.1, + 0.1, + 0.1, + 0.2, + 0.1, + 0.1, + 0.7, + 0.1, + 0.2, + 0.1, + 0.1, + ], + dtype=dtype, + ).reshape(1, 2, 3, 5) + targets = np.array([[1, 2]], dtype=np.int32) + logit_lengths = np.array([2], dtype=np.int32) + target_lengths = np.array([2], dtype=np.int32) + + blank = -1 + + ref_costs = np.array([5.09566688538], dtype=dtype) + ref_gradients = np.array( + [ + 0.17703132, + -0.39992708, + 0.17703132, + 0.17703132, + -0.13116692, + 0.12247062, + 0.12247062, + -0.181684, + 0.12247062, + -0.1857276, + 0.06269141, + 0.06269141, + 0.06928471, + 0.12624498, + -0.32091248, + 0.05456069, + -0.2182428, + 0.05456069, + 0.05456069, + 0.05456069, + 0.12073967, + 0.12073967, + -0.48295838, + 0.12073967, + 0.12073967, + 0.30741188, + 0.16871123, + 0.18645471, + 0.16871123, + -0.83128875, + ], + dtype=dtype, + ).reshape(1, 2, 3, 5) + + data = { + "logits": logits, + "targets": targets, + "logit_lengths": logit_lengths, + "target_lengths": target_lengths, + "blank": blank, + } + + return data, ref_costs, ref_gradients + + +def get_numpy_data_B2_T4_U3_D3(dtype=np.float32): + # Test from D21322854 + + logits = np.array( + [ + 0.065357, + 0.787530, + 0.081592, + 0.529716, + 0.750675, + 0.754135, + 0.609764, + 0.868140, + 0.622532, + 0.668522, + 0.858039, + 0.164539, + 0.989780, + 0.944298, + 0.603168, + 0.946783, + 0.666203, + 0.286882, + 0.094184, + 0.366674, + 0.736168, + 0.166680, + 0.714154, + 0.399400, + 0.535982, + 0.291821, + 0.612642, + 0.324241, + 0.800764, + 0.524106, + 0.779195, + 0.183314, + 0.113745, + 0.240222, + 0.339470, + 0.134160, + 0.505562, + 0.051597, + 0.640290, + 0.430733, + 0.829473, + 0.177467, + 0.320700, + 0.042883, + 0.302803, + 0.675178, + 0.569537, + 0.558474, + 0.083132, + 0.060165, + 0.107958, + 0.748615, + 0.943918, + 0.486356, + 0.418199, + 0.652408, + 0.024243, + 0.134582, + 0.366342, + 0.295830, + 0.923670, + 0.689929, + 0.741898, + 0.250005, + 0.603430, + 0.987289, + 0.592606, + 0.884672, + 0.543450, + 0.660770, + 0.377128, + 0.358021, + ], + dtype=dtype, + ).reshape(2, 4, 3, 3) + + targets = np.array([[1, 2], [1, 1]], dtype=np.int32) + logit_lengths = np.array([4, 4], dtype=np.int32) + target_lengths = np.array([2, 2], dtype=np.int32) + + blank = 0 + + ref_costs = np.array([4.2806528590890736, 3.9384369822503591], dtype=dtype) + + ref_gradients = np.array( + [ + -0.186844, + -0.062555, + 0.249399, + -0.203377, + 0.202399, + 0.000977, + -0.141016, + 0.079123, + 0.061893, + -0.011552, + -0.081280, + 0.092832, + -0.154257, + 0.229433, + -0.075176, + -0.246593, + 0.146405, + 0.100188, + -0.012918, + -0.061593, + 0.074512, + -0.055986, + 0.219831, + -0.163845, + -0.497627, + 0.209240, + 0.288387, + 0.013605, + -0.030220, + 0.016615, + 0.113925, + 0.062781, + -0.176706, + -0.667078, + 0.367659, + 0.299419, + -0.356344, + -0.055347, + 0.411691, + -0.096922, + 0.029459, + 0.067463, + -0.063518, + 0.027654, + 0.035863, + -0.154499, + -0.073942, + 0.228441, + -0.166790, + -0.000088, + 0.166878, + -0.172370, + 0.105565, + 0.066804, + 0.023875, + -0.118256, + 0.094381, + -0.104707, + -0.108934, + 0.213642, + -0.369844, + 0.180118, + 0.189726, + 0.025714, + -0.079462, + 0.053748, + 0.122328, + -0.238789, + 0.116460, + -0.598687, + 0.302203, + 0.296484, + ], + dtype=dtype, + ).reshape(2, 4, 3, 3) + + data = { + "logits": logits, + "targets": targets, + "logit_lengths": logit_lengths, + "target_lengths": target_lengths, + "blank": blank, + } + + return data, ref_costs, ref_gradients + + +def get_numpy_random_data( + max_B=8, max_T=128, max_U=32, max_D=40, blank=-1, dtype=np.float32, seed=None +): + if seed is not None: + np.random.seed(seed=seed) + + if blank != -1: + raise ValueError("blank != -1 is not supported yet.") + + B = np.random.randint(low=1, high=max_B) + T = np.random.randint(low=5, high=max_T) + U = np.random.randint(low=5, high=max_U) + D = np.random.randint(low=2, high=max_D) + + logit_lengths = np.random.randint(low=5, high=T + 1, size=(B,), dtype=np.int32) + target_lengths = np.random.randint(low=5, high=U + 1, size=(B,), dtype=np.int32) + max_src_length = np.max(logit_lengths) + max_tgt_length = np.max(target_lengths) + targets = np.random.randint( + low=0, high=D - 1, size=(B, max_tgt_length), dtype=np.int32 + ) + logits = np.random.random_sample( + size=(B, max_src_length, max_tgt_length + 1, D) + ).astype(dtype=dtype) + + return { + "logits": logits, + "targets": targets, + "logit_lengths": logit_lengths, + "target_lengths": target_lengths, + "blank": blank, + } + + +def numpy_to_torch(data, device, requires_grad=True): + logits = torch.from_numpy(data["logits"]) + targets = torch.from_numpy(data["targets"]) + logit_lengths = torch.from_numpy(data["logit_lengths"]) + target_lengths = torch.from_numpy(data["target_lengths"]) + + if "wordpiece_ends" in data: + data["wordpiece_ends"] = torch.from_numpy(data["wordpiece_ends"]).to(device=device) + if "nbest_wers" in data: + data["nbest_wers"] = torch.from_numpy(data["nbest_wers"]).to(device=device) + if "nbest_scores" in data: + data["nbest_scores"] = torch.from_numpy(data["nbest_scores"]).to( + device=device + ) + + logits = torch.autograd.Variable(logits, requires_grad=requires_grad) + logit_lengths = torch.autograd.Variable(logit_lengths) + target_lengths = torch.autograd.Variable(target_lengths) + targets = torch.autograd.Variable(targets) + + if device == torch.device("cpu"): + logits = logits.cpu() + elif device == torch.device("cuda"): + logits = logits.cuda() + else: + raise ValueError("unrecognized device = {}".format(device)) + + def grad_hook(grad): + logits.saved_grad = grad.clone() + + logits.register_hook(grad_hook) + + data["logits"] = logits + data["logit_lengths"] = logit_lengths + data["target_lengths"] = target_lengths + data["targets"] = targets + + if "logits_sparse" in data: + logits_sparse = torch.from_numpy(data["logits_sparse"]) + logits_sparse = torch.autograd.Variable( + logits_sparse, requires_grad=requires_grad + ) + logits_sparse = logits_sparse.to(device=logits.device) + logits_sparse.register_hook(grad_hook) + data["logits_sparse"] = logits_sparse + valid_ranges = torch.from_numpy(data["valid_ranges"]) + valid_ranges = valid_ranges.to(device=logits.device) + data["valid_ranges"] = valid_ranges + cells_per_sample = torch.from_numpy(data["cells_per_sample"]) + cells_per_sample = cells_per_sample.to(device=logits.device) + data["cells_per_sample"] = cells_per_sample + return data + + +def skipIfNoTransducer(test_item): + try: + torch.ops.torchaudio.rnnt_loss + return test_item + except RuntimeError: + return unittest.skip("torchaudio C++ extension is not compiled with RNN transducer loss") diff --git a/torchaudio/csrc/rnnt/compute.cpp b/torchaudio/csrc/rnnt/compute.cpp new file mode 100644 index 0000000000..5ca69a24c7 --- /dev/null +++ b/torchaudio/csrc/rnnt/compute.cpp @@ -0,0 +1,15 @@ +#include + +TORCH_LIBRARY_FRAGMENT(torchaudio, m) { + m.def("rnnt_loss(Tensor logits," + "Tensor targets," + "Tensor src_lengths," + "Tensor tgt_lengths," + "int blank," + "float clamp," + "Tensor? wp_ends=None," + "int l_buffer=0," + "int r_buffer=0," + "bool fused_log_smax=True," + "bool reuse_logits_for_grads=True) -> (Tensor, Tensor?)"); +} diff --git a/torchaudio/csrc/rnnt/compute_alphas.cpp b/torchaudio/csrc/rnnt/compute_alphas.cpp new file mode 100644 index 0000000000..80d53995cc --- /dev/null +++ b/torchaudio/csrc/rnnt/compute_alphas.cpp @@ -0,0 +1,13 @@ +#include + +TORCH_LIBRARY_FRAGMENT(torchaudio, m) { + m.def("rnnt_loss_alphas(Tensor logits," + "Tensor targets," + "Tensor src_lengths," + "Tensor tgt_lengths," + "int blank," + "float clamp," + "Tensor? wp_ends=None," + "int l_buffer=0," + "int r_buffer=0) -> Tensor"); +} diff --git a/torchaudio/csrc/rnnt/compute_betas.cpp b/torchaudio/csrc/rnnt/compute_betas.cpp new file mode 100644 index 0000000000..f4312c59cf --- /dev/null +++ b/torchaudio/csrc/rnnt/compute_betas.cpp @@ -0,0 +1,13 @@ +#include + +TORCH_LIBRARY_FRAGMENT(torchaudio, m) { + m.def("rnnt_loss_betas(Tensor logits," + "Tensor targets," + "Tensor src_lengths," + "Tensor tgt_lengths," + "int blank," + "float clamp," + "Tensor? wp_ends=None," + "int l_buffer=0," + "int r_buffer=0) -> Tensor"); +} diff --git a/torchaudio/csrc/rnnt/cpu/alignment_restrictions.cpp b/torchaudio/csrc/rnnt/cpu/alignment_restrictions.cpp new file mode 100644 index 0000000000..abef70409d --- /dev/null +++ b/torchaudio/csrc/rnnt/cpu/alignment_restrictions.cpp @@ -0,0 +1,98 @@ +#include + +namespace torchaudio { +namespace rnnt { +namespace cpu { + +void AlignmentRestrictionCheck::validTimeRanges( + const int u, + int& t_start, + int& t_end) { + t_start = std::max(wpEnds_[u] - lBuffer_, 0); + t_end = (u == U - 1) ? T - 1 : std::min(wpEnds_[u + 1] + rBuffer_, T - 1); + return; +} + +bool AlignmentRestrictionCheck::alphaBlankTransition( + const int t, + const int u) { + if (u == 0 && t == 0) { + return false; + } + + // for alpha blank updates we move from left to right + // blank transitions are valid from: + // start time when current symbol is emitted + // **offset to right by 1** + int start = std::max(wpEnds_[u] - lBuffer_ + 1, 1); + + // blank transitions are valid until: + // for U-1: last allowed timestep i.e. T - 1 + // for other cases: last time we may emit the next symbol + int end = (u == U - 1) ? T - 1 : std::min(wpEnds_[u + 1] + rBuffer_, T - 1); + + return start <= t && t <= end; +} + +bool AlignmentRestrictionCheck::alphaEmitTransition( + const int t, + const int u) { + // For alphas we move from bottom to top + // emit transitions into (t, 0) for alpha are invalid + if (u == 0) { + return false; + } + + // For alphas emit are valid starting from: + // first time when current symbol can be emitted + int start = std::max(wpEnds_[u] - lBuffer_, 0); + + // For alphas emit are valid until: + // last timestep when current symbol can be emitted + int end = std::min(wpEnds_[u] + rBuffer_, T - 1); + + return start <= t && t <= end; +} + +bool AlignmentRestrictionCheck::betaBlankTransition( + const int t, + const int u) { + // For updating betas with blank transition + // we move from right to left + + // for beta, blanks transitions are can start + // first timestep when we emit previous symbol + int start = std::max(wpEnds_[u] - lBuffer_, 0); + + // for beta, blanks transitions are valid until + // we can emit current symbol **offset to left by 1** + // note: T-2, we init beta[-1, -1] by log_prob[-1, -1, blank] + int end = + (u == U - 1) ? T - 2 : std::min(wpEnds_[u + 1] + rBuffer_ - 1, T - 2); + + return start <= t && t <= end; +} + +bool AlignmentRestrictionCheck::betaEmitTransition(const int t, const int u) { + // While updating betas we go from top to bottom. + + // for last symbol, we do not allow emit transition, + // so beta into u-1, t is invalid + if (u == U - 1) { + return false; + } + + // For betas we allow emit transition starting from + // first time we can emit next symbol + int start = std::max(0, wpEnds_[u + 1] - lBuffer_); + + // For betas we allow emit transitions to end with + // last time we can emit next symbol + int end = std::min(wpEnds_[u + 1] + rBuffer_, T - 1); + + return start <= t and t <= end; +} + +} // namespace cpu +} // namespace rnnt +} // namespace torchaudio diff --git a/torchaudio/csrc/rnnt/cpu/alignment_restrictions.h b/torchaudio/csrc/rnnt/cpu/alignment_restrictions.h new file mode 100644 index 0000000000..0ecc6af3bb --- /dev/null +++ b/torchaudio/csrc/rnnt/cpu/alignment_restrictions.h @@ -0,0 +1,117 @@ +#pragma once +#include +#include + +namespace torchaudio { +namespace rnnt { +namespace cpu { + +// Helper class which returns locations where +// blank / emit transitions are valid while +// updating alpha / betas for Alignment +// Restricted Transducer loss +class AlignmentRestrictionCheck { + public: + AlignmentRestrictionCheck( + const int* wpEnds, + int T, + int U, + int lBuffer, + int rBuffer) + : wpEnds_(wpEnds), T(T), U(U), lBuffer_(lBuffer), rBuffer_(rBuffer) { + } + + // Returns ranges of valid timesteps which satisfy + // alignment boundary constraints + void validTimeRanges(const int u, int& t_start, int& t_end); + + // Examine if doing blank transition into (t, u) + // is allowed while updating alphas + // Note that while doing blank transitions for alpha + // we move from left to right + bool alphaBlankTransition(const int t, const int u); + + // Examine if doing emit transition into (t, u) + // is allowed while updating alphas + // Note that while doing emit transitions for alpha + // we move from bottom to top + bool alphaEmitTransition(const int t, const int u); + + // Examine if doing blank transition into (t, u) + // is allowed while updating betas + // Note that while doing blank transitions for beta + // we move from right to left + bool betaBlankTransition(const int t, const int u); + + // Examine if doing emit transition into (t, u) + // is allowed while updating betas + // Note that while doing emit transitions for beta + // we move from top to bottom + bool betaEmitTransition(const int t, const int u); + + private: + const int* wpEnds_; + int T; + int U; + int lBuffer_; + int rBuffer_; +}; + +struct SparseIndexer { + + SparseIndexer( + const int& maxU, + const int* tgtLengths, + const int* validRanges, + const int* cellsPerSample): + maxU_(maxU), + tgtLengths_(tgtLengths), + validRanges_(validRanges), + cellsPerSample_(cellsPerSample) {}; + + int operator() (int bIdx, int tIdx, int uIdx){ + + // increment the idx for valid cells in previous samples + int idx = 0; + for(int b = 0 ; b < bIdx; b++) { + idx += cellsPerSample_[b]; + } + + // increment the index for valid cells in current sample + // using pre-computed valid ranges + const int* validRangesB = validRanges_ + (maxU_*2) * bIdx; + int U = tgtLengths_[bIdx] + 1; + for (int u = 0 ; u < U ; u++) { + int startT = validRangesB[2 * u]; + int endT = validRangesB[2 * u + 1]; + if (u == uIdx) { + if (tIdx < startT || tIdx > endT) { + return -1; + } + idx += (tIdx - startT); + return idx; + } else { + idx += (endT - startT) + 1; + } + } + return -1; + } + + private: + const int& maxU_; + + // (vector of size B) contains the lengths of U for each sample in batch + const int* tgtLengths_; + + // (vector of size B*2*U) contains the valid time ranges (start_t, end_t) + // for each u in every sample, as per alignment restrictions + const int* validRanges_; + + // The total valid timesteps for each sample (sumed over all u in the sample). + // This is a quick loopup so we dont need to iterate on all previous u*b values. + const int* cellsPerSample_; +}; + +} // namespace cpu +} // namespace rnnt +} // namespace torchaudio diff --git a/torchaudio/csrc/rnnt/cpu/compute.cpp b/torchaudio/csrc/rnnt/cpu/compute.cpp new file mode 100644 index 0000000000..c8002c3bff --- /dev/null +++ b/torchaudio/csrc/rnnt/cpu/compute.cpp @@ -0,0 +1,108 @@ +#include +#include + +namespace torchaudio { +namespace rnnt { +namespace cpu { + +// Entry point into RNNT Loss +std::tuple> compute( + torch::Tensor& logits, + const torch::Tensor& targets, + const torch::Tensor& src_lengths, + const torch::Tensor& tgt_lengths, + int64_t blank, + double clamp, + const c10::optional& wp_ends = c10::nullopt, + int64_t l_buffer = 0, + int64_t r_buffer = 0, + bool fused_log_smax = true, + bool reuse_logits_for_grads = true) { + + Options options; + options.batchSize_ = src_lengths.size(0); + options.nHypos_ = tgt_lengths.size(0) / src_lengths.size(0); + options.maxSrcLen_ = logits.size(1); + options.maxTgtLen_ = logits.size(2); + options.numTargets_ = logits.size(3); + options.blank_ = blank; + options.clamp_ = clamp; + options.lBuffer_ = l_buffer; + options.rBuffer_ = r_buffer; + options.fusedLogSmax_ = fused_log_smax; + + CHECK_EQ(logits.device().type(), torch::DeviceType::CPU); + options.device_ = CPU; + + torch::Tensor costs = torch::empty( + options.batchSize_ * options.nHypos_, + torch::TensorOptions().device(logits.device()).dtype(logits.dtype())); + c10::optional gradients = c10::nullopt; + if (logits.requires_grad()) { + if (reuse_logits_for_grads) { + gradients = logits; + } else { + gradients = torch::zeros_like(logits); + } + } + + torch::Tensor int_workspace = torch::empty( + IntWorkspace::ComputeSizeFromOptions(options), + torch::TensorOptions().device(logits.device()).dtype(torch::ScalarType::Int)); + + torch::Tensor float_workspace = torch::empty( + DtypeWorkspace::ComputeSizeFromOptions(options), + torch::TensorOptions().device(logits.device()).dtype(torch::ScalarType::Float)); + + Workspace workspace( + /*options=*/options, + /*dtype_data=*/float_workspace.data(), + /*dtype_size=*/float_workspace.numel(), + /*int_data=*/int_workspace.data(), + /*int_size=*/int_workspace.numel()); + + switch (logits.type().scalarType()) { + case torch::ScalarType::Float: + { + Compute( + /*workspace=*/workspace, + /*logits=*/logits.data(), + /*targets=*/targets.data(), + /*src_lengths=*/src_lengths.data(), + /*tgt_lengths=*/tgt_lengths.data(), + /*costs=*/costs.data(), + /*gradients=*/(gradients == c10::nullopt)? nullptr : gradients->data(), + /*wp_ends=*/(wp_ends == c10::nullopt)? nullptr : wp_ends->data()); + break; + } + case torch::ScalarType::Half: + { + Compute( + /*workspace=*/workspace, + /*logits=*/logits.data(), + /*targets=*/targets.data(), + /*src_lengths=*/src_lengths.data(), + /*tgt_lengths=*/tgt_lengths.data(), + /*costs=*/costs.data(), + /*gradients=*/(gradients == c10::nullopt)? nullptr : gradients->data(), + /*wp_ends=*/(wp_ends == c10::nullopt)? nullptr : wp_ends->data()); + break; + } + default: + { + LOG(ERROR) << "unsupported logits.type().scalarType() = " + << logits.type().scalarType(); + break; + } + }; + + return std::make_tuple(costs, gradients); +} + +TORCH_LIBRARY_IMPL(torchaudio, CPU, m) { + m.impl("rnnt_loss", &compute); +} + +} // namespace cpu +} // namespace rnnt +} // namespace torchaudio diff --git a/torchaudio/csrc/rnnt/cpu/compute_alphas.cpp b/torchaudio/csrc/rnnt/cpu/compute_alphas.cpp new file mode 100644 index 0000000000..7bc462c239 --- /dev/null +++ b/torchaudio/csrc/rnnt/cpu/compute_alphas.cpp @@ -0,0 +1,76 @@ +#include +#include + +namespace torchaudio { +namespace rnnt { +namespace cpu { + +torch::Tensor compute_alphas( + const torch::Tensor& logits, + const torch::Tensor& targets, + const torch::Tensor& src_lengths, + const torch::Tensor& tgt_lengths, + int64_t blank, + double clamp, + const c10::optional& wp_ends = c10::nullopt, + int64_t l_buffer = 0, + int64_t r_buffer = 0) { + Options options; + options.batchSize_ = src_lengths.size(0); + options.nHypos_ = tgt_lengths.size(0) / src_lengths.size(0); + options.maxSrcLen_ = logits.size(1); + options.maxTgtLen_ = logits.size(2); + options.numTargets_ = logits.size(3); + options.blank_ = blank; + options.clamp_ = clamp; + options.lBuffer_ = l_buffer; + options.rBuffer_ = r_buffer; + + CHECK_EQ(logits.device().type(), torch::DeviceType::CPU); + options.device_ = CPU; + + torch::Tensor alphas = torch::zeros( + {options.batchSize_ * options.nHypos_, + options.maxSrcLen_, + options.maxTgtLen_}, + torch::TensorOptions().device(logits.device()).dtype(logits.dtype())); + + torch::Tensor int_workspace = torch::empty( + IntWorkspace::ComputeSizeFromOptions(options), + torch::TensorOptions() + .device(logits.device()) + .dtype(torch::ScalarType::Int)); + + torch::Tensor float_workspace = torch::empty( + DtypeWorkspace::ComputeSizeFromOptions(options), + torch::TensorOptions() + .device(logits.device()) + .dtype(torch::ScalarType::Float)); + + Workspace workspace( + /*options=*/options, + /*dtype_data=*/float_workspace.data(), + /*dtype_size=*/float_workspace.numel(), + /*int_data=*/int_workspace.data(), + /*int_size=*/int_workspace.numel()); + + // Only support float, this is mainly to enable easy + // unit-testing + ComputeAlphas( + /*workspace=*/workspace, + /*logits=*/logits.data(), + /*targets=*/targets.data(), + /*src_lengths=*/src_lengths.data(), + /*tgt_lengths=*/tgt_lengths.data(), + /*alphas=*/alphas.data(), + /*wp_ends=*/(wp_ends == c10::nullopt) ? nullptr : wp_ends->data()); + return alphas; +} + +TORCH_LIBRARY_IMPL(torchaudio, CPU, m) { + m.impl("rnnt_loss_alphas", &compute_alphas); +} + +} // namespace cpu +} // namespace rnnt +} // namespace torchaudio diff --git a/torchaudio/csrc/rnnt/cpu/compute_betas.cpp b/torchaudio/csrc/rnnt/cpu/compute_betas.cpp new file mode 100644 index 0000000000..1c7e3d187a --- /dev/null +++ b/torchaudio/csrc/rnnt/cpu/compute_betas.cpp @@ -0,0 +1,81 @@ +#include +#include + +namespace torchaudio { +namespace rnnt { +namespace cpu { + +torch::Tensor compute_betas( + const torch::Tensor& logits, + const torch::Tensor& targets, + const torch::Tensor& src_lengths, + const torch::Tensor& tgt_lengths, + int64_t blank, + double clamp, + const c10::optional& wp_ends = c10::nullopt, + int64_t l_buffer = 0, + int64_t r_buffer = 0) { + Options options; + options.batchSize_ = src_lengths.size(0); + options.nHypos_ = tgt_lengths.size(0) / src_lengths.size(0); + options.maxSrcLen_ = logits.size(1); + options.maxTgtLen_ = logits.size(2); + options.numTargets_ = logits.size(3); + options.blank_ = blank; + options.clamp_ = clamp; + options.lBuffer_ = l_buffer; + options.rBuffer_ = r_buffer; + + CHECK_EQ(logits.device().type(), torch::DeviceType::CPU); + options.device_ = CPU; + + torch::Tensor costs = torch::empty( + tgt_lengths.size(0), + torch::TensorOptions().device(logits.device()).dtype(logits.dtype())); + + torch::Tensor betas = torch::zeros( + {options.batchSize_ * options.nHypos_, + options.maxSrcLen_, + options.maxTgtLen_}, + torch::TensorOptions().device(logits.device()).dtype(logits.dtype())); + + torch::Tensor int_workspace = torch::empty( + IntWorkspace::ComputeSizeFromOptions(options), + torch::TensorOptions() + .device(logits.device()) + .dtype(torch::ScalarType::Int)); + + torch::Tensor float_workspace = torch::empty( + DtypeWorkspace::ComputeSizeFromOptions(options), + torch::TensorOptions() + .device(logits.device()) + .dtype(torch::ScalarType::Float)); + + Workspace workspace( + /*options=*/options, + /*dtype_data=*/float_workspace.data(), + /*dtype_size=*/float_workspace.numel(), + /*int_data=*/int_workspace.data(), + /*int_size=*/int_workspace.numel()); + + // Only support float, this is mainly to enable easy + // unit-testing + ComputeBetas( + /*workspace=*/workspace, + /*logits=*/logits.data(), + /*targets=*/targets.data(), + /*src_lengths=*/src_lengths.data(), + /*tgt_lengths=*/tgt_lengths.data(), + /*costs=*/costs.data(), + /*betas=*/betas.data(), + /*wp_ends=*/(wp_ends == c10::nullopt) ? nullptr : wp_ends->data()); + return betas; +} + +TORCH_LIBRARY_IMPL(torchaudio, CPU, m) { + m.impl("rnnt_loss_betas", &compute_betas); +} + +} // namespace cpu +} // namespace rnnt +} // namespace torchaudio diff --git a/torchaudio/csrc/rnnt/cpu/cpu_kernels.h b/torchaudio/csrc/rnnt/cpu/cpu_kernels.h new file mode 100644 index 0000000000..6d2084d24d --- /dev/null +++ b/torchaudio/csrc/rnnt/cpu/cpu_kernels.h @@ -0,0 +1,677 @@ +#pragma once + +#include +#include +#include +#include + +#include +#include +#include + +namespace torchaudio { +namespace rnnt { +namespace cpu { + +template +struct LogProbs { + DTYPE skip_; // blank. + DTYPE emit_; // target. + + LogProbs(DTYPE skip, DTYPE emit) : skip_(skip), emit_(emit) {} + + DTYPE& skip() { + return skip_; + } + DTYPE& emit() { + return emit_; + } + + const DTYPE& skip() const { + return skip_; + } + const DTYPE& emit() const { + return emit_; + } +}; + +// TensorView: view a block of allocated memory as a tensor. +template +class TensorView { + public: + TensorView(const std::vector& dims, DTYPE* data) + : dims_(dims), data_(data) { + strides_.resize(dims.size()); + strides_.back() = 1; + for (int i = dims.size() - 2; i >= 0; --i) { + strides_[i] = strides_[i + 1] * dims[i + 1]; + } + } + + DTYPE& operator()(const std::vector& indices) { + CHECK_EQ(indices.size(), dims_.size()); + int index = indices.back(); + for (int i = indices.size() - 2; i >= 0; --i) { + index += indices[i] * strides_[i]; + } + return data_[index]; + } + + void SetZero() { + int size = dims_[0] * strides_[0]; + std::memset(data_, 0, sizeof(DTYPE) * size); + } + + private: + std::vector dims_; + std::vector strides_; + DTYPE* data_; +}; + +template +status_t LogSumExp2D(int N, int D, const DTYPE* logits, CAST_DTYPE* outputs) { + for (int i = 0; i < N * D; i += D) { + CAST_DTYPE max = logits[i]; + for (int j = 1; j < D; ++j) { + max = std::max(max, CAST_DTYPE(logits[i + j])); + } + CAST_DTYPE sum = 0; + for (int j = 0; j < D; ++j) { + sum = sum + std::exp(CAST_DTYPE(logits[i + j]) - max); + } + outputs[i / D] = max + std::log(sum); + } + + return SUCCESS; +} + +template +void ComputeLogProbsOneSequence( + const Options& options, + TensorView& logits, + const int* targets, + int srcLen, + int tgtLen, + TensorView& denom, + TensorView>& logProbs) { + const int& T = srcLen; + const int& U = tgtLen; + const int& blank = options.blank_; + + for (int t = 0; t < T; ++t) { + for (int u = 0; u < U; ++u) { + if (u < U - 1) { + logProbs({t, u}).emit() = + CAST_DTYPE(logits({t, u, targets[u]})) - denom({t, u}); + } + logProbs({t, u}).skip() = + CAST_DTYPE(logits({t, u, blank})) - denom({t, u}); + } + } +} + +template +status_t ComputeLogProbs( + const Options& options, + const DTYPE* logits, + const int* targets, + const int* srcLengths, + const int* tgtLengths, + const CAST_DTYPE* denominators, + CAST_DTYPE* logProbs) { + std::vector> seqLogits; + std::vector seqTargets; + std::vector> seqDenoms; + std::vector>> seqlogProbs; + + const int& B = options.batchSize_; + const int& maxT = options.maxSrcLen_; + const int& maxU = options.maxTgtLen_; + const int& D = options.numTargets_; + for (int b = 0; b < B; ++b) { + seqLogits.push_back( + TensorView({maxT, maxU, D}, logits + b * maxT * maxU * D)); + seqTargets.push_back(targets + b * (maxU - 1)); + seqDenoms.push_back(TensorView( + {maxT, maxU}, denominators + b * maxT * maxU)); + seqlogProbs.push_back(TensorView>( + {maxT, maxU}, + reinterpret_cast*>(logProbs) + b * maxT * maxU)); + } + + //#pragma omp parallel for + for (int b = 0; b < B; ++b) { // use max 2 * B threads. + ComputeLogProbsOneSequence( + /*options=*/options, + /*logits=*/seqLogits[b], + /*targets=*/seqTargets[b], + /*srcLen=*/srcLengths[b], + /*tgtLen=*/tgtLengths[b] + 1, // with prepended blank. + /*denom=*/seqDenoms[b], + /*logProbs=*/seqlogProbs[b]); + } + + return SUCCESS; +} + +template +DTYPE ComputeAlphaOneSequence( + const Options& options, + TensorView>& logProbs, + int srcLen, + int tgtLen, + TensorView& alpha) { + const int& T = srcLen; + const int& U = tgtLen; + + alpha({0, 0}) = DTYPE(0); + + for (int t = 1; t < T; ++t) { // u == 0. + alpha({t, 0}) = alpha({t - 1, 0}) + logProbs({t - 1, 0}).skip(); + } + + for (int u = 1; u < U; ++u) { // t == 0. + alpha({0, u}) = alpha({0, u - 1}) + logProbs({0, u - 1}).emit(); + } + + for (int t = 1; t < T; ++t) { + for (int u = 1; u < U; ++u) { + alpha({t, u}) = math::lse( + alpha({t - 1, u}) + logProbs({t - 1, u}).skip(), + alpha({t, u - 1}) + logProbs({t, u - 1}).emit()); + } + } + + DTYPE forward_score = alpha({T - 1, U - 1}) + logProbs({T - 1, U - 1}).skip(); + + return forward_score; +} + +template +DTYPE ComputeAlphaOneSequenceRestricted( + const Options& options, + TensorView>& logProbs, + int srcLen, + int tgtLen, + TensorView& alpha, + const int* wpEnds) { + const int& T = srcLen; + const int& U = tgtLen; + + const int& lBuffer = options.lBuffer_; + const int& r_buffer = options.rBuffer_; + + AlignmentRestrictionCheck check(wpEnds, T, U, lBuffer, r_buffer); + + for (int t = 0; t < T; t++) { + for (int u = 0; u < U; u++) { + alpha({t, u}) = DTYPE(-INFINITY); + } + } + alpha({0, 0}) = DTYPE(0); + + for (int t = 1; t < T; ++t) { // u == 0. + if (!check.alphaBlankTransition(t, 0)) { + break; + } + alpha({t, 0}) = alpha({t - 1, 0}) + logProbs({t - 1, 0}).skip(); + } + + for (int u = 1; u < U; ++u) { // t == 0. + if (!check.alphaEmitTransition(0, u)) { + break; + } + alpha({0, u}) = alpha({0, u - 1}) + logProbs({0, u - 1}).emit(); + } + + for (int u = 1; u < U; ++u) { + int start_t = 0, end_t = 0; + check.validTimeRanges(u, start_t, end_t); + for (int t = start_t; t < end_t + 1; ++t) { + DTYPE skip = DTYPE(-INFINITY), emit = DTYPE(-INFINITY); + + if (check.alphaBlankTransition(t, u)) { + skip = alpha({t - 1, u}) + logProbs({t - 1, u}).skip(); + } + + if (check.alphaEmitTransition(t, u)) { + emit = alpha({t, u - 1}) + logProbs({t, u - 1}).emit(); + } + + if (skip != DTYPE(-INFINITY) || emit != DTYPE(-INFINITY)) { + alpha({t, u}) = math::lse(skip, emit); + } + } + } + DTYPE forward_score = alpha({T - 1, U - 1}) + logProbs({T - 1, U - 1}).skip(); + + return forward_score; +} + +template +DTYPE ComputeBetaOneSequence( + const Options& options, + TensorView>& logProbs, + int srcLen, + int tgtLen, + TensorView& beta) { + const int& T = srcLen; + const int& U = tgtLen; + + beta({T - 1, U - 1}) = logProbs({T - 1, U - 1}).skip(); + + for (int t = T - 2; t >= 0; --t) { // u == U - 1. + beta({t, U - 1}) = beta({t + 1, U - 1}) + logProbs({t, U - 1}).skip(); + } + + for (int u = U - 2; u >= 0; --u) { // t == T - 1. + beta({T - 1, u}) = beta({T - 1, u + 1}) + logProbs({T - 1, u}).emit(); + } + + for (int t = T - 2; t >= 0; --t) { + for (int u = U - 2; u >= 0; --u) { + beta({t, u}) = math::lse( + beta({t + 1, u}) + logProbs({t, u}).skip(), + beta({t, u + 1}) + logProbs({t, u}).emit()); + } + } + + DTYPE backward_score = beta({0, 0}); + + return backward_score; +} + +template +DTYPE ComputeBetaOneSequenceRestricted( + const Options& options, + TensorView>& logProbs, + int srcLen, + int tgtLen, + TensorView& beta, + const int* wpEnds = nullptr) { + const int& T = srcLen; + const int& U = tgtLen; + const int& lBuffer = options.lBuffer_; + const int& r_buffer = options.rBuffer_; + AlignmentRestrictionCheck check(wpEnds, T, U, lBuffer, r_buffer); + + for (int t = 0; t < T; t++) { + for (int u = 0; u < U; u++) { + beta({t, u}) = DTYPE(-INFINITY); + } + } + + beta({T - 1, U - 1}) = logProbs({T - 1, U - 1}).skip(); + + for (int t = T - 2; t >= 0; --t) { // u == U - 1. + if (!check.betaBlankTransition(t, U - 1)) { + break; + } + beta({t, U - 1}) = beta({t + 1, U - 1}) + logProbs({t, U - 1}).skip(); + } + + for (int u = U - 2; u >= 0; --u) { // t == T - 1. + if (!check.betaEmitTransition(T - 1, u)) { + break; + } + beta({T - 1, u}) = beta({T - 1, u + 1}) + logProbs({T - 1, u}).emit(); + } + for (int u = U - 2; u >= 0; --u) { + int start_t = 0, end_t = 0; + check.validTimeRanges(u, start_t, end_t); + for (int t = end_t; t >= start_t; --t) { + DTYPE skip = DTYPE(-INFINITY), emit = DTYPE(-INFINITY); + if (check.betaBlankTransition(t, u)) { + skip = beta({t + 1, u}) + logProbs({t, u}).skip(); + } + + if (check.betaEmitTransition(t, u)) { + emit = beta({t, u + 1}) + logProbs({t, u}).emit(); + } + + if (skip != DTYPE(-INFINITY) || emit != DTYPE(-INFINITY)) { + beta({t, u}) = math::lse(skip, emit); + } + } + } + DTYPE backward_score = beta({0, 0}); + + return backward_score; +} + +template +DTYPE ComputeAlphaOrBetaOneSequence( + int thread, + const Options& options, + TensorView>& logProbs, + int srcLen, + int tgtLen, + TensorView& alpha, + TensorView& beta, + const int* wpEnds = nullptr) { + if (wpEnds == nullptr) { + if (thread & 1) { + return ComputeAlphaOneSequence( + /*options=*/options, + /*logProbs=*/logProbs, + /*srcLen=*/srcLen, + /*tgtLen=*/tgtLen, + /*alpha=*/alpha); + } else { + return ComputeBetaOneSequence( + /*options=*/options, + /*logProbs=*/logProbs, + /*srcLen=*/srcLen, + /*tgtLen=*/tgtLen, + /*beta=*/beta); + } + } else { + if (thread & 1) { + return ComputeAlphaOneSequenceRestricted( + /*options=*/options, + /*logProbs=*/logProbs, + /*srcLen=*/srcLen, + /*tgtLen=*/tgtLen, + /*alpha=*/alpha, + /*wpEnds=*/wpEnds); + } else { + return ComputeBetaOneSequenceRestricted( + /*options=*/options, + /*logProbs=*/logProbs, + /*srcLen=*/srcLen, + /*tgtLen=*/tgtLen, + /*beta=*/beta, + /*wpEnds=*/wpEnds); + } + } +} + +template +void ComputeAlphasBetas( + const Options& options, + const CAST_DTYPE* logProbs, + const int* srcLengths, + const int* tgtLengths, + CAST_DTYPE* alphas, + CAST_DTYPE* betas, + DTYPE* costs, + const int* wpEnds = nullptr) { + std::vector>> seqlogProbs; + std::vector> seq_alphas; + std::vector> seq_betas; + std::vector seq_wpEnds; + + const int& B = options.batchSize_; + const int& maxT = options.maxSrcLen_; + const int& maxU = options.maxTgtLen_; + + for (int b = 0; b < B; ++b) { + seqlogProbs.push_back(TensorView>( + {maxT, maxU}, + reinterpret_cast*>( + const_cast(logProbs)) + + b * maxT * maxU)); + seq_alphas.push_back( + TensorView({maxT, maxU}, alphas + b * maxT * maxU)); + seq_betas.push_back( + TensorView({maxT, maxU}, betas + b * maxT * maxU)); + + if (wpEnds != nullptr) { + seq_wpEnds.push_back(wpEnds + b * (maxU)); + } + } + + std::vector scores(B << 1); + //#pragma omp parallel for + for (int t = 0; t < (B << 1); ++t) { // use max 2 * B threads. + int i = (t >> 1); + scores[t] = ComputeAlphaOrBetaOneSequence( + /*thread=*/t, + /*options=*/options, + /*logProbs=*/seqlogProbs[i], + /*srcLen=*/srcLengths[i], + /*tgtLen=*/tgtLengths[i] + 1, // with prepended blank. + /*alpha=*/seq_alphas[i], + /*beta=*/seq_betas[i], + /*wpEnds=*/(wpEnds == nullptr) ? nullptr : seq_wpEnds[i]); + } + for (int b = 0; b < B; ++b) { + costs[b] = -scores[b << 1]; + } +} + +template +void ComputeGradientsOneSequence( + const Options& options, + TensorView& logits, + const int* targets, + int srcLen, + int tgtLen, + TensorView& denom, + TensorView& alpha, + TensorView& beta, + TensorView& gradients) { + // don't set gradients to zero to here as gradients might reuse memory from + // logits + + const int& T = srcLen; + const int& U = tgtLen; + const int& D = options.numTargets_; + const int& blank = options.blank_; + const CAST_DTYPE clamp = options.clamp_; + + CAST_DTYPE cost = -beta({0, 0}); + + // Note - below gradient is different from numpy_transducer, since we + // compute log_softmax more efficiently within the loss, to save memory The + // details of the below implementation / equations can be found in Sec 3.2 + // (function merging) in below paper: + // https://www.microsoft.com/en-us/research/uploads/prod/2019/10/RNNT.pdf + + for (int t = 0; t < T; ++t) { + for (int u = 0; u < U; ++u) { + CAST_DTYPE c = alpha({t, u}) + cost - denom({t, u}); + for (int d = 0; d < D; ++d) { + CAST_DTYPE g = CAST_DTYPE(logits({t, u, d})) + c; + if (d == blank && t == T - 1 && + u == U - 1) { // last blank transition. + gradients({t, u, d}) = std::exp(g + beta({t, u})) - std::exp(g); + } else if (d == blank && t < T - 1) { + gradients({t, u, d}) = + std::exp(g + beta({t, u})) - std::exp(g + beta({t + 1, u})); + } else if (u < U - 1 && d == targets[u]) { + gradients({t, u, d}) = + std::exp(g + beta({t, u})) - std::exp(g + beta({t, u + 1})); + } else { + gradients({t, u, d}) = std::exp(g + beta({t, u})); + } + + if (clamp > 0) { + gradients({t, u, d}) = + math::min(CAST_DTYPE(gradients({t, u, d})), clamp); + gradients({t, u, d}) = + math::max(CAST_DTYPE(gradients({t, u, d})), -clamp); + } + } + } + } + + // zero out the rest of the gradients, necessary when reusing logits memory + // check the memory location to see if it's necessary + if (&gradients({0, 0, 0}) == &logits({0, 0, 0})) { + const int& maxT = options.maxSrcLen_; + const int& maxU = options.maxTgtLen_; + for (int t = T; t < maxT; ++t) { + for (int u = 0; u < maxU; ++u) { + for (int d = 0; d < D; ++d) { + gradients({t, u, d}) = 0.; + } + } + } + for (int t = 0; t < T; ++t) { + for (int u = U; u < maxU; ++u) { + for (int d = 0; d < D; ++d) { + gradients({t, u, d}) = 0.; + } + } + } + } +} + +template +void ComputeGradients( + const Options& options, + const DTYPE* logits, + const int* targets, + const int* srcLengths, + const int* tgtLengths, + const CAST_DTYPE* denominators, + const CAST_DTYPE* alphas, + const CAST_DTYPE* betas, + DTYPE* gradients) { + std::vector> seqLogits; + std::vector seqTargets; + std::vector> seqDenoms; + std::vector> seq_alphas; + std::vector> seq_betas; + std::vector> seq_gradients; + + const int& B = options.batchSize_; + const int& maxT = options.maxSrcLen_; + const int& maxU = options.maxTgtLen_; + const int& D = options.numTargets_; + for (int b = 0; b < B; ++b) { + seqLogits.push_back( + TensorView({maxT, maxU, D}, logits + b * maxT * maxU * D)); + seqTargets.push_back(targets + b * (maxU - 1)); + seqDenoms.push_back(TensorView( + {maxT, maxU}, denominators + b * maxT * maxU)); + seq_alphas.push_back( + TensorView({maxT, maxU}, alphas + b * maxT * maxU)); + seq_betas.push_back( + TensorView({maxT, maxU}, betas + b * maxT * maxU)); + seq_gradients.push_back( + TensorView({maxT, maxU, D}, gradients + b * maxT * maxU * D)); + } + + //#pragma omp parallel for + for (int b = 0; b < B; ++b) { // use max 2 * B threads. + ComputeGradientsOneSequence( + /*options=*/options, + /*logits=*/seqLogits[b], + /*targets=*/seqTargets[b], + /*srcLen=*/srcLengths[b], + /*tgtLen=*/tgtLengths[b] + 1, // with prepended blank. + /*denom=*/seqDenoms[b], + /*alpha=*/seq_alphas[b], + /*beta=*/seq_betas[b], + /*gradients=*/seq_gradients[b]); + } +} + +template +void ComputeAlphas( + const Options& options, + const CAST_DTYPE* logProbs, + const int* srcLengths, + const int* tgtLengths, + CAST_DTYPE* alphas, + const int* wpEnds = nullptr) { + std::vector>> seqlogProbs; + std::vector> seq_alphas; + std::vector seq_wpEnds; + + const int& B = options.batchSize_; + const int& maxT = options.maxSrcLen_; + const int& maxU = options.maxTgtLen_; + + for (int b = 0; b < B; ++b) { + seqlogProbs.push_back(TensorView>( + {maxT, maxU}, + reinterpret_cast*>( + const_cast(logProbs)) + + b * maxT * maxU)); + seq_alphas.push_back( + TensorView({maxT, maxU}, alphas + b * maxT * maxU)); + if (wpEnds != nullptr) { + seq_wpEnds.push_back(wpEnds + b * (maxU)); + } + } + + std::vector scores(B << 1); + //#pragma omp parallel for + for (int i = 0; i < B; ++i) { // use max 2 * B threads. + if (wpEnds == nullptr) { + ComputeAlphaOneSequence( + options, + /*logProbs=*/seqlogProbs[i], + /*srcLen=*/srcLengths[i], + /*tgtLen=*/tgtLengths[i] + 1, // with prepended blank. + /*alpha=*/seq_alphas[i]); + } else { + ComputeAlphaOneSequenceRestricted( + /*options=*/options, + /*logProbs=*/seqlogProbs[i], + /*srcLen=*/srcLengths[i], + /*tgtLen=*/tgtLengths[i] + 1, // with prepended blank. + /*alpha=*/seq_alphas[i], + /*wpEnds=*/seq_wpEnds[i]); + } + } +} + +template +void ComputeBetas( + const Options& options, + const CAST_DTYPE* logProbs, + const int* srcLengths, + const int* tgtLengths, + CAST_DTYPE* costs, + CAST_DTYPE* betas, + const int* wpEnds = nullptr) { + std::vector>> seqlogProbs; + std::vector> seq_betas; + std::vector seq_wpEnds; + + const int& B = options.batchSize_; + const int& maxT = options.maxSrcLen_; + const int& maxU = options.maxTgtLen_; + + for (int b = 0; b < B; ++b) { + seqlogProbs.push_back(TensorView>( + {maxT, maxU}, + reinterpret_cast*>( + const_cast(logProbs)) + + b * maxT * maxU)); + seq_betas.push_back( + TensorView({maxT, maxU}, betas + b * maxT * maxU)); + if (wpEnds != nullptr) { + seq_wpEnds.push_back(wpEnds + b * (maxU)); + } + } + + std::vector scores(B << 1); + //#pragma omp parallel for + for (int i = 0; i < B; ++i) { // use max 2 * B threads. + if (wpEnds == nullptr) { + ComputeBetaOneSequence( + options, + /*logProbs=*/seqlogProbs[i], + /*srcLen=*/srcLengths[i], + /*tgtLen=*/tgtLengths[i] + 1, // with prepended blank. + /*betas=*/seq_betas[i]); + } else { + ComputeBetaOneSequenceRestricted( + /*options=*/options, + /*logProbs=*/seqlogProbs[i], + /*srcLen=*/srcLengths[i], + /*tgtLen=*/tgtLengths[i] + 1, // with prepended blank. + /*betas=*/seq_betas[i], + /*wpEnds=*/seq_wpEnds[i]); + } + } +} + +} // namespace cpu +} // namespace rnnt +} // namespace torchaudio diff --git a/torchaudio/csrc/rnnt/cpu/cpu_transducer.h b/torchaudio/csrc/rnnt/cpu/cpu_transducer.h new file mode 100644 index 0000000000..72764325ee --- /dev/null +++ b/torchaudio/csrc/rnnt/cpu/cpu_transducer.h @@ -0,0 +1,192 @@ +#pragma once + +#include +#include + +namespace torchaudio { +namespace rnnt { +namespace cpu { + +// Inputs: +// workspace: workspace. +// logits: pointer to (B, maxT, maxU, D) logits. +// targets: pointer to (B, maxU - 1) targets in the batch. +// srcLengths: pointer to (B, ) source lengths in the batch. +// tgtLengths: pointer to (B, ) target lengths in the batch. +// +// Outputs: +// costs: pointer to (B, ) costs in the batch. +// gradients: pointer to (B, maxT, maxU, D) gradients in the batch. +template +status_t Compute( + const Workspace& workspace, + const DTYPE* logits, + const int* targets, + const int* srcLengths, + const int* tgtLengths, + DTYPE* costs, + DTYPE* gradients = nullptr, + const int* wpEnds = nullptr) { + const Options& options = workspace.GetOptions(); + + CHECK_EQ(options.device_, CPU); + + const int& B = options.batchSize_; + const int& maxT = options.maxSrcLen_; + const int& maxU = options.maxTgtLen_; + const int& D = options.numTargets_; + + { // compute denominators. + status_t status = LogSumExp2D( + /*N=*/B * maxT * maxU, + /*D=*/D, + /*logits=*/logits, + /*denominators=*/workspace.GetPointerToDenominators()); + } + + { // compute log prob pairs. + status_t status = ComputeLogProbs( + /*options=*/options, + /*logits=*/logits, + /*targets=*/targets, + /*srcLengths=*/srcLengths, + /*tgtLengths=*/tgtLengths, + /*denominators=*/workspace.GetPointerToDenominators(), + /*log_probs=*/workspace.GetPointerToLogProbs()); + } + + { // compute alphas and betas. + ComputeAlphasBetas( + /*options=*/options, + /*log_probs=*/workspace.GetPointerToLogProbs(), + /*srcLengths=*/srcLengths, + /*tgtLengths=*/tgtLengths, + /*alphas=*/workspace.GetPointerToAlphas(), + /*betas=*/workspace.GetPointerToBetas(), + /*costs=*/costs, + /*wpEnds=*/wpEnds); + } + + if (gradients != nullptr) { + ComputeGradients( + /*options=*/options, + /*logits=*/logits, + /*targets=*/targets, + /*srcLengths=*/srcLengths, + /*tgtLengths=*/tgtLengths, + /*denominators=*/workspace.GetPointerToDenominators(), + /*alphas=*/workspace.GetPointerToAlphas(), + /*betas=*/workspace.GetPointerToBetas(), + /*gradients=*/gradients); + } + + return SUCCESS; +} + +template +status_t ComputeAlphas( + const Workspace& workspace, + const DTYPE* logits, + const int* targets, + const int* srcLengths, + const int* tgtLengths, + DTYPE* alphas, + const int* wpEnds = nullptr) { + const Options& options = workspace.GetOptions(); + + CHECK_EQ(options.device_, CPU); + + const int& B = options.batchSize_; + const int& maxT = options.maxSrcLen_; + const int& maxU = options.maxTgtLen_; + const int& D = options.numTargets_; + + { // compute denominators. + status_t status = LogSumExp2D( + /*N=*/B * maxT * maxU, + /*D=*/D, + /*logits=*/logits, + /*denominators=*/workspace.GetPointerToDenominators()); + } + + { // compute log prob pairs. + status_t status = ComputeLogProbs( + /*options=*/options, + /*logits=*/logits, + /*targets=*/targets, + /*srcLengths=*/srcLengths, + /*tgtLengths=*/tgtLengths, + /*denominators=*/workspace.GetPointerToDenominators(), + /*log_probs=*/workspace.GetPointerToLogProbs()); + } + + { // compute alphas. + ComputeAlphas( + /*options=*/options, + /*log_probs=*/workspace.GetPointerToLogProbs(), + /*srcLengths=*/srcLengths, + /*tgtLengths=*/tgtLengths, + /*alphas=*/alphas, + /*wpEnds=*/wpEnds); + } + + return SUCCESS; +} + + + +template +status_t ComputeBetas( + const Workspace& workspace, + const DTYPE* logits, + const int* targets, + const int* srcLengths, + const int* tgtLengths, + DTYPE* costs, + DTYPE* betas, + const int* wpEnds = nullptr) { + const Options& options = workspace.GetOptions(); + + CHECK_EQ(options.device_, CPU); + + const int& B = options.batchSize_; + const int& maxT = options.maxSrcLen_; + const int& maxU = options.maxTgtLen_; + const int& D = options.numTargets_; + + { // compute denominators. + status_t status = LogSumExp2D( + /*N=*/B * maxT * maxU, + /*D=*/D, + /*logits=*/logits, + /*denominators=*/workspace.GetPointerToDenominators()); + } + + { // compute log prob pairs. + status_t status = ComputeLogProbs( + /*options=*/options, + /*logits=*/logits, + /*targets=*/targets, + /*srcLengths=*/srcLengths, + /*tgtLengths=*/tgtLengths, + /*denominators=*/workspace.GetPointerToDenominators(), + /*log_probs=*/workspace.GetPointerToLogProbs()); + } + + { // compute betas. + ComputeBetas( + /*options=*/options, + /*log_probs=*/workspace.GetPointerToLogProbs(), + /*srcLengths=*/srcLengths, + /*tgtLengths=*/tgtLengths, + /*costs=*/costs, + /*betas=*/betas, + /*wpEnds=*/wpEnds); + } + + return SUCCESS; +} + +} // namespace cpu +} // namespace rnnt +} // namespace torchaudio diff --git a/torchaudio/csrc/rnnt/cpu/kernel_utils.h b/torchaudio/csrc/rnnt/cpu/kernel_utils.h new file mode 100644 index 0000000000..4ba141503e --- /dev/null +++ b/torchaudio/csrc/rnnt/cpu/kernel_utils.h @@ -0,0 +1,117 @@ +#pragma once + +#include + +#include + +namespace torchaudio { +namespace rnnt { + +inline HOST_AND_DEVICE bool in_range( + int start, + int end, // inclusive + int val) { + return start <= val && val <= end; +} + +#define LOG_PROBS_SKIP_IDX 0 +#define LOG_PROBS_EMIT_IDX 1 + + +struct Indexer2D { + const int& size2_; + + FORCE_INLINE HOST_AND_DEVICE Indexer2D(const int& size2): size2_(size2) {} + + FORCE_INLINE HOST_AND_DEVICE int operator() (int index1, int index2) { + return index1 * size2_ + index2; + } +}; + + +struct Indexer3D { + const int& size2_; + const int& size3_; + + FORCE_INLINE HOST_AND_DEVICE Indexer3D(const int& size2, const int& size3) + : size2_(size2), size3_(size3) {} + + FORCE_INLINE HOST_AND_DEVICE int operator() (int index1, int index2, int index3) { + return (index1 * size2_ + index2) * size3_ + index3; + } +}; + + +struct Indexer4D { + const int& size2_; + const int& size3_; + const int& size4_; + + HOST_AND_DEVICE Indexer4D(const int& size2, const int& size3, const int& size4) + : size2_(size2), size3_(size3), size4_(size4) {} + + HOST_AND_DEVICE int operator() (int index1, int index2, int index3, int index4) { + return ((index1 * size2_ + index2) * size3_ + index3) * size4_ + index4; + } +}; + + +struct SparseIndexer { + HOST_AND_DEVICE SparseIndexer( + const int& maxU, + const int* tgtLengths, + const int* validRanges, + const int* cellsPerSample) : + maxU_(maxU), + tgtLengths_(tgtLengths), + validRanges_(validRanges), + cellsPerSample_(cellsPerSample) {}; + + HOST_AND_DEVICE int operator() (int bIdx, int tIdx, int uIdx) { + // Returns the sparse index given bIdx, tIdx, uIdx; or -1 if t out of band. + + // increment the idx for valid cells in previous samples + // TODO: Inefficient in the inner loop; precompute this? + int idx = 0; + for(int b = 0 ; b < bIdx; b++) { + idx += cellsPerSample_[b]; + } + + // increment the idx for valid cells in current sample + // using pre-computed valid ranges + const int* validRangesB = validRanges_ + (maxU_ * 2) * bIdx; + int U = tgtLengths_[bIdx] + 1; + for (int u = 0 ; u < U ; u++) { + int startT = validRangesB[2*u]; + int endT = validRangesB[2*u + 1]; + if (u == uIdx) { + if (tIdx < startT || tIdx > endT) { + return -1; + } + idx += (tIdx - startT); + return idx; + } else { + idx += (endT - startT) + 1; + } + } + return -1; + } + + private: + const int& maxU_; + + // (vector of size B) contains the lengths of U for each sample in batch + const int* tgtLengths_; + + // (vector of size B*2*U) contains the valid time ranges (start_t, end_t) + // for each u in every sample, as per alignment restrictions + const int* validRanges_; + + // The total valid timesteps for each sample (sumed over all u in the sample). + // This is a quick loopup so we dont need to iterate on all previous u*b values. + const int* cellsPerSample_; + +}; + +} // namespace rnnt +} // namespace torchaudio diff --git a/torchaudio/csrc/rnnt/cpu/kernels.h b/torchaudio/csrc/rnnt/cpu/kernels.h new file mode 100644 index 0000000000..66ffb6657e --- /dev/null +++ b/torchaudio/csrc/rnnt/cpu/kernels.h @@ -0,0 +1,242 @@ +#pragma once + +#include + +#include +#include + +namespace torchaudio { +namespace rnnt { + + +template +FORCE_INLINE HOST_AND_DEVICE void ComputeLogProbsSparseElement( + int bTgt, + int t, + int u, + int maxT, + int maxU, + int numTargets, + int blank, + const DTYPE* logits, + const int* targets, + const int* srcLengths, + const int* tgtLengths, + const CAST_DTYPE* denominators, + CAST_DTYPE* logProbs, + const int* wpEnds, + const int* validRanges=nullptr, + const int* cellsPerSample=nullptr, + int H=1, + bool fusedLogSmax=true) { + + const int& D = numTargets; + + const int bSrc = bTgt / H; + const int T = srcLengths[bSrc]; + const int U = tgtLengths[bTgt] + 1; + + if (t >= T || u >= U) { // out of boundary. + return; + } + const int* validRangesB = validRanges + (maxU*2) * bTgt; + int start = validRangesB[2*u]; + int end = validRangesB[2*u + 1]; + + // out of boundary for alignment restriction condition + if (t < start || t > end) { + return; + } + SparseIndexer idxr(maxU, tgtLengths, validRanges, cellsPerSample); + int idx = idxr(bTgt, t, u); + logProbs[(idx << 1) + LOG_PROBS_SKIP_IDX] = + CAST_DTYPE(logits[idx * D + blank]) - denominators[idx]; + + if (!fusedLogSmax) { + logProbs[(idx << 1) + LOG_PROBS_SKIP_IDX] = + CAST_DTYPE(logits[idx * D + blank]); + } + + if (u < U - 1) { + // emit: log_prob(b, t, u).emit() = logits(b, t, u, tgt[u]) - denom(b, t, u). + int target = targets[Indexer2D(maxU - 1)(bTgt, u)]; + logProbs[(idx << 1) + LOG_PROBS_EMIT_IDX] = + CAST_DTYPE(logits[idx * D + target]) - denominators[idx]; + + if (!fusedLogSmax) { + logProbs[(idx << 1) + LOG_PROBS_EMIT_IDX] = + CAST_DTYPE(logits[idx * D + target]); + } + } +} + + +template +HOST_AND_DEVICE void ComputeGradientsElement( + int bTgt, + int t, + int u, + int maxSrcLen, + int maxTgtLen, + int numTargets, + int blank, + CAST_DTYPE clamp, + const DTYPE* logits, + const int* targets, + const int* srcLengths, + const int* tgtLengths, + const CAST_DTYPE* denominators, + const CAST_DTYPE* alphas, + const CAST_DTYPE* betas, + DTYPE* gradients, + bool monotonic = false, + bool sparse = false, + const int* validRanges = nullptr, + const int* cellsPerSample = nullptr, + int H = 1, + bool fusedLogSmax = true) { + + const int& maxT = maxSrcLen; + const int& maxU = maxTgtLen; + const int& D = numTargets; + + const int bSrc = bTgt / H; + const int T = srcLengths[bSrc]; + const int U = tgtLengths[bTgt] + 1; + + if (t >= T || u >= U) { // out of boundary. + if (sparse) { + // no extra elements needs to be set to 0 + return; + } else if (gradients == logits && t < maxT && u < maxU) { + // gradients and logits are pointing to the same memory location + Indexer3D idxr3(maxT, maxU); + int idx_b_t_u_zero = idxr3(bTgt, t, u); + if (idx_b_t_u_zero != -1 ) { + int start = idx_b_t_u_zero * D; + for (int b_t_u_d = start; b_t_u_d < start + D; ++b_t_u_d) { + gradients[b_t_u_d] = 0; + } + } + } + return; + } + + int costIdx; + if (!sparse) { + costIdx = bTgt * maxT * maxU; + } else { + SparseIndexer idxr(maxU, tgtLengths, validRanges, cellsPerSample); + costIdx = idxr(bTgt, 0, 0); + } + CAST_DTYPE cost = -(betas[costIdx]); + + + Indexer2D idxr2(maxU - 1); + + int idx_b_t_u, idx_b_t_up1, idx_b_tp1_u, idx_b_tp1_up1; + if (sparse) { + SparseIndexer idxr(maxU, tgtLengths, validRanges, cellsPerSample); + idx_b_t_u = idxr(bTgt, t, u); + idx_b_t_up1 = idxr(bTgt, t, u+1); + idx_b_tp1_u = idxr(bTgt, t+1, u); + idx_b_tp1_up1 = idxr(bTgt, t+1, u+1); + } else { + Indexer3D idxr3(maxT, maxU); + idx_b_t_u = idxr3(bTgt, t, u); + idx_b_t_up1 = idxr3(bTgt, t, u+1); + idx_b_tp1_u = idxr3(bTgt, t+1, u); + idx_b_tp1_up1 = idxr3(bTgt, t+1, u+1); + } + + if (idx_b_t_u == -1 ) { + return; + } + + if (isinf(cost) || isnan(cost)) { + for (int d = 0; d < D; ++d) { + int b_t_u_d = idx_b_t_u * D + d; + gradients[b_t_u_d] = 0; + } + return; + } + + CAST_DTYPE c = alphas[idx_b_t_u] + cost - denominators[idx_b_t_u]; + for (int d = 0; d < D; ++d) { + int b_t_u_d = idx_b_t_u * D + d; + CAST_DTYPE g = CAST_DTYPE(logits[b_t_u_d]) + c; + + if (!monotonic) { + if (fusedLogSmax) { + if (d == blank && t == T - 1 && u == U - 1) { // last blank transition. + gradients[b_t_u_d] = std::exp(g + betas[idx_b_t_u]) - std::exp(g); + } else if (t < T - 1 && d == blank) { + gradients[b_t_u_d] = std::exp(g + betas[idx_b_t_u]); + if (idx_b_tp1_u != -1) { + gradients[b_t_u_d] = gradients[b_t_u_d] - std::exp(g + betas[idx_b_tp1_u]); + } + + } else if (u < U - 1 && d == targets[idxr2(bTgt, u)]) { + gradients[b_t_u_d] = std::exp(g + betas[idx_b_t_u]); + if (idx_b_t_up1 != -1) { + gradients[b_t_u_d] = gradients[b_t_u_d] - std::exp(g + betas[idx_b_t_up1]); + } + } else { + gradients[b_t_u_d] = std::exp(g + betas[idx_b_t_u]); + } + } + else { // Non fused log softmax case + CAST_DTYPE g = cost + CAST_DTYPE(logits[b_t_u_d]); + if (d == blank && t == T - 1 && u == U - 1) { + gradients[b_t_u_d] = g + alphas[idx_b_t_u]; + } else if (t < T - 1 && d == blank) { + if (idx_b_tp1_u != -1) { + gradients[b_t_u_d] = g + alphas[idx_b_t_u] + betas[idx_b_tp1_u]; + } else { + gradients[b_t_u_d] = g + CAST_DTYPE(-INFINITY); + } + } else if (u < U - 1 && d == targets[idxr2(bTgt, u)]) { + + if (idx_b_t_up1 != -1) { + gradients[b_t_u_d] = g + alphas[idx_b_t_u] + betas[idx_b_t_up1]; + } else { + gradients[b_t_u_d] = g + CAST_DTYPE(-INFINITY); + } + + } + else { + gradients[b_t_u_d] = g + CAST_DTYPE(-INFINITY); + } + gradients[b_t_u_d] = -std::exp(gradients[b_t_u_d]); + } + } else { // Monotonic RNNT case + CAST_DTYPE g = cost + CAST_DTYPE(logits[b_t_u_d]); + if (d == blank && t == T - 1 && u == U - 1) { // last blank transition. + g = g + alphas[idx_b_t_u]; + } else if (t < T - 1 && d == blank) { + g = g + alphas[idx_b_t_u]; + if (idx_b_tp1_u != -1) { + g = g + betas[idx_b_tp1_u]; + } + } else if (u < U - 1 && t < T - 1 && d == targets[idxr2(bTgt, u)]) { + g = g + alphas[idx_b_t_u]; + if (idx_b_tp1_up1 != -1) { + g = g + betas[idx_b_tp1_up1]; + } + } + else { + g = g + CAST_DTYPE(-INFINITY); + } + gradients[b_t_u_d] = -std::exp(g); + } // end of monotonic else + + if (clamp > 0) { + auto g = CAST_DTYPE(gradients[b_t_u_d]); + gradients[b_t_u_d] = math::min(g, clamp); + gradients[b_t_u_d] = math::max(g, -clamp); + } + } +} + +} // namespace rnnt +} // namespace torchaudio diff --git a/torchaudio/csrc/rnnt/cpu/math.h b/torchaudio/csrc/rnnt/cpu/math.h new file mode 100644 index 0000000000..4f1d7bc4dd --- /dev/null +++ b/torchaudio/csrc/rnnt/cpu/math.h @@ -0,0 +1,35 @@ +#pragma once + +#include + +namespace torchaudio { +namespace rnnt { + +namespace math { + +template +FORCE_INLINE HOST_AND_DEVICE DTYPE max(DTYPE x, DTYPE y) { + if (x > y) return x; + else return y; +} + +template +FORCE_INLINE HOST_AND_DEVICE DTYPE min(DTYPE x, DTYPE y) { + if (x > y) return y; + else return x; +} + +// log_sum_exp +template +FORCE_INLINE HOST_AND_DEVICE DTYPE lse(DTYPE x, DTYPE y); + +template <> +FORCE_INLINE HOST_AND_DEVICE float lse(float x, float y) { + if (y > x) { return y + log1pf(expf(x - y)); } + else { return x + log1pf(expf(y-x)); } +} + +} + +} // namespace rnnt +} // namespace torchaudio diff --git a/torchaudio/csrc/rnnt/gpu/compute.cu b/torchaudio/csrc/rnnt/gpu/compute.cu new file mode 100644 index 0000000000..53567c131d --- /dev/null +++ b/torchaudio/csrc/rnnt/gpu/compute.cu @@ -0,0 +1,242 @@ +#include +#include +#include + +namespace torchaudio { +namespace rnnt { +namespace gpu { + +// Entry point into Sparse Alignment Restricted RNNT Loss. +std::tuple> +compute_sparse( + torch::Tensor& logits, + const torch::Tensor& targets, + const torch::Tensor& src_lengths, + const torch::Tensor& tgt_lengths, + int64_t blank, + double clamp, + int64_t max_T, + int64_t max_U, + const c10::optional& wp_ends = c10::nullopt, + int64_t l_buffer = 0, + int64_t r_buffer = 0, + const c10::optional& valid_ranges = c10::nullopt, + const c10::optional& cells_per_sample = c10::nullopt, + bool fused_log_smax = true, + bool reuse_logits_for_grads = true) { + + Options options; + options.batchSize_ = src_lengths.size(0); + options.nHypos_ = tgt_lengths.size(0) / src_lengths.size(0); + options.maxSrcLen_ = max_T; + options.maxTgtLen_ = max_U; + options.sparseCells_ = logits.size(0); + options.numTargets_ = logits.size(1); + options.fusedLogSmax_ = fused_log_smax; + + options.blank_ = blank; + options.clamp_ = clamp; + options.lBuffer_ = l_buffer; + options.rBuffer_ = r_buffer; + options.sparse_ = true; + + CHECK_EQ(logits.device().type(), torch::DeviceType::CUDA); + options.stream_ = at::cuda::getCurrentCUDAStream(); + cudaSetDevice(logits.get_device()); + options.device_ = GPU; + + torch::Tensor costs = torch::empty( + options.batchSize_ * options.nHypos_, + torch::TensorOptions().device(logits.device()).dtype(logits.dtype())); + + c10::optional gradients = c10::nullopt; + if (logits.requires_grad()) { + if (reuse_logits_for_grads) { + gradients = logits; + } else { + gradients = torch::zeros_like(logits); + } + } + torch::Tensor int_workspace = torch::empty( + IntWorkspace::ComputeSizeFromOptions(options), + torch::TensorOptions().device(logits.device()).dtype(torch::ScalarType::Int)); + + torch::Tensor float_workspace = torch::empty( + DtypeWorkspace::ComputeSizeFromOptions(options), + torch::TensorOptions().device(logits.device()).dtype(torch::ScalarType::Float)); + + Workspace workspace( + /*options=*/options, + /*dtype_data=*/float_workspace.data(), + /*dtype_size=*/float_workspace.numel(), + /*int_data=*/int_workspace.data(), + /*int_size=*/int_workspace.numel()); + + switch (logits.type().scalarType()) { + case torch::ScalarType::Float: + { + ComputeSparse( + /*workspace=*/workspace, + /*logits=*/logits.data(), + /*targets=*/targets.data(), + /*src_lengths=*/src_lengths.data(), + /*tgt_lengths=*/tgt_lengths.data(), + /*costs=*/costs.data(), + /*gradients=*/(gradients == c10::nullopt)? nullptr : gradients->data(), + /*wp_ends=*/(wp_ends == c10::nullopt)? nullptr : wp_ends->data(), + (valid_ranges == c10::nullopt)? nullptr : valid_ranges->data(), + (cells_per_sample == c10::nullopt)? nullptr : cells_per_sample->data()); + break; + } + case torch::ScalarType::Half: + { + ComputeSparse( + /*workspace=*/workspace, + /*logits=*/logits.data(), + /*targets=*/targets.data(), + /*src_lengths=*/src_lengths.data(), + /*tgt_lengths=*/tgt_lengths.data(), + /*costs=*/costs.data(), + /*gradients=*/(gradients == c10::nullopt)? nullptr : gradients->data(), + /*wp_ends=*/(wp_ends == c10::nullopt)? nullptr : wp_ends->data(), + (valid_ranges == c10::nullopt)? nullptr : valid_ranges->data(), + (cells_per_sample == c10::nullopt)? nullptr : cells_per_sample->data()); + break; + } + default: + { + LOG(ERROR) << "unsupported logits.type().scalarType() = " + << logits.type().scalarType(); + break; + } + }; + + + return std::make_tuple(costs, gradients); +} + + +// Entry point into RNNT Loss +std::tuple> +compute( + torch::Tensor& logits, + const torch::Tensor& targets, + const torch::Tensor& src_lengths, + const torch::Tensor& tgt_lengths, + int64_t blank, + double clamp, + const c10::optional& wp_ends = c10::nullopt, + int64_t l_buffer = 0, + int64_t r_buffer = 0, + bool fused_log_smax = true, + bool reuse_logits_for_grads = true) { + + Options options; + options.batchSize_ = src_lengths.size(0); + options.nHypos_ = tgt_lengths.size(0) / src_lengths.size(0); + options.maxSrcLen_ = logits.size(1); + options.maxTgtLen_ = logits.size(2); + options.numTargets_ = logits.size(3); + options.blank_ = blank; + options.clamp_ = clamp; + options.lBuffer_ = l_buffer; + options.rBuffer_ = r_buffer; + options.fusedLogSmax_ = fused_log_smax; + + CHECK_EQ(logits.device().type(), torch::DeviceType::CUDA); + options.stream_ = at::cuda::getCurrentCUDAStream(); + cudaSetDevice(logits.get_device()); + options.device_ = GPU; + + torch::Tensor costs = torch::empty( + options.batchSize_ * options.nHypos_, + torch::TensorOptions().device(logits.device()).dtype(logits.dtype())); + c10::optional gradients = c10::nullopt; + if (logits.requires_grad()) { + if (reuse_logits_for_grads) { + gradients = logits; + } else { + gradients = torch::zeros_like(logits); + } + } + + torch::Tensor int_workspace = torch::empty( + IntWorkspace::ComputeSizeFromOptions(options), + torch::TensorOptions().device(logits.device()).dtype(torch::ScalarType::Int)); + + torch::Tensor float_workspace = torch::empty( + DtypeWorkspace::ComputeSizeFromOptions(options), + torch::TensorOptions().device(logits.device()).dtype(torch::ScalarType::Float)); + + Workspace workspace( + /*options=*/options, + /*dtype_data=*/float_workspace.data(), + /*dtype_size=*/float_workspace.numel(), + /*int_data=*/int_workspace.data(), + /*int_size=*/int_workspace.numel()); + + switch (logits.type().scalarType()) { + case torch::ScalarType::Float: + { + Compute( + /*workspace=*/workspace, + /*logits=*/logits.data(), + /*targets=*/targets.data(), + /*src_lengths=*/src_lengths.data(), + /*tgt_lengths=*/tgt_lengths.data(), + /*costs=*/costs.data(), + /*gradients=*/(gradients == c10::nullopt)? nullptr : gradients->data(), + /*wp_ends=*/(wp_ends == c10::nullopt)? nullptr : wp_ends->data()); + break; + } + case torch::ScalarType::Half: + { + Compute( + /*workspace=*/workspace, + /*logits=*/logits.data(), + /*targets=*/targets.data(), + /*src_lengths=*/src_lengths.data(), + /*tgt_lengths=*/tgt_lengths.data(), + /*costs=*/costs.data(), + /*gradients=*/(gradients == c10::nullopt)? nullptr : gradients->data(), + /*wp_ends=*/(wp_ends == c10::nullopt)? nullptr : wp_ends->data()); + break; + } + default: + { + LOG(ERROR) << "unsupported logits.type().scalarType() = " + << logits.type().scalarType(); + break; + } + }; + + return std::make_tuple(costs, gradients); +} + +TORCH_LIBRARY_FRAGMENT(torchaudio, m) { + m.def("rnnt_loss_sparse(Tensor logits," + "Tensor targets," + "Tensor src_lengths," + "Tensor tgt_lengths," + "int blank," + "float clamp," + "int max_T," + "int max_U," + "Tensor? wp_ends=None," + "int l_buffer=0," + "int r_buffer=0," + "Tensor? valid_ranges=None," + "Tensor? cells_per_sample=None," + "bool fused_log_smax=True," + "bool reuse_logits_for_grads=True) -> (Tensor, Tensor?)", + &compute_sparse); +} + +TORCH_LIBRARY_IMPL(torchaudio, CUDA, m) { + m.impl("rnnt_loss", &compute); + m.impl("rnnt_loss_sparse", &compute_sparse); +} + +} // namespace gpu +} // namespace rnnt +} // namespace torchaudio diff --git a/torchaudio/csrc/rnnt/gpu/compute_alphas.cu b/torchaudio/csrc/rnnt/gpu/compute_alphas.cu new file mode 100644 index 0000000000..f9bff447cd --- /dev/null +++ b/torchaudio/csrc/rnnt/gpu/compute_alphas.cu @@ -0,0 +1,168 @@ +#include +#include +#include + +namespace torchaudio { +namespace rnnt { +namespace gpu { + +torch::Tensor compute_alphas( + const torch::Tensor& logits, + const torch::Tensor& targets, + const torch::Tensor& src_lengths, + const torch::Tensor& tgt_lengths, + int64_t blank, + double clamp, + const c10::optional& wp_ends = c10::nullopt, + int64_t l_buffer = 0, + int64_t r_buffer = 0) { + Options options; + options.batchSize_ = src_lengths.size(0); + options.nHypos_ = tgt_lengths.size(0) / src_lengths.size(0); + options.maxSrcLen_ = logits.size(1); + options.maxTgtLen_ = logits.size(2); + options.numTargets_ = logits.size(3); + options.blank_ = blank; + options.clamp_ = clamp; + options.lBuffer_ = l_buffer; + options.rBuffer_ = r_buffer; + + CHECK_EQ(logits.device().type(), torch::DeviceType::CUDA); + options.stream_ = at::cuda::getCurrentCUDAStream(); + cudaSetDevice(logits.get_device()); + options.device_ = GPU; + + torch::Tensor alphas = torch::zeros( + {options.batchSize_ * options.nHypos_, + options.maxSrcLen_, + options.maxTgtLen_}, + torch::TensorOptions().device(logits.device()).dtype(logits.dtype())); + + torch::Tensor int_workspace = torch::empty( + IntWorkspace::ComputeSizeFromOptions(options), + torch::TensorOptions() + .device(logits.device()) + .dtype(torch::ScalarType::Int)); + + torch::Tensor float_workspace = torch::empty( + DtypeWorkspace::ComputeSizeFromOptions(options), + torch::TensorOptions() + .device(logits.device()) + .dtype(torch::ScalarType::Float)); + + Workspace workspace( + /*options=*/options, + /*dtype_data=*/float_workspace.data(), + /*dtype_size=*/float_workspace.numel(), + /*int_data=*/int_workspace.data(), + /*int_size=*/int_workspace.numel()); + + // Only support float, this is mainly to enable easy + // unit-testing + ComputeAlphas( + /*workspace=*/workspace, + /*logits=*/logits.data(), + /*targets=*/targets.data(), + /*src_lengths=*/src_lengths.data(), + /*tgt_lengths=*/tgt_lengths.data(), + /*alphas=*/alphas.data(), + /*wp_ends=*/(wp_ends == c10::nullopt) ? nullptr : wp_ends->data()); + return alphas; +} + +torch::Tensor compute_alphas_sparse( + const torch::Tensor& logits, + const torch::Tensor& targets, + const torch::Tensor& src_lengths, + const torch::Tensor& tgt_lengths, + int64_t blank, + double clamp, + int64_t max_T, + int64_t max_U, + const c10::optional& wp_ends = c10::nullopt, + int64_t l_buffer = 0, + int64_t r_buffer = 0, + const c10::optional& valid_ranges = c10::nullopt, + const c10::optional& cells_per_sample = c10::nullopt) { + Options options; + options.batchSize_ = src_lengths.size(0); + options.nHypos_ = tgt_lengths.size(0) / src_lengths.size(0); + options.maxSrcLen_ = max_T; + options.maxTgtLen_ = max_U; + options.sparseCells_ = logits.size(0); + options.numTargets_ = logits.size(1); + + options.blank_ = blank; + options.clamp_ = clamp; + options.lBuffer_ = l_buffer; + options.rBuffer_ = r_buffer; + options.sparse_ = true; + + CHECK_EQ(logits.device().type(), torch::DeviceType::CUDA); + options.stream_ = at::cuda::getCurrentCUDAStream(); + cudaSetDevice(logits.get_device()); + options.device_ = GPU; + + torch::Tensor alphas = torch::zeros( + {logits.size(0)}, + torch::TensorOptions().device(logits.device()).dtype(logits.dtype())); + + torch::Tensor int_workspace = torch::empty( + IntWorkspace::ComputeSizeFromOptions(options), + torch::TensorOptions() + .device(logits.device()) + .dtype(torch::ScalarType::Int)); + + torch::Tensor float_workspace = torch::empty( + DtypeWorkspace::ComputeSizeFromOptions(options), + torch::TensorOptions() + .device(logits.device()) + .dtype(torch::ScalarType::Float)); + + Workspace workspace( + /*options=*/options, + /*dtype_data=*/float_workspace.data(), + /*dtype_size=*/float_workspace.numel(), + /*int_data=*/int_workspace.data(), + /*int_size=*/int_workspace.numel()); + + // Only support float, this is mainly to enable easy + // unit-testing + ComputeAlphasSparse( + /*workspace=*/workspace, + /*logits=*/logits.data(), + /*targets=*/targets.data(), + /*src_lengths=*/src_lengths.data(), + /*tgt_lengths=*/tgt_lengths.data(), + /*alphas=*/alphas.data(), + /*wp_ends=*/(wp_ends == c10::nullopt) ? nullptr : wp_ends->data(), + (valid_ranges == c10::nullopt) ? nullptr : valid_ranges->data(), + (cells_per_sample == c10::nullopt) ? nullptr + : cells_per_sample->data()); + return alphas; +} + +TORCH_LIBRARY_FRAGMENT(torchaudio, m) { + m.def("rnnt_loss_alphas_sparse(Tensor logits," + "Tensor targets," + "Tensor src_lengths," + "Tensor tgt_lengths," + "int blank," + "float clamp," + "int max_T," + "int max_U, Tensor? wp_ends=None," + "int l_buffer=0," + "int r_buffer=0," + "Tensor? valid_ranges=None," + "Tensor? cells_per_sample=None) -> Tensor", + &compute_alphas_sparse); +} + +TORCH_LIBRARY_IMPL(torchaudio, CUDA, m) { + m.impl("rnnt_loss_alphas", &compute_alphas); + m.impl("rnnt_loss_alphas_sparse", &compute_alphas_sparse); +} + +} // namespace gpu +} // namespace rnnt +} // namespace torchaudio diff --git a/torchaudio/csrc/rnnt/gpu/compute_betas.cu b/torchaudio/csrc/rnnt/gpu/compute_betas.cu new file mode 100644 index 0000000000..ffdad7ccb7 --- /dev/null +++ b/torchaudio/csrc/rnnt/gpu/compute_betas.cu @@ -0,0 +1,178 @@ +#include +#include +#include + +namespace torchaudio { +namespace rnnt { +namespace gpu { + +torch::Tensor compute_betas( + const torch::Tensor& logits, + const torch::Tensor& targets, + const torch::Tensor& src_lengths, + const torch::Tensor& tgt_lengths, + int64_t blank, + double clamp, + const c10::optional& wp_ends = c10::nullopt, + int64_t l_buffer = 0, + int64_t r_buffer = 0) { + Options options; + options.batchSize_ = src_lengths.size(0); + options.nHypos_ = tgt_lengths.size(0) / src_lengths.size(0); + options.maxSrcLen_ = logits.size(1); + options.maxTgtLen_ = logits.size(2); + options.numTargets_ = logits.size(3); + options.blank_ = blank; + options.clamp_ = clamp; + options.lBuffer_ = l_buffer; + options.rBuffer_ = r_buffer; + + CHECK_EQ(logits.device().type(), torch::DeviceType::CUDA); + options.stream_ = at::cuda::getCurrentCUDAStream(); + cudaSetDevice(logits.get_device()); + options.device_ = GPU; + + torch::Tensor costs = torch::empty( + tgt_lengths.size(0), + torch::TensorOptions().device(logits.device()).dtype(logits.dtype())); + + torch::Tensor betas = torch::zeros( + {options.batchSize_ * options.nHypos_, + options.maxSrcLen_, + options.maxTgtLen_}, + torch::TensorOptions().device(logits.device()).dtype(logits.dtype())); + + torch::Tensor int_workspace = torch::empty( + IntWorkspace::ComputeSizeFromOptions(options), + torch::TensorOptions() + .device(logits.device()) + .dtype(torch::ScalarType::Int)); + + torch::Tensor float_workspace = torch::empty( + DtypeWorkspace::ComputeSizeFromOptions(options), + torch::TensorOptions() + .device(logits.device()) + .dtype(torch::ScalarType::Float)); + + Workspace workspace( + /*options=*/options, + /*dtype_data=*/float_workspace.data(), + /*dtype_size=*/float_workspace.numel(), + /*int_data=*/int_workspace.data(), + /*int_size=*/int_workspace.numel()); + + // Only support float, this is mainly to enable easy + // unit-testing + ComputeBetas( + /*workspace=*/workspace, + /*logits=*/logits.data(), + /*targets=*/targets.data(), + /*src_lengths=*/src_lengths.data(), + /*tgt_lengths=*/tgt_lengths.data(), + /*costs=*/costs.data(), + /*betas=*/betas.data(), + /*wp_ends=*/(wp_ends == c10::nullopt) ? nullptr : wp_ends->data()); + return betas; +} + +torch::Tensor compute_betas_sparse( + const torch::Tensor& logits, + const torch::Tensor& targets, + const torch::Tensor& src_lengths, + const torch::Tensor& tgt_lengths, + int64_t blank, + double clamp, + int64_t max_T, + int64_t max_U, + const c10::optional& wp_ends = c10::nullopt, + int64_t l_buffer = 0, + int64_t r_buffer = 0, + const c10::optional& valid_ranges = c10::nullopt, + const c10::optional& cells_per_sample = c10::nullopt) { + Options options; + options.batchSize_ = src_lengths.size(0); + options.nHypos_ = tgt_lengths.size(0) / src_lengths.size(0); + options.maxSrcLen_ = max_T; + options.maxTgtLen_ = max_U; + options.sparseCells_ = logits.size(0); + options.numTargets_ = logits.size(1); + + options.blank_ = blank; + options.clamp_ = clamp; + options.lBuffer_ = l_buffer; + options.rBuffer_ = r_buffer; + + CHECK_EQ(logits.device().type(), torch::DeviceType::CUDA); + options.stream_ = at::cuda::getCurrentCUDAStream(); + cudaSetDevice(logits.get_device()); + options.device_ = GPU; + + torch::Tensor costs = torch::empty( + tgt_lengths.size(0), + torch::TensorOptions().device(logits.device()).dtype(logits.dtype())); + + torch::Tensor betas = torch::zeros( + {logits.size(0)}, + torch::TensorOptions().device(logits.device()).dtype(logits.dtype())); + + torch::Tensor int_workspace = torch::empty( + IntWorkspace::ComputeSizeFromOptions(options), + torch::TensorOptions() + .device(logits.device()) + .dtype(torch::ScalarType::Int)); + + torch::Tensor float_workspace = torch::empty( + DtypeWorkspace::ComputeSizeFromOptions(options), + torch::TensorOptions() + .device(logits.device()) + .dtype(torch::ScalarType::Float)); + + Workspace workspace( + /*options=*/options, + /*dtype_data=*/float_workspace.data(), + /*dtype_size=*/float_workspace.numel(), + /*int_data=*/int_workspace.data(), + /*int_size=*/int_workspace.numel()); + + // Only support float, this is mainly to enable easy + // unit-testing + ComputeBetasSparse( + /*workspace=*/workspace, + /*logits=*/logits.data(), + /*targets=*/targets.data(), + /*src_lengths=*/src_lengths.data(), + /*tgt_lengths=*/tgt_lengths.data(), + /*costs=*/costs.data(), + /*betas=*/betas.data(), + /*wp_ends=*/(wp_ends == c10::nullopt) ? nullptr : wp_ends->data(), + (valid_ranges == c10::nullopt) ? nullptr : valid_ranges->data(), + (cells_per_sample == c10::nullopt) ? nullptr + : cells_per_sample->data()); + return betas; +} + +TORCH_LIBRARY_FRAGMENT(torchaudio, m) { + m.def("rnnt_loss_betas_sparse(Tensor logits," + "Tensor targets," + "Tensor src_lengths," + "Tensor tgt_lengths," + "int blank," + "float clamp," + "int max_T," + "int max_U," + "Tensor? wp_ends=None," + "int l_buffer=0," + "int r_buffer=0," + "Tensor? valid_ranges=None," + "Tensor? cells_per_sample=None) -> Tensor", + &compute_betas_sparse); +} + +TORCH_LIBRARY_IMPL(torchaudio, CUDA, m) { + m.impl("rnnt_loss_betas", &compute_betas); + m.impl("rnnt_loss_betas_sparse", &compute_betas_sparse); +} + +} // namespace gpu +} // namespace rnnt +} // namespace torchaudio diff --git a/torchaudio/csrc/rnnt/gpu/gpu_alignment_restrictions.cuh b/torchaudio/csrc/rnnt/gpu/gpu_alignment_restrictions.cuh new file mode 100644 index 0000000000..564eb0a3fb --- /dev/null +++ b/torchaudio/csrc/rnnt/gpu/gpu_alignment_restrictions.cuh @@ -0,0 +1,551 @@ +#pragma once + +#ifdef USE_CUDA + +#include + +#include +#include +#include + +namespace torchaudio { +namespace rnnt { + +template +__global__ void ComputeLogProbsSparse( + int maxT, + int maxU, + int numTargets, + int blank, + const DTYPE* logits, + const int* targets, + const int* srcLengths, + const int* tgtLengths, + const CAST_DTYPE* denominators, + CAST_DTYPE* logProbs, + const int* wpEnds, + const int* validRanges=nullptr, + const int* cellsPerSample=nullptr, + int H=1, + bool fusedLogSmax=true) { + + const int bTgt = blockIdx.z; // 0 <= b < B + const int t = blockIdx.x * blockDim.x + threadIdx.x; + const int u = blockIdx.y; + + ComputeLogProbsSparseElement( + bTgt, + t, + u, + maxT, + maxU, + numTargets, + blank, + logits, + targets, + srcLengths, + tgtLengths, + denominators, + logProbs, + wpEnds, + validRanges, + cellsPerSample, + H=1, + fusedLogSmax); +} + +template +__device__ void ComputeAlphasRestricted( + int maxSrcLen, + int maxTgtLen, + int numTargets, + int blank, + const CAST_DTYPE* logProbs, + const int* srcLengths, + const int* tgtLengths, + int* alpha_counters, + volatile CAST_DTYPE* alphas, + const int* wpEnds, + int lBuffer, + int rBuffer, + int warp_size, + bool sparse=false, + const int* validRanges=nullptr, + const int* cellsPerSample=nullptr, + int H=1) { + + const int& maxT = maxSrcLen; + const int& maxU = maxTgtLen; + + // Block's 3d dim is batchsize + const int bTgt = blockIdx.z; // 0 <= b < B + const int bSrc = bTgt / H; + const int T = srcLengths[bSrc]; + const int U = tgtLengths[bTgt] + 1; + + assert(T <= maxT && "T must be < maxT"); + assert(U <= maxU && "U must be < maxU"); + + // Blocks 1st dim is T i.e. warpsize timesteps + // to find timestep, we index into correct block idx * dim + // then offset by the thread + const int t = blockIdx.x * blockDim.x + threadIdx.x; + + // Blocks 2nd dim is U. For u, we just offset by 2nd idx + const int u = blockIdx.y; + + // simply exit if we are out of bounds + // this happens typically when warp size is larger than T + if (t > T-1 || u > U-1 || t < 0 || u < 0) { + return; + } + + const int* wpEndsB = wpEnds + maxU * bTgt; + assert(wpEndsB[u] >= 0 && "wpEnds cannot be negative"); + if (u < U - 1) { + assert(wpEndsB[u+1] >= 0 && "wpEnds cannot be negative"); + } + + // below indexes are inclusive + // compute valid ranges for emit transitions in current warp + int emit_start = math::max(wpEndsB[u] - lBuffer, 0); + int emit_end = math::min(wpEndsB[u] + rBuffer, T - 1); + + // compute valid ranges for blank transitions in current warp + int blank_start = math::max(wpEndsB[u] - lBuffer + 1, 1); + int blank_end = (u == U - 1) ? T - 1 : math::min(wpEndsB[u + 1] + rBuffer, T - 1); + + // this is a useful pointer to track the last timestep + // for previous warp. + int prevWarpEndT = blockIdx.x * blockDim.x - 1; + + int* counter = alpha_counters + Indexer2D(maxU)(bTgt, blockIdx.y); + + + int idx_b_t_u = -1, idx_b_t_um1 = -1, idx_b_tm1_u = -1; + int idx_b_prevWarpEndT_u = -1; + + if (sparse) { + SparseIndexer idxr(maxU, tgtLengths, validRanges, cellsPerSample); + idx_b_t_u = idxr(bTgt, t, u); + idx_b_t_um1 = idxr(bTgt, t, u-1); + idx_b_tm1_u = idxr(bTgt, t-1, u); + idx_b_prevWarpEndT_u = idxr(bTgt, prevWarpEndT, u); + } else { + Indexer3D idxr(maxT, maxU); + idx_b_t_u = idxr(bTgt, t, u); + idx_b_t_um1 = idxr(bTgt, t, u - 1); + idx_b_tm1_u = idxr(bTgt, t - 1, u); + idx_b_prevWarpEndT_u = idxr(bTgt, prevWarpEndT, u); + } + + alphas[idx_b_t_u] = CAST_DTYPE(-INFINITY); + + // Initialization condition for alphas + if (t == 0 && u == 0) { + alphas[idx_b_t_u] = 0; + } + + // Synchronization routines: + // Below conditions make sure given t, u + // - threads in previous warp for u is complete + // - threads in the warp corresponding to t, u-1 is complete + // See https://github.com/1ytic/warp-rnnt for illustration + if (blockIdx.x > 0) { // wait for previous warp (in t-axis) is ready. + while (atomicAdd(counter, 0) < blockIdx.x) {} + } + + if (blockIdx.y > 0) { // wait for previous warp (in u-axis) is ready. + while (atomicAdd(counter - 1, 0) <= blockIdx.x) {} + } + + // This is initialization loop for t = 0, u + // i.e. emit condition while running alphas + if (t == 0 && u > 0) { + // Alignment Restriction check + if (in_range(emit_start, emit_end, t)) { + alphas[idx_b_t_u] = + alphas[idx_b_t_um1] + + logProbs[(idx_b_t_um1 << 1) + LOG_PROBS_EMIT_IDX]; + } + } + + // This is initialization loop for u = 0, t + if (u == 0 && t > 0) { + + // skip_prob stores the log probability of t, u + CAST_DTYPE skip_prob = logProbs[(idx_b_tm1_u << 1) + LOG_PROBS_SKIP_IDX]; + + #pragma unroll + // iterating on i = 1, 2, 4, 8.. + for (int i = 1; i < warp_size; i <<= 1) { + + // https://devblogs.nvidia.com/using-cuda-warp-level-primitives/ + // first param is a mask -1 indicates all threads in warp participate + // second param is the value being passed for current thread + // third param is the offset which will be used for addition of values + // copy from a thread with lower ID relative to the caller + CAST_DTYPE synced_val = __shfl_up_sync(0xffffffff, skip_prob, i); + + // Illustration with 8 threads in warp + // Initial: 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1 + // i == 1: 0.1, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2 + // i == 2: 0.1, 0.2, 0.3, 0.4, 0.4, 0.4, 0.4, 0.4 + // i == 4: 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8 + + // Alignment restriction check + // add to skip_prob only if *t-i* is within allowed range + if (i <= threadIdx.x && + in_range(blank_start, blank_end, t - i) ) { + skip_prob += synced_val; + } + } + + // update the values of alpha if *t* is within allowed range + if (in_range(blank_start, blank_end, t)) { + alphas[idx_b_t_u] = skip_prob; + } + + // Optionally add previous warp's end idx value if it is + // within range to get cumulative score for all previous timesteps, + // and not just within current warp + if (in_range(blank_start, blank_end, prevWarpEndT)) { + alphas[idx_b_t_u] += alphas[idx_b_prevWarpEndT_u]; + } + } + + // General case + if (t < T && u < U) { + + CAST_DTYPE skip_prob = CAST_DTYPE(-INFINITY); + if (in_range(blank_start, blank_end, t) && t > 0) { + skip_prob = logProbs[(idx_b_tm1_u << 1) + LOG_PROBS_SKIP_IDX]; + } + + // We check if the first index of current warp (prevWarpEndT+1) was within allowed + // timesteps, if so we add the alphas of previous warp's last timestep + // to skip score. + CAST_DTYPE skip = skip_prob; + if (in_range(blank_start, blank_end, prevWarpEndT+1) && prevWarpEndT >= 0) { + skip += alphas[idx_b_prevWarpEndT_u]; + } + + CAST_DTYPE emit = CAST_DTYPE(-INFINITY); + if (in_range(emit_start, emit_end, t) && u > 0) { + emit = alphas[idx_b_t_um1] + + logProbs[(idx_b_t_um1 << 1) + LOG_PROBS_EMIT_IDX]; + } + + CAST_DTYPE out_score = math::lse(skip, emit); + + + // Below we loop over warp_size updating the out score + // once per thread in each loop. + // shared memory is used to synchronize the values in threads + for(int i = 1; i < warp_size; i++) { + + CAST_DTYPE synced_val = __shfl_up_sync(0xffffffff, out_score, 1); + + // We will only update the out_score if t is within range + // of alignment constraints and it is the thread's turn in loop + if ((i == threadIdx.x) && in_range(blank_start, blank_end, t)) { + out_score = math::lse(synced_val + skip_prob, emit); + } + } + // update alphas if t was within range of blanks, or emits + if ( (in_range(blank_start, blank_end, t) || in_range(emit_start, emit_end, t) ) + && (t > 0 && u > 0)) { + alphas[idx_b_t_u] = out_score; + } + } + + // Synchronization mechanism + if (threadIdx.x == 0) { + __threadfence(); + atomicAdd(counter, 1); + } +} + + + +// This is a wrapper around ComputeAlphasRestricted +// kernel to enable unit testing +template +__global__ void ComputeAlphasRestrictedWrapper( + int maxSrcLen, + int maxTgtLen, + int numTargets, + int blank, + const CAST_DTYPE* logProbs, + const int* srcLengths, + const int* tgtLengths, + int* alpha_counters, + volatile CAST_DTYPE* alphas, + const int* wpEnds, + int lBuffer, + int rBuffer, + int warp_size, + bool sparse=false, + const int* validRanges=nullptr, + const int* cellsPerSample=nullptr, + int H=1) { + ComputeAlphasRestricted( + maxSrcLen, + maxTgtLen, + numTargets, + blank, + logProbs, + srcLengths, + tgtLengths, + alpha_counters, + alphas, + wpEnds, + lBuffer, + rBuffer, + warp_size, + sparse, + validRanges, + cellsPerSample, + H); +} + + +template +__device__ void ComputeBetasCostsRestricted( + int maxSrcLen, + int maxTgtLen, + int numTargets, + int blank, + const CAST_DTYPE* logProbs, + const int* srcLengths, + const int* tgtLengths, + int* beta_counters, + DTYPE* costs, + volatile CAST_DTYPE* betas, + const int* wpEnds, + int lBuffer, + int rBuffer, + int warp_size, + int num_warps, + bool sparse=false, + const int* validRanges=nullptr, + const int* cellsPerSample=nullptr, + int H=1) { + + const int& maxT = maxSrcLen; + const int& maxU = maxTgtLen; + + // Block's 3d dim is batchsize + const int bTgt = blockIdx.z; // 0 <= b < B + const int bSrc = bTgt / H; + const int T = srcLengths[bSrc]; + const int U = tgtLengths[bTgt] + 1; + + assert(T <= maxT); + assert(U <= maxU); + + const int t = T - 1 - blockIdx.x * blockDim.x - threadIdx.x; + const int u = U - 1 - blockIdx.y; + + if (t < 0 || u < 0) { // out of boundary. + return; + } + + const int* wpEndsB = wpEnds + maxU * bTgt; + + // below indexes are inclusive + // compute valid ranges for emit transitions in + // current warp + int emit_start = (u >= U - 1) ? -1 : math::max(0, wpEndsB[u + 1] - lBuffer); + int emit_end = (u >= U - 1) ? -1 : math::min(wpEndsB[u + 1] + rBuffer, T - 1); + + + // compute valid ranges for blank transitions in + // current warp + int blank_start = (u > U - 1) ? -1 : math::max(wpEndsB[u] - lBuffer, 0); + int blank_end = (u >= U - 1) ? T - 2 : math::min(wpEndsB[u + 1] + rBuffer - 1, T - 2); + + int rightBlockStartT = T - 1 - blockIdx.x * blockDim.x + 1; + int* counter = beta_counters + Indexer2D(maxU)(bTgt, blockIdx.y); + + int idx_b_t_u = -1, idx_b_t_up1 = -1; + int idx_b_tp1_up1 = -1, idx_b_rightBlockStartT_u = -1; + if (sparse) { + SparseIndexer idxr(maxU, tgtLengths, validRanges, cellsPerSample); + idx_b_t_u = idxr(bTgt, t, u); + idx_b_t_up1 = idxr(bTgt, t, u+1); + idx_b_tp1_up1 = idxr(bTgt, t+1, u+1); + idx_b_rightBlockStartT_u = idxr(bTgt, rightBlockStartT, u); + } else { + Indexer3D idxr(maxT, maxU); + idx_b_t_u = idxr(bTgt, t, u); + idx_b_t_up1 = idxr(bTgt, t, u+1); + idx_b_tp1_up1 = idxr(bTgt, t+1, u+1); + idx_b_rightBlockStartT_u = idxr(bTgt, rightBlockStartT, u); + } + + if (t < T && u < U) { + betas[idx_b_t_u] = CAST_DTYPE(-INFINITY); + } + + // Initialization condition + if (t == T - 1 && u == U - 1) { + betas[idx_b_t_u] = + logProbs[(idx_b_t_u << 1) + LOG_PROBS_SKIP_IDX]; + } + + // For betas, we process warps from right to left + // blockIdx.x specifies the warp id for a given u + // here we want to wait until the warp to the right is done + if (blockIdx.x > 0) { // wait for previous warp (in t-axis) is ready. + while (atomicAdd(counter, 0) < blockIdx.x) {} + } + + if (blockIdx.y > 0) { // wait for previous warp (in u-axis) is ready. + while (atomicAdd(counter - 1, 0) <= blockIdx.x) {} + } + + // edge condition for emits + if (t == T - 1 && u < U - 1) { + if (emit_start <= t && t <= emit_end) { + betas[idx_b_t_u] = + betas[idx_b_t_up1] + + logProbs[(idx_b_t_u << 1) + LOG_PROBS_EMIT_IDX]; + } + } + + if (u == U - 1 && t <= T - 1) { + CAST_DTYPE skip_prob = logProbs[(idx_b_t_u << 1) + LOG_PROBS_SKIP_IDX]; + + #pragma unroll + for(int i = 1; i < warp_size; i <<= 1) { + + CAST_DTYPE synced_val = __shfl_up_sync(0xffffffff, skip_prob, i); + if (i <= threadIdx.x && in_range(blank_start, blank_end, t)) { + skip_prob = skip_prob + synced_val; + } + } + + if (in_range(blank_start, blank_end, t) && t < T - 1) { + // we add skipprob and right block's first value + // and assign it to beta + betas[idx_b_t_u] = skip_prob; + if (in_range(blank_start, blank_end, rightBlockStartT) || + in_range(emit_start, emit_end, rightBlockStartT)) { + betas[idx_b_t_u] += betas[idx_b_rightBlockStartT_u]; + } + } + } + + // General case + if (t < T && u < U) { + + CAST_DTYPE skip_prob = CAST_DTYPE(-INFINITY); + if (in_range(blank_start, blank_end, t)) { + skip_prob = logProbs[(idx_b_t_u << 1) + LOG_PROBS_SKIP_IDX]; + } + // We check if the first index of right warp is within allowed + // timesteps, if so we add the betas of right warp's first timestep + // to skip score + CAST_DTYPE skip = skip_prob; + if (in_range(blank_start, blank_end, rightBlockStartT) || in_range(emit_start, emit_end, rightBlockStartT)) { + skip += betas[idx_b_rightBlockStartT_u]; + } + + CAST_DTYPE emit = CAST_DTYPE(-INFINITY); + if (in_range(emit_start, emit_end, t) && u < U - 1) { + emit = betas[idx_b_t_up1] + + logProbs[(idx_b_t_u << 1) + LOG_PROBS_EMIT_IDX]; + } + + CAST_DTYPE out_score = CAST_DTYPE(-INFINITY); + if (skip != CAST_DTYPE(-INFINITY) || emit != CAST_DTYPE(-INFINITY)) { + out_score = math::lse(skip, emit); + } + + for(int i = 1; i < warp_size; i++) { + + CAST_DTYPE synced_val = __shfl_up_sync(0xffffffff, out_score, 1); + + if (i == threadIdx.x && + (in_range(blank_start, blank_end, t) || + in_range(emit_start, emit_end, t)) + ) { + out_score = math::lse(synced_val + skip_prob, emit); + } + } + + // bounds check for last warps + if (t < T - 1 && u < U - 1) { + // bound checks for t + if (in_range(blank_start, blank_end, t) || + in_range(emit_start, emit_end, t)) { + betas[idx_b_t_u] = out_score; + } + } + } + + if (t == 0 && u == 0) { // use -beta(0, 0) as cost. + if (isinf(-betas[idx_b_t_u]) || isnan(-betas[idx_b_t_u])) { + costs[bTgt] = 0; + } else { + costs[bTgt] = -betas[idx_b_t_u]; + } + } + + if (threadIdx.x == 0) { + __threadfence(); + atomicAdd(counter, 1); + } +} + + +// This is a wrapper around ComputeAlphasRestricted +// kernel to enable unit testing +template +__global__ void ComputeBetasCostsRestrictedWrapper( + int maxSrcLen, + int maxTgtLen, + int numTargets, + int blank, + const CAST_DTYPE* logProbs, + const int* srcLengths, + const int* tgtLengths, + int* beta_counters, + CAST_DTYPE* costs, + volatile CAST_DTYPE* betas, + const int* wpEnds, + int lBuffer, + int rBuffer, + int warp_size, + int num_warp, + bool sparse=false, + const int* validRanges=nullptr, + const int* cellsPerSample=nullptr, + int H=1) { + ComputeBetasCostsRestricted( + maxSrcLen, + maxTgtLen, + numTargets, + blank, + logProbs, + srcLengths, + tgtLengths, + beta_counters, + costs, + betas, + wpEnds, + lBuffer, + rBuffer, + warp_size, + num_warp, + sparse, + validRanges, + cellsPerSample, + H); +} + +} // namespace rnnt +} // namespace torchaudio + +#endif // USE_CUDA diff --git a/torchaudio/csrc/rnnt/gpu/gpu_kernel_utils.cuh b/torchaudio/csrc/rnnt/gpu/gpu_kernel_utils.cuh new file mode 100644 index 0000000000..f42e35b46f --- /dev/null +++ b/torchaudio/csrc/rnnt/gpu/gpu_kernel_utils.cuh @@ -0,0 +1,99 @@ +#pragma once + +#ifdef USE_CUDA + +#include + +namespace torchaudio { +namespace rnnt { + +template +__global__ void ReduceMax2D( + int dim, + const DTYPE* inputs, // [N, dim] + CAST_DTYPE* outputs) { + + __shared__ CAST_DTYPE shared[NUM_THREADS]; + + // each thread reduces one matrix row + int offset = blockIdx.x * dim; // [n, 0] + CAST_DTYPE val = inputs[offset]; // default = inputs(n, 0) + for (int d = threadIdx.x; d < dim; d += NUM_THREADS) { + CAST_DTYPE next = inputs[offset + d]; + if (next > val) { + val = next; + } + } + + shared[threadIdx.x] = val; + __syncthreads(); + + for (int stride = (NUM_THREADS >> 1); stride >= WARP_SIZE; stride >>= 1) { + if (threadIdx.x < stride && threadIdx.x + stride < dim) { + if (shared[threadIdx.x + stride] > shared[threadIdx.x]) { + shared[threadIdx.x] = shared[threadIdx.x + stride]; + val = shared[threadIdx.x]; + } + } + __syncthreads(); + } + + CAST_DTYPE shf; + for (int stride = (WARP_SIZE >> 1); stride > 0; stride >>= 1) { + shf = __shfl_down_sync(0xFFFFFFFF, val, stride); + if (threadIdx.x < stride && threadIdx.x + stride < dim) { + if (shf > val) { + val = shf; + } + } + } + + if (threadIdx.x == 0) { + outputs[blockIdx.x] = val; + } +} + +template +__global__ void ReduceLogSumExpGivenMax2D( + int dim, + const DTYPE* inputs, // [N, dim] + CAST_DTYPE* outputs) { // in: max -> out: logsum + + __shared__ CAST_DTYPE shared[NUM_THREADS]; + + CAST_DTYPE max = outputs[blockIdx.x]; + CAST_DTYPE val = 0; + + int offset = blockIdx.x * dim; + for (int d = threadIdx.x; d < dim; d += NUM_THREADS) { + val = val + std::exp(CAST_DTYPE(inputs[offset + d]) - max); + } + + shared[threadIdx.x] = val; + __syncthreads(); + + for (int stride = (NUM_THREADS >> 1); stride >= WARP_SIZE; stride >>= 1) { + if (threadIdx.x < stride && threadIdx.x + stride < dim) { + val = shared[threadIdx.x] + shared[threadIdx.x + stride]; + shared[threadIdx.x] = val; + } + __syncthreads(); + } + + CAST_DTYPE shf; + for (int stride = (WARP_SIZE >> 1); stride > 0; stride >>= 1) { + shf = __shfl_down_sync(0xFFFFFFFF, val, stride); + if (threadIdx.x < stride && threadIdx.x + stride < dim) { + val = val + shf; + } + } + + if (threadIdx.x == 0) { + outputs[blockIdx.x] = max + std::log(val); + } +} + +} // namespace rnnt +} // namespace torchaudio + +#endif // USE_CUDA diff --git a/torchaudio/csrc/rnnt/gpu/gpu_kernels.cuh b/torchaudio/csrc/rnnt/gpu/gpu_kernels.cuh new file mode 100644 index 0000000000..88f625a251 --- /dev/null +++ b/torchaudio/csrc/rnnt/gpu/gpu_kernels.cuh @@ -0,0 +1,488 @@ +#pragma once + +#ifdef USE_CUDA + +#include + +#include +#include +#include + +namespace torchaudio { +namespace rnnt { + + +template +__global__ void ComputeLogProbs( + int maxSrcLen, + int maxTgtLen, + int numTargets, + int blank, + const DTYPE* logits, + const int* targets, + const int* srcLengths, + const int* tgtLengths, + const CAST_DTYPE* denominators, + CAST_DTYPE* logProbs, + int H=1, + bool fusedLogSmax=true) { + + const int& maxT = maxSrcLen; + const int& maxU = maxTgtLen; + const int& D = numTargets; + + const int bTgt = blockIdx.z; // 0 <= b < B + const int bSrc = bTgt / H; + const int T = srcLengths[bSrc]; + const int U = tgtLengths[bTgt] + 1; + + const int t = blockIdx.x * blockDim.x + threadIdx.x; + const int u = blockIdx.y; + + if (t >= T || u >= U) { // out of boundary. + return; + } + + Indexer3D indexer(maxT, maxU); + + int idx = indexer(bTgt, t, u); + + // skip: log_prob(b, t, u).skip() = logits(b, t, u, blank) - denom(b, t, u). + logProbs[(idx << 1) + LOG_PROBS_SKIP_IDX] = + CAST_DTYPE(logits[idx * D + blank]) - denominators[idx]; + + if (!fusedLogSmax) { + logProbs[(idx << 1) + LOG_PROBS_SKIP_IDX] = + CAST_DTYPE(logits[idx * D + blank]); + } + + if (u < U - 1) { + // emit: log_prob(b, t, u).emit() = logits(b, t, u, tgt[u]) - denom(b, t, u). + int target = targets[Indexer2D(maxU - 1)(bTgt, u)]; + logProbs[(idx << 1) + LOG_PROBS_EMIT_IDX] = + CAST_DTYPE(logits[idx * D + target]) - denominators[idx]; + + if (!fusedLogSmax) { + logProbs[(idx << 1) + LOG_PROBS_EMIT_IDX] = + CAST_DTYPE(logits[idx * D + target]); + } + } + + +} + + +template +__device__ void ComputeAlphas( + int maxSrcLen, + int maxTgtLen, + int numTargets, + int blank, + const CAST_DTYPE* logProbs, + const int* srcLengths, + const int* tgtLengths, + int* alpha_counters, + volatile CAST_DTYPE* alphas, + int H=1) { + + const int& maxT = maxSrcLen; + const int& maxU = maxTgtLen; + + const int bTgt = blockIdx.z; // 0 <= b < B + const int bSrc = bTgt / H; + const int T = srcLengths[bSrc]; + const int U = tgtLengths[bTgt] + 1; + + const int t = blockIdx.x * blockDim.x + threadIdx.x + 1; + const int u = blockIdx.y + 1; + + if (t >= T || u >= U) { // out of boundary. + return; + } + + int* counter = alpha_counters + Indexer2D(maxU)(bTgt, blockIdx.y); + + Indexer3D idxr(maxT, maxU); + + if (t == 1 && u == 1) { + alphas[idxr(bTgt, 0, 0)] = 0; + } + + if (blockIdx.x > 0) { // wait for previous warp (in t-axis) is ready. + while (atomicAdd(counter, 0) < blockIdx.x) {} + } + + if (blockIdx.y > 0) { // wait for previous warp (in u-axis) is ready. + while (atomicAdd(counter - 1, 0) <= blockIdx.x) {} + } + + if (t == 1 && u < U) { + + // alpha(0, u) = alpha(0, u - 1) + logProbs(0, u - 1).emit(). + alphas[idxr(bTgt, 0, u)] = + alphas[idxr(bTgt, 0, u - 1)] + + logProbs[(idxr(bTgt, 0, u - 1) << 1) + LOG_PROBS_EMIT_IDX]; + } + + if (blockIdx.y == 0 && t < T) { + CAST_DTYPE skip_prob = logProbs[(idxr(bTgt, t - 1, 0) << 1) + LOG_PROBS_SKIP_IDX]; + CAST_DTYPE val; + +#pragma unroll + for (int i = 1; i < warpSize; i <<= 1) { + val = __shfl_up_sync(0xffffffff, skip_prob, i); + if (i <= threadIdx.x) { + skip_prob = skip_prob + val; + } + } + + val = alphas[idxr(bTgt, blockIdx.x * blockDim.x, 0)]; + alphas[idxr(bTgt, t, 0)] = skip_prob + val; + } + + if (t < T && u < U) { + + CAST_DTYPE skip_prob = logProbs[(idxr(bTgt, t - 1, u) << 1) + LOG_PROBS_SKIP_IDX]; + CAST_DTYPE emit_prob = logProbs[(idxr(bTgt, t, u - 1) << 1) + LOG_PROBS_EMIT_IDX]; + + CAST_DTYPE skip = alphas[idxr(bTgt, blockIdx.x * blockDim.x, u)] + skip_prob; + CAST_DTYPE emit = alphas[idxr(bTgt, t, u - 1)] + emit_prob; + + CAST_DTYPE val = math::lse(skip, emit); + CAST_DTYPE out = val; + + for(int i = 1; i < warpSize; ++i) { + val = __shfl_up_sync(0xffffffff, val, 1); + if (i == threadIdx.x) { + val = math::lse(val + skip_prob, emit); + out = val; + } + } + + alphas[idxr(bTgt, t, u)] = out; + } + + if (threadIdx.x == 0) { + __threadfence(); + atomicAdd(counter, 1); + } +} + + +template +__device__ void ComputeBetasCosts( + int maxSrcLen, + int maxTgtLen, + int numTargets, + int blank, + const CAST_DTYPE* logProbs, + const int* srcLengths, + const int* tgtLengths, + int* betaCounters, + volatile CAST_DTYPE* betas, + DTYPE* costs, + int H=1) { + + const int& maxT = maxSrcLen; + const int& maxU = maxTgtLen; + + const int bTgt = blockIdx.z; // 0 <= b < B + const int bSrc = bTgt / H; + const int T = srcLengths[bSrc]; + const int U = tgtLengths[bTgt] + 1; + + const int t = T - 2 - blockIdx.x * blockDim.x - threadIdx.x; + const int u = U - 2 - blockIdx.y; + + if (t < 0 || u < 0) { // out of boundary. + return; + } + + int* counter = betaCounters + Indexer2D(maxU)(bTgt, blockIdx.y); + + Indexer3D idxr(maxT, maxU); + + if (t == T - 2 && u == U - 2) { + betas[idxr(bTgt, T - 1, U - 1)] = + logProbs[(idxr(bTgt, T - 1, U - 1) << 1) + LOG_PROBS_SKIP_IDX]; + } + + if (blockIdx.x > 0) { // wait for previous warp (in t-axis) is ready. + while (atomicAdd(counter, 0) < blockIdx.x) {} + } + + if (blockIdx.y > 0) { // wait for previous warp (in u-axis) is ready. + while (atomicAdd(counter - 1, 0) <= blockIdx.x) {} + } + + if (t == T - 2 && u >= 0) { + + betas[idxr(bTgt, T - 1, u)] = + betas[idxr(bTgt, T - 1, u + 1)] + + logProbs[(idxr(bTgt, T - 1, u) << 1) + LOG_PROBS_EMIT_IDX]; + } + + if (blockIdx.y == 0 && t >= 0) { + CAST_DTYPE skip_prob = logProbs[(idxr(bTgt, t, U - 1) << 1) + LOG_PROBS_SKIP_IDX]; + CAST_DTYPE val; + +#pragma unroll + for(int i = 1; i < warpSize; i <<= 1) { + val = __shfl_up_sync(0xffffffff, skip_prob, i); + if (i <= threadIdx.x) { + skip_prob = skip_prob + val; + } + } + + betas[idxr(bTgt, t, U - 1)] = + betas[idxr(bTgt, T - 1 - blockIdx.x * blockDim.x, U - 1)] + skip_prob; + } + + if (t >= 0 && u >= 0) { + + CAST_DTYPE skip_prob = logProbs[(idxr(bTgt, t, u) << 1) + LOG_PROBS_SKIP_IDX]; + CAST_DTYPE emit_prob = logProbs[(idxr(bTgt, t, u) << 1) + LOG_PROBS_EMIT_IDX]; + + CAST_DTYPE skip = betas[idxr(bTgt, t + threadIdx.x + 1, u)] + skip_prob; + CAST_DTYPE emit = betas[idxr(bTgt, t, u + 1)] + emit_prob; + + CAST_DTYPE val = math::lse(skip, emit); + CAST_DTYPE out = val; + + for(int i = 1; i < warpSize; ++i) { + val = __shfl_up_sync(0xffffffff, val, 1); + if (i == threadIdx.x) { + val = math::lse(val + skip_prob, emit); + out = val; + } + } + + betas[idxr(bTgt, t, u)] = out; + + if (t == 0 && u == 0) { // use -beta(0, 0) as cost. + costs[bTgt] = DTYPE(-out); + } + } + + if (threadIdx.x == 0) { + __threadfence(); + atomicAdd(counter, 1); + } +} + + +template +__global__ void ComputeAlphasBetasCosts( + int maxSrcLen, + int maxTgtLen, + int numTargets, + int blank, + const CAST_DTYPE* logProbs, + const int* srcLengths, + const int* tgtLengths, + int* alpha_counters, + volatile CAST_DTYPE* alphas, + int* betaCounters, + volatile CAST_DTYPE* betas, + DTYPE* costs, + const int* wpEnds=nullptr, + int lBuffer = 0, + int rBuffer = 0, + int warpSize = 0, + int numWarps=0, + bool sparse=false, + const int* validRanges=nullptr, + const int* cellsPerSample=nullptr, + int H = 1) { + + assert(threadIdx.y == 0 || threadIdx.y == 1); + + if (threadIdx.y == 0) { + if (wpEnds == nullptr) { + ComputeAlphas( + /*maxSrcLen=*/maxSrcLen, + /*maxTgtLen=*/maxTgtLen, + /*numTargets=*/numTargets, + /*blank=*/blank, + /*logProbs=*/logProbs, + /*srcLengths=*/srcLengths, + /*tgtLengths=*/tgtLengths, + /*alpha_counters=*/alpha_counters, + /*alphas=*/alphas, + H); + } + else { + ComputeAlphasRestricted( + /*maxSrcLen=*/maxSrcLen, + /*maxTgtLen=*/maxTgtLen, + /*numTargets=*/numTargets, + /*blank=*/blank, + /*logProbs=*/logProbs, + /*srcLengths=*/srcLengths, + /*tgtLengths=*/tgtLengths, + /*alpha_counters=*/alpha_counters, + /*alphas=*/(CAST_DTYPE*)alphas, + /*wpEnds=*/wpEnds, + /*lBuffer=*/lBuffer, + /*rBuffer=*/rBuffer, + /*warpSize=*/warpSize, + sparse, + validRanges, + cellsPerSample, + H); + } + } else { // threadIdx.y == 1 + if (wpEnds == nullptr) { + ComputeBetasCosts( + /*maxSrcLen=*/maxSrcLen, + /*maxTgtLen=*/maxTgtLen, + /*numTargets=*/numTargets, + /*blank=*/blank, + /*logProbs=*/logProbs, + /*srcLengths=*/srcLengths, + /*tgtLengths=*/tgtLengths, + /*betaCounters=*/betaCounters, + /*beta=*/betas, + /*costs=*/costs, + H); + } else { + ComputeBetasCostsRestricted( + maxSrcLen, + maxTgtLen, + numTargets, + blank, + logProbs, + srcLengths, + tgtLengths, + betaCounters, + costs, + betas, + wpEnds, + lBuffer, + rBuffer, + warpSize, + numWarps, + sparse, + validRanges, + cellsPerSample, + H); + } + + } +} + + +template +__global__ void ComputeGradients( + int maxSrcLen, + int maxTgtLen, + int numTargets, + int blank, + CAST_DTYPE clamp, + const DTYPE* logits, + const int* targets, + const int* srcLengths, + const int* tgtLengths, + const CAST_DTYPE* denominators, + const CAST_DTYPE* alphas, + const CAST_DTYPE* betas, + DTYPE* gradients, + bool sparse = false, + const int* validRanges = nullptr, + const int* cellsPerSample = nullptr, + int H = 1, + bool fusedLogSmax = true) { + + const int bTgt = blockIdx.z; // 0 <= b < B + const int t = blockIdx.x * blockDim.x + threadIdx.x; + const int u = blockIdx.y; + + ComputeGradientsElement( + bTgt, + t, + u, + maxSrcLen, + maxTgtLen, + numTargets, + blank, + clamp, + logits, + targets, + srcLengths, + tgtLengths, + denominators, + alphas, + betas, + gradients, + sparse, + validRanges, + cellsPerSample, + H, + fusedLogSmax); +} + + +// This is a __global__ wrapper around ComputeAlphas +// device kernel to enable unit testing +template +__global__ void ComputeAlphasWrapper( + int maxSrcLen, + int maxTgtLen, + int numTargets, + int blank, + const CAST_DTYPE* logProbs, + const int* srcLengths, + const int* tgtLengths, + int* alpha_counters, + volatile CAST_DTYPE* alphas, + int H=1) { + ComputeAlphas( + maxSrcLen, + maxTgtLen, + numTargets, + blank, + logProbs, + srcLengths, + tgtLengths, + alpha_counters, + alphas, + H); +} + +// This is a __global__ wrapper around ComputeBetas +// device kernel to enable unit testing +template +__global__ void ComputeBetasWrapper( + int maxSrcLen, + int maxTgtLen, + int numTargets, + int blank, + const CAST_DTYPE* logProbs, + const int* srcLengths, + const int* tgtLengths, + int* betaCounters, + volatile CAST_DTYPE* betas, + DTYPE* costs, + int H=1) { + ComputeBetasCosts( + maxSrcLen, + maxTgtLen, + numTargets, + blank, + logProbs, + srcLengths, + tgtLengths, + betaCounters, + betas, + costs, + H); +} + + +// #undef LOG_PROBS_SKIP_IDX +// #undef LOG_PROBS_EMIT_IDX + +} // namespace rnnt +} // namespace torchaudio + +#endif // USE_CUDA diff --git a/torchaudio/csrc/rnnt/gpu/gpu_transducer.h b/torchaudio/csrc/rnnt/gpu/gpu_transducer.h new file mode 100644 index 0000000000..7db7fe8a78 --- /dev/null +++ b/torchaudio/csrc/rnnt/gpu/gpu_transducer.h @@ -0,0 +1,829 @@ +#pragma once + +#ifdef USE_CUDA + +#include +#include +#include +#include + +namespace torchaudio { +namespace rnnt { +namespace gpu { + +#define gpuErrchk(ans) \ + { gpuAssert((ans), __FILE__, __LINE__); } + +inline void +gpuAssert(cudaError_t code, const char* file, int line, bool abort = true) { + if (code != cudaSuccess) { + fprintf( + stderr, + "\nGPUassert: %s %s %d\n", + cudaGetErrorString(code), + file, + line); + if (abort) + exit(code); + } +} + +template +status_t LogSumExp2D( + cudaStream_t stream, + int N, + int D, + const DTYPE* logits, // [N, D] + CAST_DTYPE* outputs) { + { // compute max among D. + dim3 block_dims(N); + dim3 thread_dims(REDUCE_THREADS); + + ReduceMax2D + <<>>( + /*dim=*/D, + /*inputs=*/logits, + /*outputs=*/outputs); + + // BUGBUG: These error codes are only accurate when launching with + // blocking. Otherwise they usually reflect earlier errors. + if (cudaGetLastError() != cudaSuccess) { + return COMPUTE_DENOMINATOR_REDUCE_MAX_FAILED; + } + } + + { // compute log(sum(exp(d_i - max))) + dim3 block_dims(N); + dim3 thread_dims(REDUCE_THREADS); + + ReduceLogSumExpGivenMax2D + <<>>( + /*dim=*/D, + /*inputs=*/logits, + /*outputs=*/outputs); + + if (cudaGetLastError() != cudaSuccess) { + return COMPUTE_DENOMINATOR_REDUCE_SUM_FAILED; + } + } + + return SUCCESS; +} + +// Inputs: +// workspace: workspace. +// logits: pointer to (B, max_T, max_U, D) logits. +// targets: pointer to (B, max_U - 1) targets in the batch. +// srcLengths: pointer to (B, ) source lengths in the batch. +// tgtLengths: pointer to (B, ) target lengths in the batch. +// +// Outputs: +// costs: pointer to (B, ) costs in the batch. +// gradients: pointer to (B, max_T, max_U, D) gradients in the batch. +template +status_t Compute( + const Workspace& workspace, + const DTYPE* logits, + const int* targets, + const int* srcLengths, + const int* tgtLengths, + DTYPE* costs, + DTYPE* gradients = nullptr, + const int* wpEnds = nullptr) { + const Options& options = workspace.GetOptions(); + + const cudaStream_t& stream = options.stream_; + const int& B = options.batchSize_; + const int& H = options.nHypos_; + const int& max_T = options.maxSrcLen_; + const int& max_U = options.maxTgtLen_; + const int& D = options.numTargets_; + const int& blank = options.blank_; + const CAST_DTYPE clamp = options.clamp_; + + const int& l_buffer = options.lBuffer_; + const int& r_buffer = options.rBuffer_; + const bool& fusedLogSmax = options.fusedLogSmax_; + + { // compute denominators. + status_t status = LogSumExp2D( + /*stream=*/stream, + /*N=*/B * H * max_T * max_U, + /*D=*/D, + /*logits=*/logits, + /*denominators=*/workspace.GetPointerToDenominators()); + + if (status != SUCCESS) { + return status; + } + } + + { // compute log probability pairs (blank and target). + int num_segments = + (max_T + MAX_THREADS_PER_BLOCK - 1) / MAX_THREADS_PER_BLOCK; + dim3 block_dims(num_segments, max_U, B * H); + dim3 thread_dims(MAX_THREADS_PER_BLOCK); + + ComputeLogProbs<<>>( + /*max_src_len=*/max_T, + /*max_tgt_len=*/max_U, + /*num_targets=*/D, + /*blank=*/blank, + /*logits=*/logits, + /*targets=*/targets, + /*srcLengths=*/srcLengths, + /*tgtLengths=*/tgtLengths, + /*denominators=*/workspace.GetPointerToDenominators(), + /*log_probs=*/workspace.GetPointerToLogProbs(), + H, + fusedLogSmax); + + if (cudaGetLastError() != cudaSuccess) { + return COMPUTE_LOG_PROBS_FAILED; + } + } + + { // compute alphas, betas and costs. + // warp is usually a group of threads (32) + int num_warps = (max_T + WARP_SIZE - 1) / WARP_SIZE; + + // each block is identified by 3 d tuple. + // we are using num_warp * max_U * B * H blocks + // where num_warp is division among Time axis + dim3 block_dims(num_warps, max_U, B * H); + + // each thread is identified by a 2 d tuple + // 2nd dim is 2. 1 for alpha, 1 for beta + dim3 thread_dims(WARP_SIZE, 2); + + ComputeAlphasBetasCosts + <<>>( + /*max_src_len=*/max_T, + /*max_tgt_len=*/max_U, + /*num_targets=*/D, + /*blank=*/blank, + /*log_probs=*/workspace.GetPointerToLogProbs(), + /*srcLengths=*/srcLengths, + /*tgtLengths=*/tgtLengths, + /*alpha_counters=*/workspace.GetPointerToAlphaCounters(), + /*alphas=*/workspace.GetPointerToAlphas(), + /*beta_counters=*/workspace.GetPointerToBetaCounters(), + /*betas=*/workspace.GetPointerToBetas(), + /*costs=*/costs, + /*wpEnds=*/wpEnds, + /*l_buffer=*/l_buffer, + /*r_buffer=*/r_buffer, + /*warp_size=*/WARP_SIZE, + /*num_warps=*/num_warps, + /*sparse=*/false, + /*validRanges=*/nullptr, + /*cellsPerSample=*/nullptr, + H); + if (cudaGetLastError() != cudaSuccess) { + return COMPUTE_ALPHAS_BETAS_COSTS_FAILED; + } + } + + if (gradients != nullptr) { // compute gradients. + // don't set gradients to zero to here as gradients might reuse memory from + // logits + + int num_blocks = + (max_T + MAX_THREADS_PER_BLOCK - 1) / MAX_THREADS_PER_BLOCK; + dim3 block_dims(num_blocks, max_U, B * H); + dim3 thread_dims(MAX_THREADS_PER_BLOCK); + + ComputeGradients<<>>( + /*max_src_len=*/max_T, + /*max_tgt_len=*/max_U, + /*num_targets=*/D, + /*blank=*/blank, + /*clamp=*/clamp, + /*logits=*/logits, + /*targets=*/targets, + /*srcLengths=*/srcLengths, + /*tgtLengths=*/tgtLengths, + /*denominators=*/workspace.GetPointerToDenominators(), + /*alphas=*/workspace.GetPointerToAlphas(), + /*betas=*/workspace.GetPointerToBetas(), + /*gradients=*/gradients, + /*sparse=*/false, + /*validRanges=*/nullptr, + /*cellsPerSample=*/nullptr, + H, + fusedLogSmax); + if (cudaGetLastError() != cudaSuccess) { + return COMPUTE_GRADIENTS_FAILED; + } + } + + return SUCCESS; +} + +// Inputs: +// workspace: workspace. +// logits: pointer to (sparseCells, D) logits. +// targets: pointer to (B, max_U - 1) targets in the batch. +// srcLengths: pointer to (B, ) source lengths in the batch. +// tgtLengths: pointer to (B, ) target lengths in the batch. +// +// Outputs: +// costs: pointer to (B, ) costs in the batch. +// gradients: pointer to (sparseCells, D) gradients in the batch. +template +status_t ComputeSparse( + const Workspace& workspace, + const DTYPE* logits, + const int* targets, + const int* srcLengths, + const int* tgtLengths, + DTYPE* costs, + DTYPE* gradients = nullptr, + const int* wpEnds = nullptr, + const int* validRanges = nullptr, + const int* cellsPerSample = nullptr) { + const Options& options = workspace.GetOptions(); + + const cudaStream_t& stream = options.stream_; + const int& B = options.batchSize_; + const int& H = options.nHypos_; + const int& max_T = options.maxSrcLen_; + const int& max_U = options.maxTgtLen_; + const int& D = options.numTargets_; + const int& blank = options.blank_; + const CAST_DTYPE clamp = options.clamp_; + + const int& l_buffer = options.lBuffer_; + const int& r_buffer = options.rBuffer_; + const bool& fusedLogSmax = options.fusedLogSmax_; + + const int& sparseCells = options.sparseCells_; + { // compute denominators. + // for sparse kernel, we call kernel with sparseSize + status_t status = LogSumExp2D( + /*stream=*/stream, + /*N=*/sparseCells, // not B * max_T * max_U + /*D=*/D, + /*logits=*/logits, + /*denominators=*/workspace.GetPointerToDenominators()); + gpuErrchk(cudaGetLastError()); + if (status != SUCCESS) { + return status; + } + } + { // compute log probability pairs (blank and target). + int num_segments = + (max_T + MAX_THREADS_PER_BLOCK - 1) / MAX_THREADS_PER_BLOCK; + dim3 block_dims(num_segments, max_U, B * H); + dim3 thread_dims(MAX_THREADS_PER_BLOCK); + + ComputeLogProbsSparse + <<>>( + max_T, + max_U, + /*num_targets=*/D, + /*blank=*/blank, + /*logits=*/logits, + /*targets=*/targets, + /*srcLengths=*/srcLengths, + /*tgtLengths=*/tgtLengths, + /*denominators=*/workspace.GetPointerToDenominators(), + /*log_probs=*/workspace.GetPointerToLogProbs(), + wpEnds, + validRanges, + cellsPerSample, + H, + fusedLogSmax); + gpuErrchk(cudaGetLastError()); + } + { // compute alphas, betas and costs. + // warp is usually a group of threads (32) + int num_warps = (max_T + WARP_SIZE - 1) / WARP_SIZE; + + // each block is identified by 3 d tuple. + // we are using num_warp * max_U * B * H blocks + // where num_warp is division among Time axis + dim3 block_dims(num_warps, max_U, B * H); + + // each thread is identified by a 2 d tuple + // 2nd dim is 2. 1 for alpha, 1 for beta + dim3 thread_dims(WARP_SIZE, 2); + + ComputeAlphasBetasCosts + <<>>( + /*max_src_len=*/max_T, + /*max_tgt_len=*/max_U, + /*num_targets=*/D, + /*blank=*/blank, + /*log_probs=*/workspace.GetPointerToLogProbs(), + /*srcLengths=*/srcLengths, + /*tgtLengths=*/tgtLengths, + /*alpha_counters=*/workspace.GetPointerToAlphaCounters(), + /*alphas=*/workspace.GetPointerToAlphas(), + /*beta_counters=*/workspace.GetPointerToBetaCounters(), + /*betas=*/workspace.GetPointerToBetas(), + /*costs=*/costs, + /*wpEnds=*/wpEnds, + /*l_buffer=*/l_buffer, + /*r_buffer=*/r_buffer, + /*warp_size=*/WARP_SIZE, + /*num_warps=*/num_warps, + true, + validRanges, + cellsPerSample, + H); + gpuErrchk(cudaGetLastError()); + } + + if (gradients != nullptr) { // compute gradients. + // don't zero gradients here as gradient might share memory with logits + + int num_blocks = + (max_T + MAX_THREADS_PER_BLOCK - 1) / MAX_THREADS_PER_BLOCK; + dim3 block_dims(num_blocks, max_U, B * H); + dim3 thread_dims(MAX_THREADS_PER_BLOCK); + + ComputeGradients<<>>( + /*max_src_len=*/max_T, + /*max_tgt_len=*/max_U, + /*num_targets=*/D, + /*blank=*/blank, + /*clamp=*/clamp, + /*logits=*/logits, + /*targets=*/targets, + /*srcLengths=*/srcLengths, + /*tgtLengths=*/tgtLengths, + /*denominators=*/workspace.GetPointerToDenominators(), + /*alphas=*/workspace.GetPointerToAlphas(), + /*betas=*/workspace.GetPointerToBetas(), + /*gradients=*/gradients, + /*sparse=*/true, + /*validRanges=*/validRanges, + /*cellsPerSample=*/cellsPerSample, + H, + fusedLogSmax); + gpuErrchk(cudaGetLastError()); + } + + return SUCCESS; +} + +template +status_t ComputeAlphas( + const Workspace& workspace, + const DTYPE* logits, + const int* targets, + const int* srcLengths, + const int* tgtLengths, + DTYPE* alphas, + const int* wpEnds = nullptr) { + const Options& options = workspace.GetOptions(); + + const cudaStream_t& stream = options.stream_; + const int& B = options.batchSize_; + const int& H = options.nHypos_; + const int& max_T = options.maxSrcLen_; + const int& max_U = options.maxTgtLen_; + const int& D = options.numTargets_; + const int& blank = options.blank_; + + const int& l_buffer = options.lBuffer_; + const int& r_buffer = options.rBuffer_; + + { // compute denominators. + status_t status = LogSumExp2D( + /*stream=*/stream, + /*N=*/B * H * max_T * max_U, + /*D=*/D, + /*logits=*/logits, + /*denominators=*/workspace.GetPointerToDenominators()); + + if (status != SUCCESS) { + return status; + } + } + + { // compute log probability pairs (blank and target). + int num_segments = + (max_T + MAX_THREADS_PER_BLOCK - 1) / MAX_THREADS_PER_BLOCK; + dim3 block_dims(num_segments, max_U, B * H); + dim3 thread_dims(MAX_THREADS_PER_BLOCK); + + ComputeLogProbs<<>>( + /*max_src_len=*/max_T, + /*max_tgt_len=*/max_U, + /*num_targets=*/D, + /*blank=*/blank, + /*logits=*/logits, + /*targets=*/targets, + /*srcLengths=*/srcLengths, + /*tgtLengths=*/tgtLengths, + /*denominators=*/workspace.GetPointerToDenominators(), + /*log_probs=*/workspace.GetPointerToLogProbs(), + H); + + if (cudaGetLastError() != cudaSuccess) { + return COMPUTE_LOG_PROBS_FAILED; + } + } + { // compute alphas + // warp is usually a group of threads (32) + int num_warps = (max_T + WARP_SIZE - 1) / WARP_SIZE; + + // each block is identified by 3 d tuple. + // we are using num_warp * max_U * B blocks + // where num_warp is division among Time axis + dim3 block_dims(num_warps, max_U, B * H); + + // each thread is identified by a 2 d tuple + // 2nd dim is 1 for alpha only + dim3 thread_dims(WARP_SIZE, 1); + + if (wpEnds == nullptr) { + ComputeAlphasWrapper + <<>>( + /*max_src_len=*/max_T, + /*max_tgt_len=*/max_U, + /*num_targets=*/D, + /*blank=*/blank, + /*log_probs=*/workspace.GetPointerToLogProbs(), + /*srcLengths=*/srcLengths, + /*tgtLengths=*/tgtLengths, + /*alpha_counters=*/workspace.GetPointerToAlphaCounters(), + /*alphas=*/(volatile DTYPE*)alphas, + H); + } else { + // cudaMemset(alphas, 0, B * max_T * max_U * sizeof(DTYPE)); + ComputeAlphasRestrictedWrapper + <<>>( + max_T, + max_U, + D, + blank, + workspace.GetPointerToLogProbs(), + srcLengths, + tgtLengths, + workspace.GetPointerToAlphaCounters(), + // workspace.GetPointerToAlphas(), + (volatile DTYPE*)alphas, + wpEnds, + l_buffer, + r_buffer, + WARP_SIZE, + false, + nullptr, + nullptr, + H); + } + if (cudaGetLastError() != cudaSuccess) { + return COMPUTE_ALPHAS_BETAS_COSTS_FAILED; + } + } + + return SUCCESS; +} + +template +status_t ComputeAlphasSparse( + const Workspace& workspace, + const DTYPE* logits, + const int* targets, + const int* srcLengths, + const int* tgtLengths, + DTYPE* alphas, + const int* wpEnds = nullptr, + const int* validRanges = nullptr, + const int* cellsPerSample = nullptr) { + const Options& options = workspace.GetOptions(); + const cudaStream_t& stream = options.stream_; + const int& B = options.batchSize_; + const int& H = options.nHypos_; + const int& max_T = options.maxSrcLen_; + const int& max_U = options.maxTgtLen_; + const int& D = options.numTargets_; + const int& blank = options.blank_; + + const int& l_buffer = options.lBuffer_; + const int& r_buffer = options.rBuffer_; + + const int& sparseCells = options.sparseCells_; + + { // compute denominators. + // for sparse kernel, we would call kernel with sparseSize + status_t status = LogSumExp2D( + /*stream=*/stream, + /*N=*/sparseCells, // not B * max_T * max_U + /*D=*/D, + /*logits=*/logits, + /*denominators=*/workspace.GetPointerToDenominators()); + + if (status != SUCCESS) { + return status; + } + } + + { // compute log probability pairs (blank and target). + int num_segments = + (max_T + MAX_THREADS_PER_BLOCK - 1) / MAX_THREADS_PER_BLOCK; + dim3 block_dims(num_segments, max_U, B * H); + dim3 thread_dims(MAX_THREADS_PER_BLOCK); + + ComputeLogProbsSparse + <<>>( + max_T, + max_U, + /*num_targets=*/D, + /*blank=*/blank, + /*logits=*/logits, + /*targets=*/targets, + /*srcLengths=*/srcLengths, + /*tgtLengths=*/tgtLengths, + /*denominators=*/workspace.GetPointerToDenominators(), + /*log_probs=*/workspace.GetPointerToLogProbs(), + wpEnds, + validRanges, + cellsPerSample, + H); + + if (cudaGetLastError() != cudaSuccess) { + return COMPUTE_LOG_PROBS_FAILED; + } + } + { // compute alphas + // warp is usually a group of threads (32) + int num_warps = (max_T + WARP_SIZE - 1) / WARP_SIZE; + + // each block is identified by 3 d tuple. + // we are using num_warp * max_U * B blocks + // where num_warp is division among Time axis + dim3 block_dims(num_warps, max_U, B * H); + + // each thread is identified by a 2 d tuple + // 2nd dim is 1 for alpha only + dim3 thread_dims(WARP_SIZE, 1); + + // cudaMemset(alphas, 0, B * max_T * max_U * sizeof(DTYPE)); + ComputeAlphasRestrictedWrapper + <<>>( + max_T, + max_U, + D, + blank, + workspace.GetPointerToLogProbs(), + srcLengths, + tgtLengths, + workspace.GetPointerToAlphaCounters(), + // workspace.GetPointerToAlphas(), + (volatile DTYPE*)alphas, + wpEnds, + l_buffer, + r_buffer, + WARP_SIZE, + true, + validRanges, + cellsPerSample, + H); + + if (cudaGetLastError() != cudaSuccess) { + return COMPUTE_ALPHAS_BETAS_COSTS_FAILED; + } + } + + return SUCCESS; +} + +template +status_t ComputeBetas( + const Workspace& workspace, + const DTYPE* logits, + const int* targets, + const int* srcLengths, + const int* tgtLengths, + DTYPE* costs, + DTYPE* betas, + const int* wpEnds = nullptr) { + const Options& options = workspace.GetOptions(); + + const cudaStream_t& stream = options.stream_; + const int& B = options.batchSize_; + const int& H = options.nHypos_; + const int& max_T = options.maxSrcLen_; + const int& max_U = options.maxTgtLen_; + const int& D = options.numTargets_; + const int& blank = options.blank_; + + const int& l_buffer = options.lBuffer_; + const int& r_buffer = options.rBuffer_; + + { // compute denominators. + status_t status = LogSumExp2D( + /*stream=*/stream, + /*N=*/B * H * max_T * max_U, + /*D=*/D, + /*logits=*/logits, + /*denominators=*/workspace.GetPointerToDenominators()); + + if (status != SUCCESS) { + return status; + } + } + + { // compute log probability pairs (blank and target). + int num_segments = + (max_T + MAX_THREADS_PER_BLOCK - 1) / MAX_THREADS_PER_BLOCK; + dim3 block_dims(num_segments, max_U, B * H); + dim3 thread_dims(MAX_THREADS_PER_BLOCK); + + ComputeLogProbs<<>>( + /*max_src_len=*/max_T, + /*max_tgt_len=*/max_U, + /*num_targets=*/D, + /*blank=*/blank, + /*logits=*/logits, + /*targets=*/targets, + /*srcLengths=*/srcLengths, + /*tgtLengths=*/tgtLengths, + /*denominators=*/workspace.GetPointerToDenominators(), + /*log_probs=*/workspace.GetPointerToLogProbs(), + H); + + if (cudaGetLastError() != cudaSuccess) { + return COMPUTE_LOG_PROBS_FAILED; + } + } + { // compute betas + // warp is usually a group of threads (32) + int num_warps = (max_T + WARP_SIZE - 1) / WARP_SIZE; + + // each block is identified by 3 d tuple. + // we are using num_warp * max_U * B blocks + // where num_warp is division among Time axis + dim3 block_dims(num_warps, max_U, B * H); + + // each thread is identified by a 2 d tuple + // 2nd dim is 1 for betas only + dim3 thread_dims(WARP_SIZE, 1); + + if (wpEnds == nullptr) { + ComputeBetasWrapper + <<>>( + /*max_src_len=*/max_T, + /*max_tgt_len=*/max_U, + /*num_targets=*/D, + /*blank=*/blank, + /*log_probs=*/workspace.GetPointerToLogProbs(), + /*srcLengths=*/srcLengths, + /*tgtLengths=*/tgtLengths, + /*alpha_counters=*/workspace.GetPointerToBetaCounters(), + /*alphas=*/(volatile DTYPE*)betas, + costs, + H); + } else { + ComputeBetasCostsRestrictedWrapper + <<>>( + max_T, + max_U, + D, + blank, + workspace.GetPointerToLogProbs(), + srcLengths, + tgtLengths, + workspace.GetPointerToBetaCounters(), + costs, + (volatile DTYPE*)betas, + wpEnds, + l_buffer, + r_buffer, + WARP_SIZE, + num_warps, + false, + nullptr, + nullptr, + H); + cudaDeviceSynchronize(); + } + if (cudaGetLastError() != cudaSuccess) { + return COMPUTE_ALPHAS_BETAS_COSTS_FAILED; + } + } + + return SUCCESS; +} + +template +status_t ComputeBetasSparse( + const Workspace& workspace, + const DTYPE* logits, + const int* targets, + const int* srcLengths, + const int* tgtLengths, + DTYPE* costs, + DTYPE* betas, + const int* wpEnds = nullptr, + const int* validRanges = nullptr, + const int* cellsPerSample = nullptr) { + const Options& options = workspace.GetOptions(); + const cudaStream_t& stream = options.stream_; + const int& B = options.batchSize_; + const int& H = options.nHypos_; + const int& max_T = options.maxSrcLen_; + const int& max_U = options.maxTgtLen_; + const int& D = options.numTargets_; + const int& blank = options.blank_; + + const int& l_buffer = options.lBuffer_; + const int& r_buffer = options.rBuffer_; + + const int& sparseCells = options.sparseCells_; + + { // compute denominators. + // for sparse kernel, we would call kernel with sparseSize + status_t status = LogSumExp2D( + /*stream=*/stream, + /*N=*/sparseCells, // not B * max_T * max_U + /*D=*/D, + /*logits=*/logits, + /*denominators=*/workspace.GetPointerToDenominators()); + + if (status != SUCCESS) { + return status; + } + } + + { // compute log probability pairs (blank and target). + int num_segments = + (max_T + MAX_THREADS_PER_BLOCK - 1) / MAX_THREADS_PER_BLOCK; + dim3 block_dims(num_segments, max_U, B * H); + dim3 thread_dims(MAX_THREADS_PER_BLOCK); + + ComputeLogProbsSparse + <<>>( + max_T, + max_U, + /*num_targets=*/D, + /*blank=*/blank, + /*logits=*/logits, + /*targets=*/targets, + /*srcLengths=*/srcLengths, + /*tgtLengths=*/tgtLengths, + /*denominators=*/workspace.GetPointerToDenominators(), + /*log_probs=*/workspace.GetPointerToLogProbs(), + wpEnds, + validRanges, + cellsPerSample, + H); + + if (cudaGetLastError() != cudaSuccess) { + return COMPUTE_LOG_PROBS_FAILED; + } + } + { // compute alphas + // warp is usually a group of threads (32) + int num_warps = (max_T + WARP_SIZE - 1) / WARP_SIZE; + + // each block is identified by 3 d tuple. + // we are using num_warp * max_U * B blocks + // where num_warp is division among Time axis + dim3 block_dims(num_warps, max_U, B * H); + + // each thread is identified by a 2 d tuple + // 2nd dim is 1 for alpha only + dim3 thread_dims(WARP_SIZE, 1); + + // cudaMemset(alphas, 0, B * max_T * max_U * sizeof(DTYPE)); + ComputeBetasCostsRestrictedWrapper + <<>>( + max_T, + max_U, + D, + blank, + workspace.GetPointerToLogProbs(), + srcLengths, + tgtLengths, + workspace.GetPointerToBetaCounters(), + costs, + (volatile DTYPE*)betas, + wpEnds, + l_buffer, + r_buffer, + WARP_SIZE, + num_warps, + true, + validRanges, + cellsPerSample, + H); + cudaDeviceSynchronize(); + + if (cudaGetLastError() != cudaSuccess) { + return COMPUTE_ALPHAS_BETAS_COSTS_FAILED; + } + } + + return SUCCESS; +} + +} // namespace gpu +} // namespace rnnt +} // namespace torchaudio + +#endif // USE_CUDA diff --git a/torchaudio/csrc/rnnt/gpu/half.cuh b/torchaudio/csrc/rnnt/gpu/half.cuh new file mode 100644 index 0000000000..d49ac3bdcf --- /dev/null +++ b/torchaudio/csrc/rnnt/gpu/half.cuh @@ -0,0 +1,38 @@ +#pragma once + +#ifdef USE_C10_HALF +#include "c10/util/Half.h" +#endif // USE_C10_HALF + +#include + +namespace torchaudio { +namespace rnnt { + +struct alignas(sizeof(__half)) Half { + __half x; + + HOST_AND_DEVICE Half() = default; + + FORCE_INLINE HOST_AND_DEVICE Half(float f) { + x = __float2half_rn(f); + if (isinf(__half2float(x))) { + x = __float2half_rz(f); // round toward 0. + } + } + + FORCE_INLINE HOST_AND_DEVICE operator float() const { + return __half2float(x); + } + + FORCE_INLINE HOST_AND_DEVICE Half(__half f) { + x = f; + } + + FORCE_INLINE HOST_AND_DEVICE operator __half() const { + return x; + } +}; + +} // namespace rnnt +} // namespace torchaudio diff --git a/torchaudio/csrc/rnnt/gpu/kernel_utils.h b/torchaudio/csrc/rnnt/gpu/kernel_utils.h new file mode 100644 index 0000000000..89d681a22d --- /dev/null +++ b/torchaudio/csrc/rnnt/gpu/kernel_utils.h @@ -0,0 +1,117 @@ +#pragma once + +#include + +#include + +namespace torchaudio { +namespace rnnt { + +inline HOST_AND_DEVICE bool in_range( + int start, + int end, // inclusive + int val) { + return start <= val && val <= end; +} + +#define LOG_PROBS_SKIP_IDX 0 +#define LOG_PROBS_EMIT_IDX 1 + + +struct Indexer2D { + const int& size2_; + + FORCE_INLINE HOST_AND_DEVICE Indexer2D(const int& size2): size2_(size2) {} + + FORCE_INLINE HOST_AND_DEVICE int operator() (int index1, int index2) { + return index1 * size2_ + index2; + } +}; + + +struct Indexer3D { + const int& size2_; + const int& size3_; + + FORCE_INLINE HOST_AND_DEVICE Indexer3D(const int& size2, const int& size3) + : size2_(size2), size3_(size3) {} + + FORCE_INLINE HOST_AND_DEVICE int operator() (int index1, int index2, int index3) { + return (index1 * size2_ + index2) * size3_ + index3; + } +}; + + +struct Indexer4D { + const int& size2_; + const int& size3_; + const int& size4_; + + HOST_AND_DEVICE Indexer4D(const int& size2, const int& size3, const int& size4) + : size2_(size2), size3_(size3), size4_(size4) {} + + HOST_AND_DEVICE int operator() (int index1, int index2, int index3, int index4) { + return ((index1 * size2_ + index2) * size3_ + index3) * size4_ + index4; + } +}; + + +struct SparseIndexer { + HOST_AND_DEVICE SparseIndexer( + const int& maxU, + const int* tgtLengths, + const int* validRanges, + const int* cellsPerSample) : + maxU_(maxU), + tgtLengths_(tgtLengths), + validRanges_(validRanges), + cellsPerSample_(cellsPerSample) {}; + + HOST_AND_DEVICE int operator() (int bIdx, int tIdx, int uIdx) { + // Returns the sparse index given bIdx, tIdx, uIdx; or -1 if t out of band. + + // increment the idx for valid cells in previous samples + // TODO: Inefficient in the inner loop; precompute this? + int idx = 0; + for(int b = 0 ; b < bIdx; b++) { + idx += cellsPerSample_[b]; + } + + // increment the idx for valid cells in current sample + // using pre-computed valid ranges + const int* validRangesB = validRanges_ + (maxU_ * 2) * bIdx; + int U = tgtLengths_[bIdx] + 1; + for (int u = 0 ; u < U ; u++) { + int startT = validRangesB[2*u]; + int endT = validRangesB[2*u + 1]; + if (u == uIdx) { + if (tIdx < startT || tIdx > endT) { + return -1; + } + idx += (tIdx - startT); + return idx; + } else { + idx += (endT - startT) + 1; + } + } + return -1; + } + + private: + const int& maxU_; + + // (vector of size B) contains the lengths of U for each sample in batch + const int* tgtLengths_; + + // (vector of size B*2*U) contains the valid time ranges (start_t, end_t) + // for each u in every sample, as per alignment restrictions + const int* validRanges_; + + // The total valid timesteps for each sample (sumed over all u in the sample). + // This is a quick loopup so we dont need to iterate on all previous u*b values. + const int* cellsPerSample_; + +}; + +} // namespace rnnt +} // namespace torchaudio diff --git a/torchaudio/csrc/rnnt/gpu/kernels.h b/torchaudio/csrc/rnnt/gpu/kernels.h new file mode 100644 index 0000000000..2dbf6231b4 --- /dev/null +++ b/torchaudio/csrc/rnnt/gpu/kernels.h @@ -0,0 +1,215 @@ +#pragma once + +#include + +#include +#include + +namespace torchaudio { +namespace rnnt { + + +template +FORCE_INLINE HOST_AND_DEVICE void ComputeLogProbsSparseElement( + int bTgt, + int t, + int u, + int maxT, + int maxU, + int numTargets, + int blank, + const DTYPE* logits, + const int* targets, + const int* srcLengths, + const int* tgtLengths, + const CAST_DTYPE* denominators, + CAST_DTYPE* logProbs, + const int* wpEnds, + const int* validRanges=nullptr, + const int* cellsPerSample=nullptr, + int H=1, + bool fusedLogSmax=true) { + + const int& D = numTargets; + + const int bSrc = bTgt / H; + const int T = srcLengths[bSrc]; + const int U = tgtLengths[bTgt] + 1; + + if (t >= T || u >= U) { // out of boundary. + return; + } + const int* validRangesB = validRanges + (maxU*2) * bTgt; + int start = validRangesB[2*u]; + int end = validRangesB[2*u + 1]; + + // out of boundary for alignment restriction condition + if (t < start || t > end) { + return; + } + SparseIndexer idxr(maxU, tgtLengths, validRanges, cellsPerSample); + int idx = idxr(bTgt, t, u); + logProbs[(idx << 1) + LOG_PROBS_SKIP_IDX] = + CAST_DTYPE(logits[idx * D + blank]) - denominators[idx]; + + if (!fusedLogSmax) { + logProbs[(idx << 1) + LOG_PROBS_SKIP_IDX] = + CAST_DTYPE(logits[idx * D + blank]); + } + + if (u < U - 1) { + // emit: log_prob(b, t, u).emit() = logits(b, t, u, tgt[u]) - denom(b, t, u). + int target = targets[Indexer2D(maxU - 1)(bTgt, u)]; + logProbs[(idx << 1) + LOG_PROBS_EMIT_IDX] = + CAST_DTYPE(logits[idx * D + target]) - denominators[idx]; + + if (!fusedLogSmax) { + logProbs[(idx << 1) + LOG_PROBS_EMIT_IDX] = + CAST_DTYPE(logits[idx * D + target]); + } + } +} + + +template +HOST_AND_DEVICE void ComputeGradientsElement( + int bTgt, + int t, + int u, + int maxSrcLen, + int maxTgtLen, + int numTargets, + int blank, + CAST_DTYPE clamp, + const DTYPE* logits, + const int* targets, + const int* srcLengths, + const int* tgtLengths, + const CAST_DTYPE* denominators, + const CAST_DTYPE* alphas, + const CAST_DTYPE* betas, + DTYPE* gradients, + bool sparse = false, + const int* validRanges = nullptr, + const int* cellsPerSample = nullptr, + int H = 1, + bool fusedLogSmax = true) { + + const int& maxT = maxSrcLen; + const int& maxU = maxTgtLen; + const int& D = numTargets; + + const int bSrc = bTgt / H; + const int T = srcLengths[bSrc]; + const int U = tgtLengths[bTgt] + 1; + + if (t >= T || u >= U) { // out of boundary. + if (sparse) { + // no extra elements needs to be set to 0 + return; + } else if (gradients == logits && t < maxT && u < maxU) { + // gradients and logits are pointing to the same memory location + Indexer3D idxr3(maxT, maxU); + int idx_b_t_u_zero = idxr3(bTgt, t, u); + if (idx_b_t_u_zero != -1 ) { + int start = idx_b_t_u_zero * D; + for (int b_t_u_d = start; b_t_u_d < start + D; ++b_t_u_d) { + gradients[b_t_u_d] = 0; + } + } + } + return; + } + + int costIdx; + if (!sparse) { + costIdx = bTgt * maxT * maxU; + } else { + SparseIndexer idxr(maxU, tgtLengths, validRanges, cellsPerSample); + costIdx = idxr(bTgt, 0, 0); + } + CAST_DTYPE cost = -(betas[costIdx]); + + + Indexer2D idxr2(maxU - 1); + + int idx_b_t_u, idx_b_t_up1, idx_b_tp1_u, idx_b_tp1_up1; + if (sparse) { + SparseIndexer idxr(maxU, tgtLengths, validRanges, cellsPerSample); + idx_b_t_u = idxr(bTgt, t, u); + idx_b_t_up1 = idxr(bTgt, t, u+1); + idx_b_tp1_u = idxr(bTgt, t+1, u); + idx_b_tp1_up1 = idxr(bTgt, t+1, u+1); + } else { + Indexer3D idxr3(maxT, maxU); + idx_b_t_u = idxr3(bTgt, t, u); + idx_b_t_up1 = idxr3(bTgt, t, u+1); + idx_b_tp1_u = idxr3(bTgt, t+1, u); + idx_b_tp1_up1 = idxr3(bTgt, t+1, u+1); + } + + if (idx_b_t_u == -1 ) { + return; + } + + if (isinf(cost) || isnan(cost)) { + for (int d = 0; d < D; ++d) { + int b_t_u_d = idx_b_t_u * D + d; + gradients[b_t_u_d] = 0; + } + return; + } + + CAST_DTYPE c = alphas[idx_b_t_u] + cost - denominators[idx_b_t_u]; + for (int d = 0; d < D; ++d) { + int b_t_u_d = idx_b_t_u * D + d; + CAST_DTYPE g = CAST_DTYPE(logits[b_t_u_d]) + c; + + if (fusedLogSmax) { + if (d == blank && t == T - 1 && u == U - 1) { // last blank transition. + gradients[b_t_u_d] = std::exp(g + betas[idx_b_t_u]) - std::exp(g); + } else if (t < T - 1 && d == blank) { + gradients[b_t_u_d] = std::exp(g + betas[idx_b_t_u]); + if (idx_b_tp1_u != -1) { + gradients[b_t_u_d] = gradients[b_t_u_d] - std::exp(g + betas[idx_b_tp1_u]); + } + } else if (u < U - 1 && d == targets[idxr2(bTgt, u)]) { + gradients[b_t_u_d] = std::exp(g + betas[idx_b_t_u]); + if (idx_b_t_up1 != -1) { + gradients[b_t_u_d] = gradients[b_t_u_d] - std::exp(g + betas[idx_b_t_up1]); + } + } else { + gradients[b_t_u_d] = std::exp(g + betas[idx_b_t_u]); + } + } else { // Non fused log softmax case + CAST_DTYPE g = cost + CAST_DTYPE(logits[b_t_u_d]); + if (d == blank && t == T - 1 && u == U - 1) { + gradients[b_t_u_d] = g + alphas[idx_b_t_u]; + } else if (t < T - 1 && d == blank) { + if (idx_b_tp1_u != -1) { + gradients[b_t_u_d] = g + alphas[idx_b_t_u] + betas[idx_b_tp1_u]; + } else { + gradients[b_t_u_d] = g + CAST_DTYPE(-INFINITY); + } + } else if (u < U - 1 && d == targets[idxr2(bTgt, u)]) { + if (idx_b_t_up1 != -1) { + gradients[b_t_u_d] = g + alphas[idx_b_t_u] + betas[idx_b_t_up1]; + } else { + gradients[b_t_u_d] = g + CAST_DTYPE(-INFINITY); + } + } else { + gradients[b_t_u_d] = g + CAST_DTYPE(-INFINITY); + } + gradients[b_t_u_d] = -std::exp(gradients[b_t_u_d]); + } + + if (clamp > 0) { + auto g = CAST_DTYPE(gradients[b_t_u_d]); + gradients[b_t_u_d] = math::min(g, clamp); + gradients[b_t_u_d] = math::max(g, -clamp); + } + } +} + +} // namespace rnnt +} // namespace torchaudio diff --git a/torchaudio/csrc/rnnt/gpu/math.cuh b/torchaudio/csrc/rnnt/gpu/math.cuh new file mode 100644 index 0000000000..a2eaabff93 --- /dev/null +++ b/torchaudio/csrc/rnnt/gpu/math.cuh @@ -0,0 +1,41 @@ +#pragma once + +#ifdef USE_CUDA + +#include + +#endif // USE_CUDA + +#include + +namespace torchaudio { +namespace rnnt { + +namespace math { + +template +FORCE_INLINE HOST_AND_DEVICE DTYPE max(DTYPE x, DTYPE y) { + if (x > y) return x; + else return y; +} + +template +FORCE_INLINE HOST_AND_DEVICE DTYPE min(DTYPE x, DTYPE y) { + if (x > y) return y; + else return x; +} + +// log_sum_exp +template +FORCE_INLINE HOST_AND_DEVICE DTYPE lse(DTYPE x, DTYPE y); + +template <> +FORCE_INLINE HOST_AND_DEVICE float lse(float x, float y) { + if (y > x) { return y + log1pf(expf(x - y)); } + else { return x + log1pf(expf(y-x)); } +} + +} + +} // namespace rnnt +} // namespace torchaudio diff --git a/torchaudio/csrc/rnnt/macros.cpp b/torchaudio/csrc/rnnt/macros.cpp new file mode 100644 index 0000000000..da6e5045bc --- /dev/null +++ b/torchaudio/csrc/rnnt/macros.cpp @@ -0,0 +1,21 @@ +#include + +#ifdef USE_GLOG +#else + +const char* ToString(level_t level) { + switch (level) { + case INFO: + return "INFO"; + case WARNING: + return "WARNING"; + case ERROR: + return "ERROR"; + case FATAL: + return "FATAL"; + default: + return "UNKNOWN"; + } +} + +#endif // USE_GLOG diff --git a/torchaudio/csrc/rnnt/macros.h b/torchaudio/csrc/rnnt/macros.h new file mode 100644 index 0000000000..84a8db24f0 --- /dev/null +++ b/torchaudio/csrc/rnnt/macros.h @@ -0,0 +1,47 @@ +#pragma once + +#ifdef USE_CUDA +#define WARP_SIZE 32 +#define MAX_THREADS_PER_BLOCK 1024 +#define REDUCE_THREADS 256 +#define HOST_AND_DEVICE __host__ __device__ +#define FORCE_INLINE __forceinline__ +#include +#include +#else +#define HOST_AND_DEVICE +#define FORCE_INLINE inline +#endif // USE_CUDA + +#ifdef USE_GLOG +#include +#else +#include +#include + +typedef enum { INFO = 0, WARNING = 1, ERROR = 2, FATAL = 3 } level_t; + +const char* ToString(level_t level); + +struct LOG { + LOG(const level_t& level) { + ::std::cerr << "LOG(" << ToString(level) << "): "; + } + ~LOG() { + ::std::cerr << ::std::endl; + } +}; + +template +LOG&& operator<<(LOG&& log, const T& object) { + ::std::cerr << object; + return ::std::move(log); +} + +#define DCHECK(x) +#define DCHECK_EQ(x, y) +#define DCHECK_NE(x, y) +#define CHECK(x) +#define CHECK_EQ(x, y) +#define CHECK_NE(x, y) +#endif // USE_GLOG diff --git a/torchaudio/csrc/rnnt/options.h b/torchaudio/csrc/rnnt/options.h new file mode 100644 index 0000000000..4debce21df --- /dev/null +++ b/torchaudio/csrc/rnnt/options.h @@ -0,0 +1,99 @@ +#pragma once + +//#include + +#ifdef USE_CUDA +#include +#endif // USE_CUDA + +#include +#include + +namespace torchaudio { +namespace rnnt { + +typedef struct Options { + // the device to compute transducer loss. + device_t device_; +#ifdef USE_CUDA + // the stream to launch kernels in when using GPU. + cudaStream_t stream_; +#endif + // The maximum number of threads that can be used. + int numThreads_; + + // the index for "blank". + int blank_; + // whether to backtrack the best path. + bool backtrack_; + // gradient clamp value. + float clamp_; + + // alignment restricted loss l buffer + int lBuffer_; + + // alignment restricted loss r buffer + int rBuffer_; + + // batch size = B. + int batchSize_; + + // Number of hypos per sample = H + int nHypos_; + + // the maximum length of src encodings = max_T. + int maxSrcLen_; + // the maximum length of tgt encodings = max_U. + int maxTgtLen_; + // num_targets = D. + int numTargets_; + + // whether to use sparse layout for ar-rnnt + bool sparse_; + + int sparseCells_; + + // if set to true, inputs are logits and gradients are + // fused with logsoftmax gradients. + // if set to false, log_softmax is computed outside of loss + // True by default + bool fusedLogSmax_; + + Options() + : device_(UNDEFINED), + numThreads_(0), + blank_(-1), + backtrack_(false), + clamp_(-1), // negative for disabling clamping by default. + lBuffer_(0), + rBuffer_(0), + batchSize_(0), + nHypos_(1), + maxSrcLen_(0), + maxTgtLen_(0), + numTargets_(0), + sparse_(false), + sparseCells_(0), + fusedLogSmax_(true) {} + + int BU() const { + return batchSize_ * maxTgtLen_ * nHypos_; + } + + int BTU() const { + return batchSize_ * maxSrcLen_ * maxTgtLen_ * nHypos_; + } + + friend std::ostream& operator<<(std::ostream& os, const Options& options) { + os << "Options(" + << "batchSize_=" << options.batchSize_ << ", " + << "maxSrcLen_=" << options.maxSrcLen_ << ", " + << "maxTgtLen_=" << options.maxTgtLen_ << ", " + << "numTargets_=" << options.numTargets_ << ")"; + + return os; + } +} Options; + +} // namespace rnnt +} // namespace torchaudio diff --git a/torchaudio/csrc/rnnt/transducer.h b/torchaudio/csrc/rnnt/transducer.h new file mode 100644 index 0000000000..8384fd5a9d --- /dev/null +++ b/torchaudio/csrc/rnnt/transducer.h @@ -0,0 +1,239 @@ +#pragma once + +#include +#include + +namespace torchaudio { +namespace rnnt { + +template +status_t Compute( + const Workspace& workspace, + const DTYPE* logits, + const int* targets, + const int* srcLengths, + const int* tgtLengths, + DTYPE* costs, + DTYPE* gradients = nullptr, + const int* wp_ends=nullptr) { + switch (workspace.GetOptions().device_) { + case CPU: { + status_t status = cpu::Compute( + /*workspace=*/workspace, + /*logits=*/logits, + /*targets=*/targets, + /*srcLengths=*/srcLengths, + /*tgtLengths=*/tgtLengths, + /*costs=*/costs, + /*gradients=*/gradients, + /*wp_ends =*/wp_ends); + return status; + } + case GPU: { + status_t status = gpu::Compute( + /*workspace=*/workspace, + /*logits=*/logits, + /*targets=*/targets, + /*srcLengths=*/srcLengths, + /*tgtLengths=*/tgtLengths, + /*costs=*/costs, + /*gradients=*/gradients, + /*wp_ends =*/wp_ends); + return status; + } + default: { + LOG(ERROR) << "unsupported workspace.GetOptions().device = " + << workspace.GetOptions().device_; + return FAILURE; + } + }; +} + +template +status_t ComputeSparse( + const Workspace& workspace, + const DTYPE* logits, + const int* targets, + const int* srcLengths, + const int* tgtLengths, + DTYPE* costs, + DTYPE* gradients = nullptr, + const int* wp_ends=nullptr, + const int* validRanges=nullptr, + const int* cellsPerSample=nullptr) { + switch (workspace.GetOptions().device_) { + case GPU: { + status_t status = gpu::ComputeSparse( + /*workspace=*/workspace, + /*logits=*/logits, + /*targets=*/targets, + /*srcLengths=*/srcLengths, + /*tgtLengths=*/tgtLengths, + /*costs=*/costs, + /*gradients=*/gradients, + /*wp_ends =*/wp_ends, + validRanges, + cellsPerSample); + return status; + } + default: { + LOG(ERROR) << "unsupported workspace.GetOptions().device = " + << workspace.GetOptions().device_; + return FAILURE; + } + }; +} + +template +status_t ComputeAlphas( + const Workspace& workspace, + const DTYPE* logits, + const int* targets, + const int* srcLengths, + const int* tgtLengths, + DTYPE* alphas, + const int* wp_ends=nullptr) { + switch (workspace.GetOptions().device_) { + case CPU: { + status_t status = cpu::ComputeAlphas( + /*workspace=*/workspace, + /*logits=*/logits, + /*targets=*/targets, + /*srcLengths=*/srcLengths, + /*tgtLengths=*/tgtLengths, + /*alphas=*/alphas, + /*wp_ends =*/wp_ends); + return status; + } + case GPU: { + status_t status = gpu::ComputeAlphas( + /*workspace=*/workspace, + /*logits=*/logits, + /*targets=*/targets, + /*srcLengths=*/srcLengths, + /*tgtLengths=*/tgtLengths, + /*costs=*/alphas, + /*wp_ends =*/wp_ends); + return status; + } + default: { + LOG(ERROR) << "unsupported workspace.GetOptions().device = " + << workspace.GetOptions().device_; + return FAILURE; + } + }; +} + +template +status_t ComputeAlphasSparse( + const Workspace& workspace, + const DTYPE* logits, + const int* targets, + const int* srcLengths, + const int* tgtLengths, + DTYPE* alphas, + const int* wp_ends=nullptr, + const int* validRanges=nullptr, + const int* cellsPerSample=nullptr) { + switch (workspace.GetOptions().device_) { + case GPU: { + status_t status = gpu::ComputeAlphasSparse( + /*workspace=*/workspace, + /*logits=*/logits, + /*targets=*/targets, + /*srcLengths=*/srcLengths, + /*tgtLengths=*/tgtLengths, + /*costs=*/alphas, + /*wp_ends =*/wp_ends, + validRanges, + cellsPerSample); + return status; + } + default: { + LOG(ERROR) << "unsupported workspace.GetOptions().device = " + << workspace.GetOptions().device_; + return FAILURE; + } + }; +} + +template +status_t ComputeBetas( + const Workspace& workspace, + const DTYPE* logits, + const int* targets, + const int* srcLengths, + const int* tgtLengths, + DTYPE* costs, + DTYPE* betas, + const int* wp_ends=nullptr) { + switch (workspace.GetOptions().device_) { + case CPU: { + status_t status = cpu::ComputeBetas( + /*workspace=*/workspace, + /*logits=*/logits, + /*targets=*/targets, + /*srcLengths=*/srcLengths, + /*tgtLengths=*/tgtLengths, + /*costs=*/costs, + /*betas=*/betas, + /*wp_ends =*/wp_ends); + return status; + } + case GPU: { + status_t status = gpu::ComputeBetas( + /*workspace=*/workspace, + /*logits=*/logits, + /*targets=*/targets, + /*srcLengths=*/srcLengths, + /*tgtLengths=*/tgtLengths, + /*costs=*/costs, + /*betas=*/betas, + /*wp_ends =*/wp_ends); + return status; + } + default: { + LOG(ERROR) << "unsupported workspace.GetOptions().device = " + << workspace.GetOptions().device_; + return FAILURE; + } + }; +} + +template +status_t ComputeBetasSparse( + const Workspace& workspace, + const DTYPE* logits, + const int* targets, + const int* srcLengths, + const int* tgtLengths, + DTYPE* costs, + DTYPE* betas, + const int* wp_ends=nullptr, + const int* validRanges=nullptr, + const int* cellsPerSample=nullptr) { + switch (workspace.GetOptions().device_) { + case GPU: { + status_t status = gpu::ComputeBetasSparse( + /*workspace=*/workspace, + /*logits=*/logits, + /*targets=*/targets, + /*srcLengths=*/srcLengths, + /*tgtLengths=*/tgtLengths, + /*costs=*/costs, + /*betas=*/betas, + /*wp_ends =*/wp_ends, + validRanges, + cellsPerSample); + return status; + } + default: { + LOG(ERROR) << "unsupported workspace.GetOptions().device = " + << workspace.GetOptions().device_; + return FAILURE; + } + }; +} + +} // namespace rnnt +} // namespace torchaudio diff --git a/torchaudio/csrc/rnnt/types.cpp b/torchaudio/csrc/rnnt/types.cpp new file mode 100644 index 0000000000..3c08a7eeb3 --- /dev/null +++ b/torchaudio/csrc/rnnt/types.cpp @@ -0,0 +1,41 @@ +#include + +namespace torchaudio { +namespace rnnt { + +const char* toString(status_t status) { + switch (status) { + case SUCCESS: + return "success"; + case FAILURE: + return "failure"; + case COMPUTE_DENOMINATOR_REDUCE_MAX_FAILED: + return "compute_denominator_reduce_max_failed"; + case COMPUTE_DENOMINATOR_REDUCE_SUM_FAILED: + return "compute_denominator_reduce_sum_failed"; + case COMPUTE_LOG_PROBS_FAILED: + return "compute_log_probs_failed"; + case COMPUTE_ALPHAS_BETAS_COSTS_FAILED: + return "compute_alphas_betas_costs_failed"; + case COMPUTE_GRADIENTS_FAILED: + return "compute_gradients_failed"; + default: + return "unknown"; + } +} + +const char* toString(device_t device) { + switch (device) { + case UNDEFINED: + return "undefined"; + case CPU: + return "cpu"; + case GPU: + return "gpu"; + default: + return "unknown"; + } +} + +} // namespace rnnt +} // namespace torchaudio diff --git a/torchaudio/csrc/rnnt/types.h b/torchaudio/csrc/rnnt/types.h new file mode 100644 index 0000000000..34d2998cff --- /dev/null +++ b/torchaudio/csrc/rnnt/types.h @@ -0,0 +1,23 @@ +#pragma once + +namespace torchaudio { +namespace rnnt { + +typedef enum { + SUCCESS = 0, + FAILURE = 1, + COMPUTE_DENOMINATOR_REDUCE_MAX_FAILED = 2, + COMPUTE_DENOMINATOR_REDUCE_SUM_FAILED = 3, + COMPUTE_LOG_PROBS_FAILED = 4, + COMPUTE_ALPHAS_BETAS_COSTS_FAILED = 5, + COMPUTE_GRADIENTS_FAILED = 6 +} status_t; + +typedef enum { UNDEFINED = 0, CPU = 1, GPU = 2 } device_t; + +const char* toString(status_t status); + +const char* toString(device_t device); + +} // namespace rnnt +} // namespace torchaudio diff --git a/torchaudio/csrc/rnnt/workspace.cpp b/torchaudio/csrc/rnnt/workspace.cpp new file mode 100644 index 0000000000..2c8d0f6ab1 --- /dev/null +++ b/torchaudio/csrc/rnnt/workspace.cpp @@ -0,0 +1,20 @@ +#include + +namespace torchaudio { +namespace rnnt { + +void IntWorkspace::ResetAlphaBetaCounters() { + if (data_ != nullptr && options_.device_ == GPU) { + cudaMemset( + GetPointerToAlphaCounters(), + 0, + ComputeSizeForAlphaCounters(options_) * sizeof(int)); + cudaMemset( + GetPointerToBetaCounters(), + 0, + ComputeSizeForBetaCounters(options_) * sizeof(int)); + } +} + +} // namespace rnnt +} // namespace torchaudio diff --git a/torchaudio/csrc/rnnt/workspace.h b/torchaudio/csrc/rnnt/workspace.h new file mode 100644 index 0000000000..243b836a93 --- /dev/null +++ b/torchaudio/csrc/rnnt/workspace.h @@ -0,0 +1,210 @@ +#pragma once + +#include +#include + +#include + +namespace torchaudio { +namespace rnnt { + +// Since CUDA has strict memory alignment, it's better to keep allocated memory +// blocks separate for different data types. + +// DtypeWorkspace holds a "view" of workspace for: +// 1. softmax denominators (in log form), size = B * max_T * max_U +// 2. log probibility pairs for blank and target, size = B * max_T * max_U +// 3. alphas, size = B * max_T * max_U +// 4. betas, size = B * max_T * max_U +template +class DtypeWorkspace { + public: + DtypeWorkspace() : options_(), size_(0), data_(nullptr) {} + DtypeWorkspace(const Options& options, DTYPE* data, int size) + : DtypeWorkspace() { + Reset(options, data, size); + } + ~DtypeWorkspace() {} + + static int ComputeSizeFromOptions(const Options& options) { + CHECK_NE(options.device_, UNDEFINED); + return ComputeSizeForDenominators(options) + + ComputeSizeForLogProbs(options) + ComputeSizeForAlphas(options) + + ComputeSizeForBetas(options); + } + + void Free(); + void Reset(const Options& options, DTYPE* data, int size) { + int needed_size = ComputeSizeFromOptions(options); + CHECK_LE(needed_size, size); + options_ = options; + data_ = data; + size_ = size; + } + int Size() const { + return size_; + } + + DTYPE* GetPointerToDenominators() const { + return data_; + } + DTYPE* GetPointerToLogProbs() const { + return GetPointerToDenominators() + ComputeSizeForDenominators(options_); + } + DTYPE* GetPointerToAlphas() const { + return GetPointerToLogProbs() + ComputeSizeForLogProbs(options_); + } + DTYPE* GetPointerToBetas() const { + return GetPointerToAlphas() + ComputeSizeForAlphas(options_); + } + + private: + static int ComputeSizeForDenominators(const Options& options) { // B * T * U + return options.sparse_ ? options.sparseCells_ : options.BTU(); + } + + static int ComputeSizeForLogProbs(const Options& options) { // B * T * U * 2 + return options.sparse_ ? options.sparseCells_ * 2 : options.BTU() * 2; + } + + static int ComputeSizeForAlphas(const Options& options) { // B * T * U + return options.sparse_ ? options.sparseCells_ : options.BTU(); + } + + static int ComputeSizeForBetas(const Options& options) { // B * T * U + return options.sparse_ ? options.sparseCells_ : options.BTU(); + } + + Options options_; + int size_; // number of elements in allocated memory. + DTYPE* data_; // pointer to the allocated memory. +}; + +// IntWorkspace holds a "view" of workspace for: +// 1. alpha counters, size = B * max_U +// 2. beta counters, size = B * max_U +class IntWorkspace { + public: + IntWorkspace() : options_(), size_(0), data_(nullptr) {} + IntWorkspace(const Options& options, int* data, int size) : IntWorkspace() { + Reset(options, data, size); + } + ~IntWorkspace() {} + + static int ComputeSizeFromOptions(const Options& options) { + return ComputeSizeForAlphaCounters(options) + + ComputeSizeForBetaCounters(options); + } + + void Reset(const Options& options, int* data, int size) { + int needed_size = ComputeSizeFromOptions(options); + //CHECK_LE(needed_size, size); + options_ = options; + data_ = data; + size_ = size; + ResetAlphaBetaCounters(); + } + int Size() const { + return size_; + } + + int* GetPointerToAlphaCounters() const { + CHECK_EQ(options_.device_, GPU); + return data_; + } + int* GetPointerToBetaCounters() const { + CHECK_EQ(options_.device_, GPU); + return GetPointerToAlphaCounters() + ComputeSizeForAlphaCounters(options_); + } + + private: + void ResetAlphaBetaCounters(); + + static int ComputeSizeForAlphaCounters(const Options& options) { // B * U +#ifdef USE_CUDA + if (options.device_ == GPU) { + return options.BU(); + } else { + return 0; + } +#else + return 0; +#endif // USE_CUDA + } + static int ComputeSizeForBetaCounters(const Options& options) { // B * U +#ifdef USE_CUDA + if (options.device_ == GPU) { + return options.BU(); + } else { + return 0; + } +#else + return 0; +#endif // USE_CUDA + } + + Options options_; + int size_; // number of elements in allocated memory. + int* data_; // pointer to the allocated memory. +}; + +// Workspace holds: +// 1. DtypeWorkspace +// 2. IntWorkspace +template +class Workspace { + public: + Workspace() : options_(), dtype_workspace_(), int_workspace_() {} + Workspace( + const Options& options, + DTYPE* dtype_data, + int dtype_size, + int* int_data, + int int_size) + : Workspace() { + Reset(options, dtype_data, dtype_size, int_data, int_size); + } + ~Workspace() {} + + void Reset( + const Options& options, + DTYPE* dtype_data, + int dtype_size, + int* int_data, + int int_size) { + options_ = options; + dtype_workspace_.Reset(options_, dtype_data, dtype_size); + int_workspace_.Reset(options_, int_data, int_size); + } + + const Options& GetOptions() const { + return options_; + } + + DTYPE* GetPointerToDenominators() const { + return dtype_workspace_.GetPointerToDenominators(); + } + DTYPE* GetPointerToLogProbs() const { + return dtype_workspace_.GetPointerToLogProbs(); + } + DTYPE* GetPointerToAlphas() const { + return dtype_workspace_.GetPointerToAlphas(); + } + DTYPE* GetPointerToBetas() const { + return dtype_workspace_.GetPointerToBetas(); + } + int* GetPointerToAlphaCounters() const { + return int_workspace_.GetPointerToAlphaCounters(); + } + int* GetPointerToBetaCounters() const { + return int_workspace_.GetPointerToBetaCounters(); + } + + private: + Options options_; + DtypeWorkspace dtype_workspace_; + IntWorkspace int_workspace_; +}; + +} // namespace rnnt +} // namespace torchaudio diff --git a/torchaudio/prototype/rnnt_loss.py b/torchaudio/prototype/rnnt_loss.py new file mode 100644 index 0000000000..0839290e0a --- /dev/null +++ b/torchaudio/prototype/rnnt_loss.py @@ -0,0 +1,520 @@ +import torch + +__all__ = [ + "RNNTLoss", + "rnnt_loss", +] + + +def _rnnt_loss_alphas( + logits, + targets, + logit_lengths, + target_lengths, + blank=-1, + clamp=-1, + wordpiece_ends=None, + left_buffer=0, + right_buffer=0, + sparse=False, + valid_ranges=None, + cells_per_sample=None, +): + """ + Compute alphas for RNN transducer loss. + + See documentation for RNNTLoss + """ + targets = targets.to(device=logits.device) + logit_lengths = logit_lengths.to(device=logits.device) + target_lengths = target_lengths.to(device=logits.device) + if wordpiece_ends is not None: + wordpiece_ends = wordpiece_ends.to(device=logits.device) + + # make sure all int tensors are of type int32. + targets = targets.int() + logit_lengths = logit_lengths.int() + target_lengths = target_lengths.int() + if not sparse: + return torch.ops.torchaudio.rnnt_loss_alphas( + logits, + targets, + logit_lengths, + target_lengths, + blank, + clamp, + wordpiece_ends, + left_buffer, + right_buffer, + ) + else: + try: + return torch.ops.torchaudio.rnnt_loss_alphas_sparse( + logits, + targets, + logit_lengths, + target_lengths, + blank, + clamp, + torch.max(logit_lengths).item(), + torch.max(target_lengths).item() + 1, + wordpiece_ends, + left_buffer, + right_buffer, + valid_ranges, + cells_per_sample, + ) + except RuntimeError: + raise RuntimeError("sparse is only supported on GPU with torchaudio compiled with GPU support") + + +def _rnnt_loss_betas( + logits, + targets, + logit_lengths, + target_lengths, + blank=-1, + clamp=-1, + wordpiece_ends=None, + left_buffer=0, + right_buffer=0, + sparse=False, + valid_ranges=None, + cells_per_sample=None, +): + """ + Compute betas for RNN transducer loss + + See documentation for RNNTLoss + """ + targets = targets.to(device=logits.device) + logit_lengths = logit_lengths.to(device=logits.device) + target_lengths = target_lengths.to(device=logits.device) + if wordpiece_ends is not None: + wordpiece_ends = wordpiece_ends.to(device=logits.device) + + # make sure all int tensors are of type int32. + targets = targets.int() + logit_lengths = logit_lengths.int() + target_lengths = target_lengths.int() + if not sparse: + return torch.ops.torchaudio.rnnt_loss_betas( + logits, + targets, + logit_lengths, + target_lengths, + blank, + clamp, + wordpiece_ends, + left_buffer, + right_buffer, + ) + else: + try: + return torch.ops.torchaudio.rnnt_loss_betas_sparse( + logits, + targets, + logit_lengths, + target_lengths, + blank, + clamp, + torch.max(logit_lengths).item(), + torch.max(target_lengths).item() + 1, + wordpiece_ends, + left_buffer, + right_buffer, + valid_ranges, + cells_per_sample, + ) + except RuntimeError: + raise RuntimeError("sparse is only supported on GPU with torchaudio compiled with GPU support") + + +class _RNNT(torch.autograd.Function): + @staticmethod + def forward( + ctx, + logits, + targets, + logit_lengths, + target_lengths, + blank=-1, + clamp=-1, + runtime_check=False, + wordpiece_ends=None, + left_buffer=0, + right_buffer=0, + sparse=False, + valid_ranges=None, + cells_per_sample=None, + fused_log_softmax=True, + reuse_logits_for_grads=True, + ): + """ + See documentation for RNNTLoss + """ + + # move everything to the same device. + targets = targets.to(device=logits.device) + logit_lengths = logit_lengths.to(device=logits.device) + target_lengths = target_lengths.to(device=logits.device) + if wordpiece_ends is not None: + wordpiece_ends = wordpiece_ends.to(device=logits.device) + if valid_ranges is not None: + valid_ranges = valid_ranges.to(device=logits.device) + if cells_per_sample is not None: + cells_per_sample = cells_per_sample.to(device=logits.device) + + # make sure all int tensors are of type int32. + targets = targets.int() + logit_lengths = logit_lengths.int() + target_lengths = target_lengths.int() + + if blank < 0: # reinterpret blank index if blank < 0. + blank = logits.shape[-1] + blank + + if runtime_check: + check_inputs( + logits=logits, + targets=targets, + logit_lengths=logit_lengths, + target_lengths=target_lengths, + blank=blank, + ) + if sparse: + try: + rnnt_loss_sparse = torch.ops.torchaudio.rnnt_loss_sparse + except RuntimeError: + raise RuntimeError("sparse is only supported on GPU with torchaudio compiled with GPU support") + + max_T = torch.max(logit_lengths).item() # note: not used for indexing + max_U = targets.shape[1] + 1 # used for indexing, e.g. wordpiece_ends + assert max_U >= torch.max(target_lengths).item() + 1 + assert max_U == wordpiece_ends.shape[1] and max_U == valid_ranges.shape[1] + costs, gradients = rnnt_loss_sparse( + logits=logits, + targets=targets, + src_lengths=logit_lengths, + tgt_lengths=target_lengths, + blank=blank, + clamp=clamp, + wp_ends=wordpiece_ends, + l_buffer=left_buffer, + r_buffer=right_buffer, + max_T=max_T, + max_U=max_U, + valid_ranges=valid_ranges, + cells_per_sample=cells_per_sample, + fused_log_smax=fused_log_softmax, + reuse_logits_for_grads=reuse_logits_for_grads, + ) + ctx.cells_per_sample = cells_per_sample + else: + costs, gradients = torch.ops.torchaudio.rnnt_loss( + logits=logits, + targets=targets, + src_lengths=logit_lengths, + tgt_lengths=target_lengths, + blank=blank, + clamp=clamp, + wp_ends=wordpiece_ends, + l_buffer=left_buffer, + r_buffer=right_buffer, + fused_log_smax=fused_log_softmax, + reuse_logits_for_grads=reuse_logits_for_grads, + ) + + ctx.grads = gradients + ctx.sparse = sparse + + return costs + + @staticmethod + def backward(ctx, output_gradients): + if ctx.sparse: + output_gradients = output_gradients.view(-1, 1).to(ctx.grads) + offset = 0 + count = 0 + for ncells in ctx.cells_per_sample: + ctx.grads[offset : offset + ncells, :].mul_(output_gradients[count]) + offset += ncells + count += 1 + else: + output_gradients = output_gradients.view(-1, 1, 1, 1).to(ctx.grads) + ctx.grads.mul_(output_gradients).to(ctx.grads) + + return ( + ctx.grads, # logits + None, # targets + None, # logit_lengths + None, # target_lengths + None, # blank + None, # clamp + None, # runtime_check + None, # wordpiece_ends + None, # left_buffer + None, # right_buffer + None, # sparse + None, # valid_ranges + None, # cells_per_sample + None, # fused_log_softmax + None, # reuse_logits_for_grads + ) + + +def rnnt_loss( + logits, + targets, + logit_lengths, + target_lengths, + blank=-1, + clamp=-1, + runtime_check=False, + wordpiece_ends=None, + left_buffer=0, + right_buffer=0, + sparse=False, + valid_ranges=None, + cells_per_sample=None, + fused_log_softmax=True, + reuse_logits_for_grads=True, +): + """ + Compute the RNN Transducer Loss. + + The RNN Transducer loss (`Graves 2012 `__) extends the CTC loss by defining + a distribution over output sequences of all lengths, and by jointly modelling both input-output and output-output + dependencies. + + Args: + logits (Tensor): Tensor of dimension (batch, time, target, class) containing output from joiner + targets (Tensor): Tensor of dimension (batch, max target length) containing targets with zero padded + logit_lengths (Tensor): Tensor of dimension (batch) containing lengths of each sequence from encoder + target_lengths (Tensor): Tensor of dimension (batch) containing lengths of targets for each sequence + blank (int, opt): blank label (Default: ``-1``) + clamp (float): clamp for gradients (Default: ``-1``) + runtime_check (bool): whether to do sanity check during runtime. (Default: ``False``) + wordpiece_ends (Tensor): Tensor of dimension (batch, target) containing the end frames of targets + for each sequence (including bos end_frame = 0) (Default: ``None``) + left_buffer (int): left buffer frames used for alignment restricted RNNT loss. + Loss will not be imposed on frames smaller than wordpiece_end - left_buffer. (Default: ``0``) + right_buffer (int): right buffer frames used for alignment restricted RNNT loss. + Loss will not be imposed on frames greater than wordpiece_end + right_buffer. (Default: ``0``) + sparse (bool): set to true for sparse alignment restricted RNNT. (Default: ``False``) + valid_ranges (Tensor): Tensor of dimension (batch, target, 2) containing valid ranges for sparse AR-RNNT + (Default: ``None``) + cells_per_sample (Tensor): Tensor of dimension (batch) containing total valid cells for each (Default: ``None``) + sample while doing sparse AR-RNNT (Default: ``None``) + fused_log_smax (bool): set to False if calling log_softmax outside loss (Default: ``True``) + reuse_logits_for_grads (bool): whether to save memory by reusing logits memory for grads (Default: ``True``) + """ + if not fused_log_softmax: + logits = torch.nn.functional.log_softmax(logits, dim=-1) + reuse_logits_for_grads = ( + False # softmax needs the original logits value + ) + + cost = _RNNT.apply( + logits, + targets, + logit_lengths, + target_lengths, + blank, + clamp, + runtime_check, + wordpiece_ends, + left_buffer, + right_buffer, + sparse, + valid_ranges, + cells_per_sample, + fused_log_softmax, + reuse_logits_for_grads, + ) + return cost + + +class RNNTLoss(torch.nn.Module): + """ + Compute the RNN Transducer Loss. + + The RNN Transducer loss (`Graves 2012 `__) extends the CTC loss by defining + a distribution over output sequences of all lengths, and by jointly modelling both input-output and output-output + dependencies. + + Args: + blank (int, opt): blank label (Default: ``-1``) + clamp (float): clamp for gradients (Default: ``-1``) + runtime_check (bool): whether to do sanity check during runtime. (Default: ``False``) + left_buffer (int): left buffer frames used for alignment restricted RNNT loss. + Loss will not be imposed on frames smaller than wordpiece_end - left_buffer. (Default: ``0``) + right_buffer (int): right buffer frames used for alignment restricted RNNT loss. + Loss will not be imposed on frames greater than wordpiece_end + right_buffer. (Default: ``0``) + sparse (bool): set to true for sparse alignment restricted RNNT. (Default: ``False``) + fused_log_smax (bool): set to False if calling log_softmax outside loss (Default: ``True``) + reuse_logits_for_grads (bool): whether to save memory by reusing logits memory for grads (Default: ``True``) + """ + + def __init__( + self, + blank=-1, + clamp=-1, + runtime_check=False, + left_buffer=0, + right_buffer=0, + sparse=False, + fused_log_softmax=True, + reuse_logits_for_grads=True, + ): + super().__init__() + self.blank = blank + self.clamp = clamp + self.runtime_check = runtime_check + self.left_buffer = left_buffer + self.right_buffer = right_buffer + self.sparse = sparse + self.fused_log_softmax = fused_log_softmax + self.reuse_logits_for_grads = reuse_logits_for_grads + + def forward( + self, + logits, + targets, + logit_lengths, + target_lengths, + wordpiece_ends=None, + valid_ranges=None, + cells_per_sample=None, + left_buffer=None, + right_buffer=None, + ): + """ + Args: + logits (Tensor): Tensor of dimension (batch, time, target, class) containing output from joiner + targets (Tensor): Tensor of dimension (batch, max target length) containing targets with zero padded + logit_lengths (Tensor): Tensor of dimension (batch) containing lengths of each sequence from encoder + target_lengths (Tensor): Tensor of dimension (batch) containing lengths of targets for each sequence + wordpiece_ends (Tensor): Tensor of dimension (batch, target) containing the end frames of targets + for each sequence (including bos end_frame = 0) (Default: ``None``) + valid_ranges (Tensor): Tensor of dimension (batch, target, 2) containing valid ranges for sparse AR-RNNT + (Default: ``None``) + cells_per_sample (Tensor): Tensor of dimension (batch) containing total valid cells for each + sample while doing sparse AR-RNNT (Default: ``None``) + left_buffer (int): left buffer frames used for alignment restricted RNNT loss. + Loss will not be imposed on frames smaller than wordpiece_end - left_buffer. (Default: ``None``) + right_buffer (int): right buffer frames used for alignment restricted RNNT loss. + Loss will not be imposed on frames greater than wordpiece_end + right_buffer. (Default: ``None``) + """ + # left_buffer / right_buffer is passed in forward, + # when we use dataset or sample specific left/right buffer + # self.left_buffer / right_buffer is used by default, or + # to preserve backward compatibility + if left_buffer is None: + left_buffer = self.left_buffer + if right_buffer is None: + right_buffer = self.right_buffer + + return rnnt_loss( + logits, + targets, + logit_lengths, + target_lengths, + self.blank, + self.clamp, + self.runtime_check, + wordpiece_ends, + left_buffer, + right_buffer, + self.sparse, + valid_ranges, + cells_per_sample, + self.fused_log_softmax, + self.reuse_logits_for_grads, + ) + + +def check_type(var, t, name): + if var.dtype is not t: + raise TypeError("{} must be {}".format(name, t)) + + +def check_contiguous(var, name): + if not var.is_contiguous(): + raise ValueError("{} must be contiguous".format(name)) + + +def check_dim(var, dim, name): + if len(var.shape) != dim: + raise ValueError("{} must be {}D".format(name, dim)) + + +def check_equal(var1, name1, var2, name2): + if var1 != var2: + raise ValueError( + "`{}` ({}) must equal to ".format(name1, var1) + + "`{}` ({})".format(name2, var2) + ) + + +def check_device(var1, name1, var2, name2): + if var1.device != var2.device: + raise ValueError( + "`{}` ({}) must be on the same ".format(name1, var1.device.type) + + "device as `{}` ({})".format(name2, var2.device.type) + ) + + +def check_inputs(logits, targets, logit_lengths, target_lengths, blank): + check_device(logits, "logits", targets, "targets") + check_device(logits, "logits", targets, "logit_lengths") + check_device(logits, "logits", targets, "target_lengths") + + check_type(logits, torch.float32, "logits") + check_type(targets, torch.int32, "targets") + check_type(logit_lengths, torch.int32, "logit_lengths") + check_type(target_lengths, torch.int32, "target_lengths") + + check_contiguous(logits, "logits") + check_contiguous(targets, "targets") + check_contiguous(target_lengths, "target_lengths") + check_contiguous(logit_lengths, "logit_lengths") + + check_dim(logits, 4, "logits") + check_dim(targets, 2, "targets") + check_dim(logit_lengths, 1, "logit_lengths") + check_dim(target_lengths, 1, "target_lengths") + + check_equal( + logit_lengths.shape[0], "logit_lengths.shape[0]", logits.shape[0], "logits.shape[0]" + ) + check_equal( + target_lengths.shape[0], "target_lengths.shape[0]", logits.shape[0], "logits.shape[0]" + ) + check_equal( + targets.shape[0], "targets.shape[0]", logits.shape[0], "logits.shape[0]" + ) + check_equal( + targets.shape[1], + "targets.shape[1]", + torch.max(target_lengths), + "torch.max(target_lengths)", + ) + check_equal( + logits.shape[1], + "logits.shape[1]", + torch.max(logit_lengths), + "torch.max(logit_lengths)", + ) + check_equal( + logits.shape[2], + "logits.shape[2]", + torch.max(target_lengths) + 1, + "torch.max(target_lengths) + 1", + ) + + if blank < 0 or blank >= logits.shape[-1]: + raise ValueError( + "blank ({}) must be within [0, logits.shape[-1]={})".format( + blank, logits.shape[-1] + ) + ) From d72165b08cd2d72c61ef5f6e47c1cccbc072ffbb Mon Sep 17 00:00:00 2001 From: Caroline Chen Date: Fri, 30 Apr 2021 12:53:14 -0700 Subject: [PATCH 44/73] Remove unused file Summary: `kernels.h` was copied into both cpu and gpu folders previously, but it is not actually necessary for cpu rnnt Reviewed By: vincentqb Differential Revision: D28072209 fbshipit-source-id: 74427ee7d0c81aafdb82d1151035e89e4faec359 --- torchaudio/csrc/rnnt/cpu/kernels.h | 242 ----------------------------- 1 file changed, 242 deletions(-) delete mode 100644 torchaudio/csrc/rnnt/cpu/kernels.h diff --git a/torchaudio/csrc/rnnt/cpu/kernels.h b/torchaudio/csrc/rnnt/cpu/kernels.h deleted file mode 100644 index 66ffb6657e..0000000000 --- a/torchaudio/csrc/rnnt/cpu/kernels.h +++ /dev/null @@ -1,242 +0,0 @@ -#pragma once - -#include - -#include -#include - -namespace torchaudio { -namespace rnnt { - - -template -FORCE_INLINE HOST_AND_DEVICE void ComputeLogProbsSparseElement( - int bTgt, - int t, - int u, - int maxT, - int maxU, - int numTargets, - int blank, - const DTYPE* logits, - const int* targets, - const int* srcLengths, - const int* tgtLengths, - const CAST_DTYPE* denominators, - CAST_DTYPE* logProbs, - const int* wpEnds, - const int* validRanges=nullptr, - const int* cellsPerSample=nullptr, - int H=1, - bool fusedLogSmax=true) { - - const int& D = numTargets; - - const int bSrc = bTgt / H; - const int T = srcLengths[bSrc]; - const int U = tgtLengths[bTgt] + 1; - - if (t >= T || u >= U) { // out of boundary. - return; - } - const int* validRangesB = validRanges + (maxU*2) * bTgt; - int start = validRangesB[2*u]; - int end = validRangesB[2*u + 1]; - - // out of boundary for alignment restriction condition - if (t < start || t > end) { - return; - } - SparseIndexer idxr(maxU, tgtLengths, validRanges, cellsPerSample); - int idx = idxr(bTgt, t, u); - logProbs[(idx << 1) + LOG_PROBS_SKIP_IDX] = - CAST_DTYPE(logits[idx * D + blank]) - denominators[idx]; - - if (!fusedLogSmax) { - logProbs[(idx << 1) + LOG_PROBS_SKIP_IDX] = - CAST_DTYPE(logits[idx * D + blank]); - } - - if (u < U - 1) { - // emit: log_prob(b, t, u).emit() = logits(b, t, u, tgt[u]) - denom(b, t, u). - int target = targets[Indexer2D(maxU - 1)(bTgt, u)]; - logProbs[(idx << 1) + LOG_PROBS_EMIT_IDX] = - CAST_DTYPE(logits[idx * D + target]) - denominators[idx]; - - if (!fusedLogSmax) { - logProbs[(idx << 1) + LOG_PROBS_EMIT_IDX] = - CAST_DTYPE(logits[idx * D + target]); - } - } -} - - -template -HOST_AND_DEVICE void ComputeGradientsElement( - int bTgt, - int t, - int u, - int maxSrcLen, - int maxTgtLen, - int numTargets, - int blank, - CAST_DTYPE clamp, - const DTYPE* logits, - const int* targets, - const int* srcLengths, - const int* tgtLengths, - const CAST_DTYPE* denominators, - const CAST_DTYPE* alphas, - const CAST_DTYPE* betas, - DTYPE* gradients, - bool monotonic = false, - bool sparse = false, - const int* validRanges = nullptr, - const int* cellsPerSample = nullptr, - int H = 1, - bool fusedLogSmax = true) { - - const int& maxT = maxSrcLen; - const int& maxU = maxTgtLen; - const int& D = numTargets; - - const int bSrc = bTgt / H; - const int T = srcLengths[bSrc]; - const int U = tgtLengths[bTgt] + 1; - - if (t >= T || u >= U) { // out of boundary. - if (sparse) { - // no extra elements needs to be set to 0 - return; - } else if (gradients == logits && t < maxT && u < maxU) { - // gradients and logits are pointing to the same memory location - Indexer3D idxr3(maxT, maxU); - int idx_b_t_u_zero = idxr3(bTgt, t, u); - if (idx_b_t_u_zero != -1 ) { - int start = idx_b_t_u_zero * D; - for (int b_t_u_d = start; b_t_u_d < start + D; ++b_t_u_d) { - gradients[b_t_u_d] = 0; - } - } - } - return; - } - - int costIdx; - if (!sparse) { - costIdx = bTgt * maxT * maxU; - } else { - SparseIndexer idxr(maxU, tgtLengths, validRanges, cellsPerSample); - costIdx = idxr(bTgt, 0, 0); - } - CAST_DTYPE cost = -(betas[costIdx]); - - - Indexer2D idxr2(maxU - 1); - - int idx_b_t_u, idx_b_t_up1, idx_b_tp1_u, idx_b_tp1_up1; - if (sparse) { - SparseIndexer idxr(maxU, tgtLengths, validRanges, cellsPerSample); - idx_b_t_u = idxr(bTgt, t, u); - idx_b_t_up1 = idxr(bTgt, t, u+1); - idx_b_tp1_u = idxr(bTgt, t+1, u); - idx_b_tp1_up1 = idxr(bTgt, t+1, u+1); - } else { - Indexer3D idxr3(maxT, maxU); - idx_b_t_u = idxr3(bTgt, t, u); - idx_b_t_up1 = idxr3(bTgt, t, u+1); - idx_b_tp1_u = idxr3(bTgt, t+1, u); - idx_b_tp1_up1 = idxr3(bTgt, t+1, u+1); - } - - if (idx_b_t_u == -1 ) { - return; - } - - if (isinf(cost) || isnan(cost)) { - for (int d = 0; d < D; ++d) { - int b_t_u_d = idx_b_t_u * D + d; - gradients[b_t_u_d] = 0; - } - return; - } - - CAST_DTYPE c = alphas[idx_b_t_u] + cost - denominators[idx_b_t_u]; - for (int d = 0; d < D; ++d) { - int b_t_u_d = idx_b_t_u * D + d; - CAST_DTYPE g = CAST_DTYPE(logits[b_t_u_d]) + c; - - if (!monotonic) { - if (fusedLogSmax) { - if (d == blank && t == T - 1 && u == U - 1) { // last blank transition. - gradients[b_t_u_d] = std::exp(g + betas[idx_b_t_u]) - std::exp(g); - } else if (t < T - 1 && d == blank) { - gradients[b_t_u_d] = std::exp(g + betas[idx_b_t_u]); - if (idx_b_tp1_u != -1) { - gradients[b_t_u_d] = gradients[b_t_u_d] - std::exp(g + betas[idx_b_tp1_u]); - } - - } else if (u < U - 1 && d == targets[idxr2(bTgt, u)]) { - gradients[b_t_u_d] = std::exp(g + betas[idx_b_t_u]); - if (idx_b_t_up1 != -1) { - gradients[b_t_u_d] = gradients[b_t_u_d] - std::exp(g + betas[idx_b_t_up1]); - } - } else { - gradients[b_t_u_d] = std::exp(g + betas[idx_b_t_u]); - } - } - else { // Non fused log softmax case - CAST_DTYPE g = cost + CAST_DTYPE(logits[b_t_u_d]); - if (d == blank && t == T - 1 && u == U - 1) { - gradients[b_t_u_d] = g + alphas[idx_b_t_u]; - } else if (t < T - 1 && d == blank) { - if (idx_b_tp1_u != -1) { - gradients[b_t_u_d] = g + alphas[idx_b_t_u] + betas[idx_b_tp1_u]; - } else { - gradients[b_t_u_d] = g + CAST_DTYPE(-INFINITY); - } - } else if (u < U - 1 && d == targets[idxr2(bTgt, u)]) { - - if (idx_b_t_up1 != -1) { - gradients[b_t_u_d] = g + alphas[idx_b_t_u] + betas[idx_b_t_up1]; - } else { - gradients[b_t_u_d] = g + CAST_DTYPE(-INFINITY); - } - - } - else { - gradients[b_t_u_d] = g + CAST_DTYPE(-INFINITY); - } - gradients[b_t_u_d] = -std::exp(gradients[b_t_u_d]); - } - } else { // Monotonic RNNT case - CAST_DTYPE g = cost + CAST_DTYPE(logits[b_t_u_d]); - if (d == blank && t == T - 1 && u == U - 1) { // last blank transition. - g = g + alphas[idx_b_t_u]; - } else if (t < T - 1 && d == blank) { - g = g + alphas[idx_b_t_u]; - if (idx_b_tp1_u != -1) { - g = g + betas[idx_b_tp1_u]; - } - } else if (u < U - 1 && t < T - 1 && d == targets[idxr2(bTgt, u)]) { - g = g + alphas[idx_b_t_u]; - if (idx_b_tp1_up1 != -1) { - g = g + betas[idx_b_tp1_up1]; - } - } - else { - g = g + CAST_DTYPE(-INFINITY); - } - gradients[b_t_u_d] = -std::exp(g); - } // end of monotonic else - - if (clamp > 0) { - auto g = CAST_DTYPE(gradients[b_t_u_d]); - gradients[b_t_u_d] = math::min(g, clamp); - gradients[b_t_u_d] = math::max(g, -clamp); - } - } -} - -} // namespace rnnt -} // namespace torchaudio From c3ff2cd445d40419353302d39c0ef2719a18febe Mon Sep 17 00:00:00 2001 From: Caroline Chen Date: Fri, 30 Apr 2021 12:53:14 -0700 Subject: [PATCH 45/73] Remove sparse support for A-R RNNT Summary: sparse support is a layer on top of alignment-restriction rnnt, but we do not wish to release either of them initially this diff removes sparse functionality along with sparse-related parameters (`valid_ranges`, `cells_per_sample`) Reviewed By: vincentqb Differential Revision: D28072213 fbshipit-source-id: 9a88368af1a730b4167ffb9cebdd5eddcc6e4bf9 --- .../rnnt/rnnt_loss_impl.py | 235 ++--------- test/torchaudio_unittest/rnnt/utils.py | 77 +--- .../csrc/rnnt/cpu/alignment_restrictions.h | 55 --- torchaudio/csrc/rnnt/cpu/kernel_utils.h | 58 --- torchaudio/csrc/rnnt/gpu/compute.cu | 130 ------ torchaudio/csrc/rnnt/gpu/compute_alphas.cu | 89 ---- torchaudio/csrc/rnnt/gpu/compute_betas.cu | 94 ----- .../rnnt/gpu/gpu_alignment_restrictions.cuh | 97 +---- torchaudio/csrc/rnnt/gpu/gpu_kernels.cuh | 15 - torchaudio/csrc/rnnt/gpu/gpu_transducer.h | 381 ------------------ torchaudio/csrc/rnnt/gpu/kernel_utils.h | 58 --- torchaudio/csrc/rnnt/gpu/kernels.h | 96 +---- torchaudio/csrc/rnnt/options.h | 7 - torchaudio/csrc/rnnt/transducer.h | 103 ----- torchaudio/csrc/rnnt/workspace.h | 8 +- torchaudio/prototype/rnnt_loss.py | 195 ++------- 16 files changed, 107 insertions(+), 1591 deletions(-) diff --git a/test/torchaudio_unittest/rnnt/rnnt_loss_impl.py b/test/torchaudio_unittest/rnnt/rnnt_loss_impl.py index 6b6e4d1d20..dcab6def6f 100644 --- a/test/torchaudio_unittest/rnnt/rnnt_loss_impl.py +++ b/test/torchaudio_unittest/rnnt/rnnt_loss_impl.py @@ -9,7 +9,6 @@ from .numpy_transducer import _NumpyTransducer from .utils import ( - assert_sparse_all_close, compute_with_numpy_transducer, compute_with_pytorch_transducer, get_B1_T10_U3_D4_data, @@ -34,25 +33,20 @@ def _test_costs_and_gradients( data=data, reuse_logits_for_grads=reuse_logits_for_grads ) np.testing.assert_allclose(costs, ref_costs, atol=atol, rtol=rtol) - if "logits_sparse" in data: - assert_sparse_all_close( - data, gradients, ref_gradients, atol=atol, rtol=rtol - ) - else: - self.assertEqual(logits_shape, gradients.shape) - if not np.allclose(gradients, ref_gradients, atol=atol, rtol=rtol): - for b in range(len(gradients)): - T = data["logit_lengths"][b] - U = data["target_lengths"][b] - for t in range(gradients.shape[1]): - for u in range(gradients.shape[2]): - np.testing.assert_allclose( - gradients[b, t, u], - ref_gradients[b, t, u], - atol=atol, - rtol=rtol, - err_msg=f"failed on b={b}, t={t}/T={T}, u={u}/U={U}", - ) + self.assertEqual(logits_shape, gradients.shape) + if not np.allclose(gradients, ref_gradients, atol=atol, rtol=rtol): + for b in range(len(gradients)): + T = data["logit_lengths"][b] + U = data["target_lengths"][b] + for t in range(gradients.shape[1]): + for u in range(gradients.shape[2]): + np.testing.assert_allclose( + gradients[b, t, u], + ref_gradients[b, t, u], + atol=atol, + rtol=rtol, + err_msg=f"failed on b={b}, t={t}/T={T}, u={u}/U={U}", + ) def test_basic_backward(self): rnnt_loss = RNNTLoss() @@ -317,42 +311,36 @@ def _test_costs_and_gradients( data=data, reuse_logits_for_grads=reuse_logits_for_grads ) np.testing.assert_allclose(costs, ref_costs, atol=atol, rtol=rtol) - if "logits_sparse" in data: - assert_sparse_all_close( - data, gradients, ref_gradients, atol=atol, rtol=rtol - ) - else: - self.assertEqual(logits_shape, gradients.shape) - if not np.allclose(gradients, ref_gradients, atol=atol, rtol=rtol): - for b in range(len(gradients)): - T = data["logit_lengths"][b] - U = data["target_lengths"][b] - for t in range(gradients.shape[1]): - for u in range(gradients.shape[2]): - np.testing.assert_allclose( - gradients[b, t, u], - ref_gradients[b, t, u], - atol=atol, - rtol=rtol, - err_msg=f"failed on b={b}, t={t}/T={T}, u={u}/U={U}", - ) + self.assertEqual(logits_shape, gradients.shape) + if not np.allclose(gradients, ref_gradients, atol=atol, rtol=rtol): + for b in range(len(gradients)): + T = data["logit_lengths"][b] + U = data["target_lengths"][b] + for t in range(gradients.shape[1]): + for u in range(gradients.shape[2]): + np.testing.assert_allclose( + gradients[b, t, u], + ref_gradients[b, t, u], + atol=atol, + rtol=rtol, + err_msg=f"failed on b={b}, t={t}/T={T}, u={u}/U={U}", + ) def test_nan_logits(self): - for sparse in [False, True]: - for reuse_logits_for_grads in [False, True]: - data = get_B1_T10_U3_D4_data( - random=True, left_buffer=10, right_buffer=10, sparse=sparse, nan=True - ) - data = numpy_to_torch( - data=data, device=self.device, requires_grad=True - ) - data["left_buffer"] = 10 - data["right_buffer"] = 10 - costs, gradients = compute_with_pytorch_transducer( - data=data, reuse_logits_for_grads=reuse_logits_for_grads - ) - self.assertTrue(np.all(costs == 0)) - self.assertTrue(np.all(gradients == 0)) + for reuse_logits_for_grads in [False, True]: + data = get_B1_T10_U3_D4_data( + random=True, left_buffer=10, right_buffer=10, nan=True + ) + data = numpy_to_torch( + data=data, device=self.device, requires_grad=True + ) + data["left_buffer"] = 10 + data["right_buffer"] = 10 + costs, gradients = compute_with_pytorch_transducer( + data=data, reuse_logits_for_grads=reuse_logits_for_grads + ) + self.assertTrue(np.all(costs == 0)) + self.assertTrue(np.all(gradients == 0)) def test_rnnt_restricted_betas_with_random_data(self): for u in range(50, 60): @@ -375,53 +363,9 @@ def test_rnnt_restricted_betas_with_random_data(self): targets=data["targets"], wordpiece_ends=wordpiece_ends, blank=4095, - sparse=False, ) def test_rnnt_nonfused_log_softmax(self): - for random in [False, True]: - for sparse in [False, True]: - for left_buffer in [1, 2, 10]: - for right_buffer in [1, 2, 5, 10]: - data = get_B1_T10_U3_D4_data( - random=random, - left_buffer=left_buffer, - right_buffer=right_buffer, - sparse=sparse, - ) - data = numpy_to_torch( - data=data, device=self.device, requires_grad=True - ) - data["left_buffer"] = left_buffer - data["right_buffer"] = right_buffer - data["fused_log_softmax"] = False - ref_costs, ref_gradients = compute_with_numpy_transducer( - data=data - ) - self._test_costs_and_gradients( - data=data, ref_costs=ref_costs, ref_gradients=ref_gradients - ) - - def test_rnnt_sparse_B1_T10_U3_D4(self): - for random in [False, True]: - for left_buffer in [1, 2, 10]: - for right_buffer in [1, 2, 5, 10]: - data = get_B1_T10_U3_D4_data( - random=random, left_buffer=left_buffer, right_buffer=right_buffer, sparse=True - ) - data = numpy_to_torch( - data=data, device=self.device, requires_grad=True - ) - data["left_buffer"] = left_buffer - data["right_buffer"] = right_buffer - ref_costs, ref_gradients = compute_with_numpy_transducer( - data=data - ) - self._test_costs_and_gradients( - data=data, ref_costs=ref_costs, ref_gradients=ref_gradients - ) - - def test_rnnt_sparse_B1_T10_U3_D4_fp16(self): for random in [False, True]: for left_buffer in [1, 2, 10]: for right_buffer in [1, 2, 5, 10]: @@ -429,107 +373,16 @@ def test_rnnt_sparse_B1_T10_U3_D4_fp16(self): random=random, left_buffer=left_buffer, right_buffer=right_buffer, - sparse=True, - dtype=np.float16, ) data = numpy_to_torch( data=data, device=self.device, requires_grad=True ) data["left_buffer"] = left_buffer data["right_buffer"] = right_buffer + data["fused_log_softmax"] = False ref_costs, ref_gradients = compute_with_numpy_transducer( data=data ) self._test_costs_and_gradients( - data=data, - ref_costs=ref_costs, - ref_gradients=ref_gradients, - atol=1e-3, - rtol=10, - ) - - def test_rnnt_sparse_alpha_beta_B1_T10_U3_D4(self): - for random in [False, True]: - for left_buffer in [1, 2, 10]: - for right_buffer in [1, 2, 10]: - data = get_B1_T10_U3_D4_data( - random=random, left_buffer=left_buffer, right_buffer=right_buffer, sparse=True - ) - data = numpy_to_torch( - data=data, device=self.device, requires_grad=True - ) - data["left_buffer"] = left_buffer - data["right_buffer"] = right_buffer - logits = torch.tensor(data["logits"]) - log_probs = ( - torch.nn.functional.log_softmax(logits, dim=-1).cpu().numpy() - ) - ( - np_gradients, - np_costs, - np_alphas, - np_betas, - ) = _NumpyTransducer.compute( - log_probs=log_probs, - logit_lengths=data["logit_lengths"], - target_lengths=data["target_lengths"], - targets=data["targets"], - blank=data["blank"], - wordpiece_ends=data["wordpiece_ends"], - left_buffer=left_buffer, - right_buffer=right_buffer, - ) - pt_alphas = _rnnt_loss_alphas( - logits=data["logits_sparse"], - logit_lengths=data["logit_lengths"], - target_lengths=data["target_lengths"], - targets=data["targets"], - wordpiece_ends=data["wordpiece_ends"], - blank=data["blank"], - left_buffer=left_buffer, - right_buffer=right_buffer, - sparse=True, - valid_ranges=data["valid_ranges"], - cells_per_sample=data["cells_per_sample"], - ) - total_valid = torch.sum(data["cells_per_sample"]) - sparse_np_alphas = np.zeros((total_valid)).astype(np.float32) - valid_ranges = data["valid_ranges"] - offset = 0 - for b in range(2): - for u in range(3): - st, en = valid_ranges[b][u][0], valid_ranges[b][u][1] - sparse_np_alphas[ - offset : offset + (en - st) + 1 - ] = np_alphas[b, st : en + 1, u] - offset += (en - st) + 1 - np.testing.assert_allclose( - pt_alphas.cpu(), sparse_np_alphas, atol=1e-6, rtol=1e-2 - ) - - pt_betas = _rnnt_loss_betas( - logits=data["logits_sparse"], - logit_lengths=data["logit_lengths"], - target_lengths=data["target_lengths"], - targets=data["targets"], - wordpiece_ends=data["wordpiece_ends"], - blank=data["blank"], - left_buffer=left_buffer, - right_buffer=right_buffer, - sparse=True, - valid_ranges=data["valid_ranges"], - cells_per_sample=data["cells_per_sample"], - ) - sparse_np_betas = np.zeros((total_valid)).astype(np.float32) - valid_ranges = data["valid_ranges"] - offset = 0 - for b in range(2): - for u in range(3): - st, en = valid_ranges[b][u][0], valid_ranges[b][u][1] - sparse_np_betas[offset : offset + (en - st) + 1] = np_betas[ - b, st : en + 1, u - ] - offset += (en - st) + 1 - np.testing.assert_allclose( - pt_betas.cpu(), sparse_np_betas, atol=1e-6, rtol=1e-2 + data=data, ref_costs=ref_costs, ref_gradients=ref_gradients ) diff --git a/test/torchaudio_unittest/rnnt/utils.py b/test/torchaudio_unittest/rnnt/utils.py index 5763e72688..d8030c4989 100644 --- a/test/torchaudio_unittest/rnnt/utils.py +++ b/test/torchaudio_unittest/rnnt/utils.py @@ -10,54 +10,6 @@ ) -def _get_sparse(data, dense_tensor, left_buffer, right_buffer, H=1): - B, _, U, D = 2, 10, 3, 4 - total_valid = 0 - valid_ranges = np.zeros((B * H, U, 2), dtype=np.int32) - cells_per_sample = np.zeros(B * H, dtype=np.int32) - wordpiece_ends = data["wordpiece_ends"] - for b_tgt in range(B * H): - b_src = int(b_tgt / H) - src_len = int(data["logit_lengths"][b_src]) - tgt_len = int(data["target_lengths"][b_tgt]) + 1 - ar_check = AlignmentRestrictionCheck( - tgt_len, src_len, wordpiece_ends[b_tgt][:tgt_len], left_buffer, right_buffer - ) - sample_cells = 0 - for u in range(tgt_len): - v_range = ar_check.valid_time_ranges(u) - valid_ranges[b_tgt, u, 0] = v_range[0] - valid_ranges[b_tgt, u, 1] = v_range[1] - total_valid += v_range[1] - v_range[0] + 1 - sample_cells += v_range[1] - v_range[0] + 1 - cells_per_sample[b_tgt] = sample_cells - sparse_joint_enc = np.zeros((total_valid, D)).astype(dense_tensor.dtype) - offset = 0 - for b in range(B * H): - for u in range(U): - st, en = valid_ranges[b_tgt][u][0], valid_ranges[b_tgt][u][1] - sparse_joint_enc[offset : offset + (en - st) + 1, :] = dense_tensor[ - b, st : en + 1, u, : - ] - offset += (en - st) + 1 - return sparse_joint_enc, valid_ranges, cells_per_sample - - -def assert_sparse_all_close(data, gradients, ref_gradients, atol=1e-6, rtol=1e-2): - valid_ranges = data["valid_ranges"] - idx = 0 - for b in range(valid_ranges.size(0)): - for u in range(valid_ranges.size(1)): - st, en = valid_ranges[b, u, 0], valid_ranges[b, u, 1] - np.testing.assert_allclose( - gradients[idx : idx + (en - st + 1), :], - ref_gradients[b, st : en + 1, u, :], - atol=atol, - rtol=rtol, - ) - idx += (en - st) + 1 - - def compute_with_numpy_transducer(data): costs = NumpyTransducerLoss( blank=data["blank"], @@ -88,19 +40,14 @@ def compute_with_pytorch_transducer(data, reuse_logits_for_grads=False): blank=data["blank"], left_buffer=left_buffer, right_buffer=right_buffer, - sparse=True if "logits_sparse" in data else False, fused_log_softmax=data.get("fused_log_softmax", True), reuse_logits_for_grads=reuse_logits_for_grads, )( - logits=data.get("logits_sparse", data["logits"]), + logits=data["logits"], logit_lengths=data["logit_lengths"], target_lengths=data["target_lengths"], targets=data["targets"], wordpiece_ends=data.get("wordpiece_ends", None), - valid_ranges=data.get("valid_ranges", None), - cells_per_sample=data["cells_per_sample"] - if "cells_per_sample" in data - else None, ) loss = torch.sum(costs) @@ -150,7 +97,6 @@ def get_B1_T10_U3_D4_data( random=False, left_buffer=0, right_buffer=0, - sparse=False, dtype=np.float32, nan=False, ): @@ -168,13 +114,6 @@ def get_B1_T10_U3_D4_data( data["blank"] = 0 data["wordpiece_ends"] = np.array([[0, 2, 7], [0, 2, 7]], dtype=np.int32) - if sparse: - sparse_joint_enc, valid_ranges, cells_per_sample = _get_sparse( - data, data["logits"], left_buffer, right_buffer - ) - data["logits_sparse"] = sparse_joint_enc - data["valid_ranges"] = valid_ranges - data["cells_per_sample"] = cells_per_sample return data @@ -517,20 +456,6 @@ def grad_hook(grad): data["target_lengths"] = target_lengths data["targets"] = targets - if "logits_sparse" in data: - logits_sparse = torch.from_numpy(data["logits_sparse"]) - logits_sparse = torch.autograd.Variable( - logits_sparse, requires_grad=requires_grad - ) - logits_sparse = logits_sparse.to(device=logits.device) - logits_sparse.register_hook(grad_hook) - data["logits_sparse"] = logits_sparse - valid_ranges = torch.from_numpy(data["valid_ranges"]) - valid_ranges = valid_ranges.to(device=logits.device) - data["valid_ranges"] = valid_ranges - cells_per_sample = torch.from_numpy(data["cells_per_sample"]) - cells_per_sample = cells_per_sample.to(device=logits.device) - data["cells_per_sample"] = cells_per_sample return data diff --git a/torchaudio/csrc/rnnt/cpu/alignment_restrictions.h b/torchaudio/csrc/rnnt/cpu/alignment_restrictions.h index 0ecc6af3bb..0c265b10be 100644 --- a/torchaudio/csrc/rnnt/cpu/alignment_restrictions.h +++ b/torchaudio/csrc/rnnt/cpu/alignment_restrictions.h @@ -57,61 +57,6 @@ class AlignmentRestrictionCheck { int rBuffer_; }; -struct SparseIndexer { - - SparseIndexer( - const int& maxU, - const int* tgtLengths, - const int* validRanges, - const int* cellsPerSample): - maxU_(maxU), - tgtLengths_(tgtLengths), - validRanges_(validRanges), - cellsPerSample_(cellsPerSample) {}; - - int operator() (int bIdx, int tIdx, int uIdx){ - - // increment the idx for valid cells in previous samples - int idx = 0; - for(int b = 0 ; b < bIdx; b++) { - idx += cellsPerSample_[b]; - } - - // increment the index for valid cells in current sample - // using pre-computed valid ranges - const int* validRangesB = validRanges_ + (maxU_*2) * bIdx; - int U = tgtLengths_[bIdx] + 1; - for (int u = 0 ; u < U ; u++) { - int startT = validRangesB[2 * u]; - int endT = validRangesB[2 * u + 1]; - if (u == uIdx) { - if (tIdx < startT || tIdx > endT) { - return -1; - } - idx += (tIdx - startT); - return idx; - } else { - idx += (endT - startT) + 1; - } - } - return -1; - } - - private: - const int& maxU_; - - // (vector of size B) contains the lengths of U for each sample in batch - const int* tgtLengths_; - - // (vector of size B*2*U) contains the valid time ranges (start_t, end_t) - // for each u in every sample, as per alignment restrictions - const int* validRanges_; - - // The total valid timesteps for each sample (sumed over all u in the sample). - // This is a quick loopup so we dont need to iterate on all previous u*b values. - const int* cellsPerSample_; -}; - } // namespace cpu } // namespace rnnt } // namespace torchaudio diff --git a/torchaudio/csrc/rnnt/cpu/kernel_utils.h b/torchaudio/csrc/rnnt/cpu/kernel_utils.h index 4ba141503e..08fc97b2e1 100644 --- a/torchaudio/csrc/rnnt/cpu/kernel_utils.h +++ b/torchaudio/csrc/rnnt/cpu/kernel_utils.h @@ -55,63 +55,5 @@ struct Indexer4D { } }; - -struct SparseIndexer { - HOST_AND_DEVICE SparseIndexer( - const int& maxU, - const int* tgtLengths, - const int* validRanges, - const int* cellsPerSample) : - maxU_(maxU), - tgtLengths_(tgtLengths), - validRanges_(validRanges), - cellsPerSample_(cellsPerSample) {}; - - HOST_AND_DEVICE int operator() (int bIdx, int tIdx, int uIdx) { - // Returns the sparse index given bIdx, tIdx, uIdx; or -1 if t out of band. - - // increment the idx for valid cells in previous samples - // TODO: Inefficient in the inner loop; precompute this? - int idx = 0; - for(int b = 0 ; b < bIdx; b++) { - idx += cellsPerSample_[b]; - } - - // increment the idx for valid cells in current sample - // using pre-computed valid ranges - const int* validRangesB = validRanges_ + (maxU_ * 2) * bIdx; - int U = tgtLengths_[bIdx] + 1; - for (int u = 0 ; u < U ; u++) { - int startT = validRangesB[2*u]; - int endT = validRangesB[2*u + 1]; - if (u == uIdx) { - if (tIdx < startT || tIdx > endT) { - return -1; - } - idx += (tIdx - startT); - return idx; - } else { - idx += (endT - startT) + 1; - } - } - return -1; - } - - private: - const int& maxU_; - - // (vector of size B) contains the lengths of U for each sample in batch - const int* tgtLengths_; - - // (vector of size B*2*U) contains the valid time ranges (start_t, end_t) - // for each u in every sample, as per alignment restrictions - const int* validRanges_; - - // The total valid timesteps for each sample (sumed over all u in the sample). - // This is a quick loopup so we dont need to iterate on all previous u*b values. - const int* cellsPerSample_; - -}; - } // namespace rnnt } // namespace torchaudio diff --git a/torchaudio/csrc/rnnt/gpu/compute.cu b/torchaudio/csrc/rnnt/gpu/compute.cu index 53567c131d..98cf39e2cc 100644 --- a/torchaudio/csrc/rnnt/gpu/compute.cu +++ b/torchaudio/csrc/rnnt/gpu/compute.cu @@ -6,116 +6,6 @@ namespace torchaudio { namespace rnnt { namespace gpu { -// Entry point into Sparse Alignment Restricted RNNT Loss. -std::tuple> -compute_sparse( - torch::Tensor& logits, - const torch::Tensor& targets, - const torch::Tensor& src_lengths, - const torch::Tensor& tgt_lengths, - int64_t blank, - double clamp, - int64_t max_T, - int64_t max_U, - const c10::optional& wp_ends = c10::nullopt, - int64_t l_buffer = 0, - int64_t r_buffer = 0, - const c10::optional& valid_ranges = c10::nullopt, - const c10::optional& cells_per_sample = c10::nullopt, - bool fused_log_smax = true, - bool reuse_logits_for_grads = true) { - - Options options; - options.batchSize_ = src_lengths.size(0); - options.nHypos_ = tgt_lengths.size(0) / src_lengths.size(0); - options.maxSrcLen_ = max_T; - options.maxTgtLen_ = max_U; - options.sparseCells_ = logits.size(0); - options.numTargets_ = logits.size(1); - options.fusedLogSmax_ = fused_log_smax; - - options.blank_ = blank; - options.clamp_ = clamp; - options.lBuffer_ = l_buffer; - options.rBuffer_ = r_buffer; - options.sparse_ = true; - - CHECK_EQ(logits.device().type(), torch::DeviceType::CUDA); - options.stream_ = at::cuda::getCurrentCUDAStream(); - cudaSetDevice(logits.get_device()); - options.device_ = GPU; - - torch::Tensor costs = torch::empty( - options.batchSize_ * options.nHypos_, - torch::TensorOptions().device(logits.device()).dtype(logits.dtype())); - - c10::optional gradients = c10::nullopt; - if (logits.requires_grad()) { - if (reuse_logits_for_grads) { - gradients = logits; - } else { - gradients = torch::zeros_like(logits); - } - } - torch::Tensor int_workspace = torch::empty( - IntWorkspace::ComputeSizeFromOptions(options), - torch::TensorOptions().device(logits.device()).dtype(torch::ScalarType::Int)); - - torch::Tensor float_workspace = torch::empty( - DtypeWorkspace::ComputeSizeFromOptions(options), - torch::TensorOptions().device(logits.device()).dtype(torch::ScalarType::Float)); - - Workspace workspace( - /*options=*/options, - /*dtype_data=*/float_workspace.data(), - /*dtype_size=*/float_workspace.numel(), - /*int_data=*/int_workspace.data(), - /*int_size=*/int_workspace.numel()); - - switch (logits.type().scalarType()) { - case torch::ScalarType::Float: - { - ComputeSparse( - /*workspace=*/workspace, - /*logits=*/logits.data(), - /*targets=*/targets.data(), - /*src_lengths=*/src_lengths.data(), - /*tgt_lengths=*/tgt_lengths.data(), - /*costs=*/costs.data(), - /*gradients=*/(gradients == c10::nullopt)? nullptr : gradients->data(), - /*wp_ends=*/(wp_ends == c10::nullopt)? nullptr : wp_ends->data(), - (valid_ranges == c10::nullopt)? nullptr : valid_ranges->data(), - (cells_per_sample == c10::nullopt)? nullptr : cells_per_sample->data()); - break; - } - case torch::ScalarType::Half: - { - ComputeSparse( - /*workspace=*/workspace, - /*logits=*/logits.data(), - /*targets=*/targets.data(), - /*src_lengths=*/src_lengths.data(), - /*tgt_lengths=*/tgt_lengths.data(), - /*costs=*/costs.data(), - /*gradients=*/(gradients == c10::nullopt)? nullptr : gradients->data(), - /*wp_ends=*/(wp_ends == c10::nullopt)? nullptr : wp_ends->data(), - (valid_ranges == c10::nullopt)? nullptr : valid_ranges->data(), - (cells_per_sample == c10::nullopt)? nullptr : cells_per_sample->data()); - break; - } - default: - { - LOG(ERROR) << "unsupported logits.type().scalarType() = " - << logits.type().scalarType(); - break; - } - }; - - - return std::make_tuple(costs, gradients); -} - - // Entry point into RNNT Loss std::tuple> compute( @@ -213,28 +103,8 @@ compute( return std::make_tuple(costs, gradients); } -TORCH_LIBRARY_FRAGMENT(torchaudio, m) { - m.def("rnnt_loss_sparse(Tensor logits," - "Tensor targets," - "Tensor src_lengths," - "Tensor tgt_lengths," - "int blank," - "float clamp," - "int max_T," - "int max_U," - "Tensor? wp_ends=None," - "int l_buffer=0," - "int r_buffer=0," - "Tensor? valid_ranges=None," - "Tensor? cells_per_sample=None," - "bool fused_log_smax=True," - "bool reuse_logits_for_grads=True) -> (Tensor, Tensor?)", - &compute_sparse); -} - TORCH_LIBRARY_IMPL(torchaudio, CUDA, m) { m.impl("rnnt_loss", &compute); - m.impl("rnnt_loss_sparse", &compute_sparse); } } // namespace gpu diff --git a/torchaudio/csrc/rnnt/gpu/compute_alphas.cu b/torchaudio/csrc/rnnt/gpu/compute_alphas.cu index f9bff447cd..929434e19d 100644 --- a/torchaudio/csrc/rnnt/gpu/compute_alphas.cu +++ b/torchaudio/csrc/rnnt/gpu/compute_alphas.cu @@ -70,97 +70,8 @@ torch::Tensor compute_alphas( return alphas; } -torch::Tensor compute_alphas_sparse( - const torch::Tensor& logits, - const torch::Tensor& targets, - const torch::Tensor& src_lengths, - const torch::Tensor& tgt_lengths, - int64_t blank, - double clamp, - int64_t max_T, - int64_t max_U, - const c10::optional& wp_ends = c10::nullopt, - int64_t l_buffer = 0, - int64_t r_buffer = 0, - const c10::optional& valid_ranges = c10::nullopt, - const c10::optional& cells_per_sample = c10::nullopt) { - Options options; - options.batchSize_ = src_lengths.size(0); - options.nHypos_ = tgt_lengths.size(0) / src_lengths.size(0); - options.maxSrcLen_ = max_T; - options.maxTgtLen_ = max_U; - options.sparseCells_ = logits.size(0); - options.numTargets_ = logits.size(1); - - options.blank_ = blank; - options.clamp_ = clamp; - options.lBuffer_ = l_buffer; - options.rBuffer_ = r_buffer; - options.sparse_ = true; - - CHECK_EQ(logits.device().type(), torch::DeviceType::CUDA); - options.stream_ = at::cuda::getCurrentCUDAStream(); - cudaSetDevice(logits.get_device()); - options.device_ = GPU; - - torch::Tensor alphas = torch::zeros( - {logits.size(0)}, - torch::TensorOptions().device(logits.device()).dtype(logits.dtype())); - - torch::Tensor int_workspace = torch::empty( - IntWorkspace::ComputeSizeFromOptions(options), - torch::TensorOptions() - .device(logits.device()) - .dtype(torch::ScalarType::Int)); - - torch::Tensor float_workspace = torch::empty( - DtypeWorkspace::ComputeSizeFromOptions(options), - torch::TensorOptions() - .device(logits.device()) - .dtype(torch::ScalarType::Float)); - - Workspace workspace( - /*options=*/options, - /*dtype_data=*/float_workspace.data(), - /*dtype_size=*/float_workspace.numel(), - /*int_data=*/int_workspace.data(), - /*int_size=*/int_workspace.numel()); - - // Only support float, this is mainly to enable easy - // unit-testing - ComputeAlphasSparse( - /*workspace=*/workspace, - /*logits=*/logits.data(), - /*targets=*/targets.data(), - /*src_lengths=*/src_lengths.data(), - /*tgt_lengths=*/tgt_lengths.data(), - /*alphas=*/alphas.data(), - /*wp_ends=*/(wp_ends == c10::nullopt) ? nullptr : wp_ends->data(), - (valid_ranges == c10::nullopt) ? nullptr : valid_ranges->data(), - (cells_per_sample == c10::nullopt) ? nullptr - : cells_per_sample->data()); - return alphas; -} - -TORCH_LIBRARY_FRAGMENT(torchaudio, m) { - m.def("rnnt_loss_alphas_sparse(Tensor logits," - "Tensor targets," - "Tensor src_lengths," - "Tensor tgt_lengths," - "int blank," - "float clamp," - "int max_T," - "int max_U, Tensor? wp_ends=None," - "int l_buffer=0," - "int r_buffer=0," - "Tensor? valid_ranges=None," - "Tensor? cells_per_sample=None) -> Tensor", - &compute_alphas_sparse); -} - TORCH_LIBRARY_IMPL(torchaudio, CUDA, m) { m.impl("rnnt_loss_alphas", &compute_alphas); - m.impl("rnnt_loss_alphas_sparse", &compute_alphas_sparse); } } // namespace gpu diff --git a/torchaudio/csrc/rnnt/gpu/compute_betas.cu b/torchaudio/csrc/rnnt/gpu/compute_betas.cu index ffdad7ccb7..f906d1bbe3 100644 --- a/torchaudio/csrc/rnnt/gpu/compute_betas.cu +++ b/torchaudio/csrc/rnnt/gpu/compute_betas.cu @@ -75,102 +75,8 @@ torch::Tensor compute_betas( return betas; } -torch::Tensor compute_betas_sparse( - const torch::Tensor& logits, - const torch::Tensor& targets, - const torch::Tensor& src_lengths, - const torch::Tensor& tgt_lengths, - int64_t blank, - double clamp, - int64_t max_T, - int64_t max_U, - const c10::optional& wp_ends = c10::nullopt, - int64_t l_buffer = 0, - int64_t r_buffer = 0, - const c10::optional& valid_ranges = c10::nullopt, - const c10::optional& cells_per_sample = c10::nullopt) { - Options options; - options.batchSize_ = src_lengths.size(0); - options.nHypos_ = tgt_lengths.size(0) / src_lengths.size(0); - options.maxSrcLen_ = max_T; - options.maxTgtLen_ = max_U; - options.sparseCells_ = logits.size(0); - options.numTargets_ = logits.size(1); - - options.blank_ = blank; - options.clamp_ = clamp; - options.lBuffer_ = l_buffer; - options.rBuffer_ = r_buffer; - - CHECK_EQ(logits.device().type(), torch::DeviceType::CUDA); - options.stream_ = at::cuda::getCurrentCUDAStream(); - cudaSetDevice(logits.get_device()); - options.device_ = GPU; - - torch::Tensor costs = torch::empty( - tgt_lengths.size(0), - torch::TensorOptions().device(logits.device()).dtype(logits.dtype())); - - torch::Tensor betas = torch::zeros( - {logits.size(0)}, - torch::TensorOptions().device(logits.device()).dtype(logits.dtype())); - - torch::Tensor int_workspace = torch::empty( - IntWorkspace::ComputeSizeFromOptions(options), - torch::TensorOptions() - .device(logits.device()) - .dtype(torch::ScalarType::Int)); - - torch::Tensor float_workspace = torch::empty( - DtypeWorkspace::ComputeSizeFromOptions(options), - torch::TensorOptions() - .device(logits.device()) - .dtype(torch::ScalarType::Float)); - - Workspace workspace( - /*options=*/options, - /*dtype_data=*/float_workspace.data(), - /*dtype_size=*/float_workspace.numel(), - /*int_data=*/int_workspace.data(), - /*int_size=*/int_workspace.numel()); - - // Only support float, this is mainly to enable easy - // unit-testing - ComputeBetasSparse( - /*workspace=*/workspace, - /*logits=*/logits.data(), - /*targets=*/targets.data(), - /*src_lengths=*/src_lengths.data(), - /*tgt_lengths=*/tgt_lengths.data(), - /*costs=*/costs.data(), - /*betas=*/betas.data(), - /*wp_ends=*/(wp_ends == c10::nullopt) ? nullptr : wp_ends->data(), - (valid_ranges == c10::nullopt) ? nullptr : valid_ranges->data(), - (cells_per_sample == c10::nullopt) ? nullptr - : cells_per_sample->data()); - return betas; -} - -TORCH_LIBRARY_FRAGMENT(torchaudio, m) { - m.def("rnnt_loss_betas_sparse(Tensor logits," - "Tensor targets," - "Tensor src_lengths," - "Tensor tgt_lengths," - "int blank," - "float clamp," - "int max_T," - "int max_U," - "Tensor? wp_ends=None," - "int l_buffer=0," - "int r_buffer=0," - "Tensor? valid_ranges=None," - "Tensor? cells_per_sample=None) -> Tensor", - &compute_betas_sparse); -} - TORCH_LIBRARY_IMPL(torchaudio, CUDA, m) { m.impl("rnnt_loss_betas", &compute_betas); - m.impl("rnnt_loss_betas_sparse", &compute_betas_sparse); } } // namespace gpu diff --git a/torchaudio/csrc/rnnt/gpu/gpu_alignment_restrictions.cuh b/torchaudio/csrc/rnnt/gpu/gpu_alignment_restrictions.cuh index 564eb0a3fb..d5d927992f 100644 --- a/torchaudio/csrc/rnnt/gpu/gpu_alignment_restrictions.cuh +++ b/torchaudio/csrc/rnnt/gpu/gpu_alignment_restrictions.cuh @@ -11,48 +11,6 @@ namespace torchaudio { namespace rnnt { -template -__global__ void ComputeLogProbsSparse( - int maxT, - int maxU, - int numTargets, - int blank, - const DTYPE* logits, - const int* targets, - const int* srcLengths, - const int* tgtLengths, - const CAST_DTYPE* denominators, - CAST_DTYPE* logProbs, - const int* wpEnds, - const int* validRanges=nullptr, - const int* cellsPerSample=nullptr, - int H=1, - bool fusedLogSmax=true) { - - const int bTgt = blockIdx.z; // 0 <= b < B - const int t = blockIdx.x * blockDim.x + threadIdx.x; - const int u = blockIdx.y; - - ComputeLogProbsSparseElement( - bTgt, - t, - u, - maxT, - maxU, - numTargets, - blank, - logits, - targets, - srcLengths, - tgtLengths, - denominators, - logProbs, - wpEnds, - validRanges, - cellsPerSample, - H=1, - fusedLogSmax); -} template __device__ void ComputeAlphasRestricted( @@ -69,9 +27,6 @@ __device__ void ComputeAlphasRestricted( int lBuffer, int rBuffer, int warp_size, - bool sparse=false, - const int* validRanges=nullptr, - const int* cellsPerSample=nullptr, int H=1) { const int& maxT = maxSrcLen; @@ -125,19 +80,11 @@ __device__ void ComputeAlphasRestricted( int idx_b_t_u = -1, idx_b_t_um1 = -1, idx_b_tm1_u = -1; int idx_b_prevWarpEndT_u = -1; - if (sparse) { - SparseIndexer idxr(maxU, tgtLengths, validRanges, cellsPerSample); - idx_b_t_u = idxr(bTgt, t, u); - idx_b_t_um1 = idxr(bTgt, t, u-1); - idx_b_tm1_u = idxr(bTgt, t-1, u); - idx_b_prevWarpEndT_u = idxr(bTgt, prevWarpEndT, u); - } else { - Indexer3D idxr(maxT, maxU); - idx_b_t_u = idxr(bTgt, t, u); - idx_b_t_um1 = idxr(bTgt, t, u - 1); - idx_b_tm1_u = idxr(bTgt, t - 1, u); - idx_b_prevWarpEndT_u = idxr(bTgt, prevWarpEndT, u); - } + Indexer3D idxr(maxT, maxU); + idx_b_t_u = idxr(bTgt, t, u); + idx_b_t_um1 = idxr(bTgt, t, u - 1); + idx_b_tm1_u = idxr(bTgt, t - 1, u); + idx_b_prevWarpEndT_u = idxr(bTgt, prevWarpEndT, u); alphas[idx_b_t_u] = CAST_DTYPE(-INFINITY); @@ -285,9 +232,6 @@ __global__ void ComputeAlphasRestrictedWrapper( int lBuffer, int rBuffer, int warp_size, - bool sparse=false, - const int* validRanges=nullptr, - const int* cellsPerSample=nullptr, int H=1) { ComputeAlphasRestricted( maxSrcLen, @@ -303,9 +247,6 @@ __global__ void ComputeAlphasRestrictedWrapper( lBuffer, rBuffer, warp_size, - sparse, - validRanges, - cellsPerSample, H); } @@ -327,9 +268,6 @@ __device__ void ComputeBetasCostsRestricted( int rBuffer, int warp_size, int num_warps, - bool sparse=false, - const int* validRanges=nullptr, - const int* cellsPerSample=nullptr, int H=1) { const int& maxT = maxSrcLen; @@ -370,19 +308,12 @@ __device__ void ComputeBetasCostsRestricted( int idx_b_t_u = -1, idx_b_t_up1 = -1; int idx_b_tp1_up1 = -1, idx_b_rightBlockStartT_u = -1; - if (sparse) { - SparseIndexer idxr(maxU, tgtLengths, validRanges, cellsPerSample); - idx_b_t_u = idxr(bTgt, t, u); - idx_b_t_up1 = idxr(bTgt, t, u+1); - idx_b_tp1_up1 = idxr(bTgt, t+1, u+1); - idx_b_rightBlockStartT_u = idxr(bTgt, rightBlockStartT, u); - } else { - Indexer3D idxr(maxT, maxU); - idx_b_t_u = idxr(bTgt, t, u); - idx_b_t_up1 = idxr(bTgt, t, u+1); - idx_b_tp1_up1 = idxr(bTgt, t+1, u+1); - idx_b_rightBlockStartT_u = idxr(bTgt, rightBlockStartT, u); - } + + Indexer3D idxr(maxT, maxU); + idx_b_t_u = idxr(bTgt, t, u); + idx_b_t_up1 = idxr(bTgt, t, u+1); + idx_b_tp1_up1 = idxr(bTgt, t+1, u+1); + idx_b_rightBlockStartT_u = idxr(bTgt, rightBlockStartT, u); if (t < T && u < U) { betas[idx_b_t_u] = CAST_DTYPE(-INFINITY); @@ -519,9 +450,6 @@ __global__ void ComputeBetasCostsRestrictedWrapper( int rBuffer, int warp_size, int num_warp, - bool sparse=false, - const int* validRanges=nullptr, - const int* cellsPerSample=nullptr, int H=1) { ComputeBetasCostsRestricted( maxSrcLen, @@ -539,9 +467,6 @@ __global__ void ComputeBetasCostsRestrictedWrapper( rBuffer, warp_size, num_warp, - sparse, - validRanges, - cellsPerSample, H); } diff --git a/torchaudio/csrc/rnnt/gpu/gpu_kernels.cuh b/torchaudio/csrc/rnnt/gpu/gpu_kernels.cuh index 88f625a251..2969a7f790 100644 --- a/torchaudio/csrc/rnnt/gpu/gpu_kernels.cuh +++ b/torchaudio/csrc/rnnt/gpu/gpu_kernels.cuh @@ -290,9 +290,6 @@ __global__ void ComputeAlphasBetasCosts( int rBuffer = 0, int warpSize = 0, int numWarps=0, - bool sparse=false, - const int* validRanges=nullptr, - const int* cellsPerSample=nullptr, int H = 1) { assert(threadIdx.y == 0 || threadIdx.y == 1); @@ -326,9 +323,6 @@ __global__ void ComputeAlphasBetasCosts( /*lBuffer=*/lBuffer, /*rBuffer=*/rBuffer, /*warpSize=*/warpSize, - sparse, - validRanges, - cellsPerSample, H); } } else { // threadIdx.y == 1 @@ -362,9 +356,6 @@ __global__ void ComputeAlphasBetasCosts( rBuffer, warpSize, numWarps, - sparse, - validRanges, - cellsPerSample, H); } @@ -387,9 +378,6 @@ __global__ void ComputeGradients( const CAST_DTYPE* alphas, const CAST_DTYPE* betas, DTYPE* gradients, - bool sparse = false, - const int* validRanges = nullptr, - const int* cellsPerSample = nullptr, int H = 1, bool fusedLogSmax = true) { @@ -414,9 +402,6 @@ __global__ void ComputeGradients( alphas, betas, gradients, - sparse, - validRanges, - cellsPerSample, H, fusedLogSmax); } diff --git a/torchaudio/csrc/rnnt/gpu/gpu_transducer.h b/torchaudio/csrc/rnnt/gpu/gpu_transducer.h index 7db7fe8a78..cde953a8ef 100644 --- a/torchaudio/csrc/rnnt/gpu/gpu_transducer.h +++ b/torchaudio/csrc/rnnt/gpu/gpu_transducer.h @@ -175,9 +175,6 @@ status_t Compute( /*r_buffer=*/r_buffer, /*warp_size=*/WARP_SIZE, /*num_warps=*/num_warps, - /*sparse=*/false, - /*validRanges=*/nullptr, - /*cellsPerSample=*/nullptr, H); if (cudaGetLastError() != cudaSuccess) { return COMPUTE_ALPHAS_BETAS_COSTS_FAILED; @@ -207,9 +204,6 @@ status_t Compute( /*alphas=*/workspace.GetPointerToAlphas(), /*betas=*/workspace.GetPointerToBetas(), /*gradients=*/gradients, - /*sparse=*/false, - /*validRanges=*/nullptr, - /*cellsPerSample=*/nullptr, H, fusedLogSmax); if (cudaGetLastError() != cudaSuccess) { @@ -220,154 +214,6 @@ status_t Compute( return SUCCESS; } -// Inputs: -// workspace: workspace. -// logits: pointer to (sparseCells, D) logits. -// targets: pointer to (B, max_U - 1) targets in the batch. -// srcLengths: pointer to (B, ) source lengths in the batch. -// tgtLengths: pointer to (B, ) target lengths in the batch. -// -// Outputs: -// costs: pointer to (B, ) costs in the batch. -// gradients: pointer to (sparseCells, D) gradients in the batch. -template -status_t ComputeSparse( - const Workspace& workspace, - const DTYPE* logits, - const int* targets, - const int* srcLengths, - const int* tgtLengths, - DTYPE* costs, - DTYPE* gradients = nullptr, - const int* wpEnds = nullptr, - const int* validRanges = nullptr, - const int* cellsPerSample = nullptr) { - const Options& options = workspace.GetOptions(); - - const cudaStream_t& stream = options.stream_; - const int& B = options.batchSize_; - const int& H = options.nHypos_; - const int& max_T = options.maxSrcLen_; - const int& max_U = options.maxTgtLen_; - const int& D = options.numTargets_; - const int& blank = options.blank_; - const CAST_DTYPE clamp = options.clamp_; - - const int& l_buffer = options.lBuffer_; - const int& r_buffer = options.rBuffer_; - const bool& fusedLogSmax = options.fusedLogSmax_; - - const int& sparseCells = options.sparseCells_; - { // compute denominators. - // for sparse kernel, we call kernel with sparseSize - status_t status = LogSumExp2D( - /*stream=*/stream, - /*N=*/sparseCells, // not B * max_T * max_U - /*D=*/D, - /*logits=*/logits, - /*denominators=*/workspace.GetPointerToDenominators()); - gpuErrchk(cudaGetLastError()); - if (status != SUCCESS) { - return status; - } - } - { // compute log probability pairs (blank and target). - int num_segments = - (max_T + MAX_THREADS_PER_BLOCK - 1) / MAX_THREADS_PER_BLOCK; - dim3 block_dims(num_segments, max_U, B * H); - dim3 thread_dims(MAX_THREADS_PER_BLOCK); - - ComputeLogProbsSparse - <<>>( - max_T, - max_U, - /*num_targets=*/D, - /*blank=*/blank, - /*logits=*/logits, - /*targets=*/targets, - /*srcLengths=*/srcLengths, - /*tgtLengths=*/tgtLengths, - /*denominators=*/workspace.GetPointerToDenominators(), - /*log_probs=*/workspace.GetPointerToLogProbs(), - wpEnds, - validRanges, - cellsPerSample, - H, - fusedLogSmax); - gpuErrchk(cudaGetLastError()); - } - { // compute alphas, betas and costs. - // warp is usually a group of threads (32) - int num_warps = (max_T + WARP_SIZE - 1) / WARP_SIZE; - - // each block is identified by 3 d tuple. - // we are using num_warp * max_U * B * H blocks - // where num_warp is division among Time axis - dim3 block_dims(num_warps, max_U, B * H); - - // each thread is identified by a 2 d tuple - // 2nd dim is 2. 1 for alpha, 1 for beta - dim3 thread_dims(WARP_SIZE, 2); - - ComputeAlphasBetasCosts - <<>>( - /*max_src_len=*/max_T, - /*max_tgt_len=*/max_U, - /*num_targets=*/D, - /*blank=*/blank, - /*log_probs=*/workspace.GetPointerToLogProbs(), - /*srcLengths=*/srcLengths, - /*tgtLengths=*/tgtLengths, - /*alpha_counters=*/workspace.GetPointerToAlphaCounters(), - /*alphas=*/workspace.GetPointerToAlphas(), - /*beta_counters=*/workspace.GetPointerToBetaCounters(), - /*betas=*/workspace.GetPointerToBetas(), - /*costs=*/costs, - /*wpEnds=*/wpEnds, - /*l_buffer=*/l_buffer, - /*r_buffer=*/r_buffer, - /*warp_size=*/WARP_SIZE, - /*num_warps=*/num_warps, - true, - validRanges, - cellsPerSample, - H); - gpuErrchk(cudaGetLastError()); - } - - if (gradients != nullptr) { // compute gradients. - // don't zero gradients here as gradient might share memory with logits - - int num_blocks = - (max_T + MAX_THREADS_PER_BLOCK - 1) / MAX_THREADS_PER_BLOCK; - dim3 block_dims(num_blocks, max_U, B * H); - dim3 thread_dims(MAX_THREADS_PER_BLOCK); - - ComputeGradients<<>>( - /*max_src_len=*/max_T, - /*max_tgt_len=*/max_U, - /*num_targets=*/D, - /*blank=*/blank, - /*clamp=*/clamp, - /*logits=*/logits, - /*targets=*/targets, - /*srcLengths=*/srcLengths, - /*tgtLengths=*/tgtLengths, - /*denominators=*/workspace.GetPointerToDenominators(), - /*alphas=*/workspace.GetPointerToAlphas(), - /*betas=*/workspace.GetPointerToBetas(), - /*gradients=*/gradients, - /*sparse=*/true, - /*validRanges=*/validRanges, - /*cellsPerSample=*/cellsPerSample, - H, - fusedLogSmax); - gpuErrchk(cudaGetLastError()); - } - - return SUCCESS; -} - template status_t ComputeAlphas( const Workspace& workspace, @@ -470,9 +316,6 @@ status_t ComputeAlphas( l_buffer, r_buffer, WARP_SIZE, - false, - nullptr, - nullptr, H); } if (cudaGetLastError() != cudaSuccess) { @@ -483,115 +326,6 @@ status_t ComputeAlphas( return SUCCESS; } -template -status_t ComputeAlphasSparse( - const Workspace& workspace, - const DTYPE* logits, - const int* targets, - const int* srcLengths, - const int* tgtLengths, - DTYPE* alphas, - const int* wpEnds = nullptr, - const int* validRanges = nullptr, - const int* cellsPerSample = nullptr) { - const Options& options = workspace.GetOptions(); - const cudaStream_t& stream = options.stream_; - const int& B = options.batchSize_; - const int& H = options.nHypos_; - const int& max_T = options.maxSrcLen_; - const int& max_U = options.maxTgtLen_; - const int& D = options.numTargets_; - const int& blank = options.blank_; - - const int& l_buffer = options.lBuffer_; - const int& r_buffer = options.rBuffer_; - - const int& sparseCells = options.sparseCells_; - - { // compute denominators. - // for sparse kernel, we would call kernel with sparseSize - status_t status = LogSumExp2D( - /*stream=*/stream, - /*N=*/sparseCells, // not B * max_T * max_U - /*D=*/D, - /*logits=*/logits, - /*denominators=*/workspace.GetPointerToDenominators()); - - if (status != SUCCESS) { - return status; - } - } - - { // compute log probability pairs (blank and target). - int num_segments = - (max_T + MAX_THREADS_PER_BLOCK - 1) / MAX_THREADS_PER_BLOCK; - dim3 block_dims(num_segments, max_U, B * H); - dim3 thread_dims(MAX_THREADS_PER_BLOCK); - - ComputeLogProbsSparse - <<>>( - max_T, - max_U, - /*num_targets=*/D, - /*blank=*/blank, - /*logits=*/logits, - /*targets=*/targets, - /*srcLengths=*/srcLengths, - /*tgtLengths=*/tgtLengths, - /*denominators=*/workspace.GetPointerToDenominators(), - /*log_probs=*/workspace.GetPointerToLogProbs(), - wpEnds, - validRanges, - cellsPerSample, - H); - - if (cudaGetLastError() != cudaSuccess) { - return COMPUTE_LOG_PROBS_FAILED; - } - } - { // compute alphas - // warp is usually a group of threads (32) - int num_warps = (max_T + WARP_SIZE - 1) / WARP_SIZE; - - // each block is identified by 3 d tuple. - // we are using num_warp * max_U * B blocks - // where num_warp is division among Time axis - dim3 block_dims(num_warps, max_U, B * H); - - // each thread is identified by a 2 d tuple - // 2nd dim is 1 for alpha only - dim3 thread_dims(WARP_SIZE, 1); - - // cudaMemset(alphas, 0, B * max_T * max_U * sizeof(DTYPE)); - ComputeAlphasRestrictedWrapper - <<>>( - max_T, - max_U, - D, - blank, - workspace.GetPointerToLogProbs(), - srcLengths, - tgtLengths, - workspace.GetPointerToAlphaCounters(), - // workspace.GetPointerToAlphas(), - (volatile DTYPE*)alphas, - wpEnds, - l_buffer, - r_buffer, - WARP_SIZE, - true, - validRanges, - cellsPerSample, - H); - - if (cudaGetLastError() != cudaSuccess) { - return COMPUTE_ALPHAS_BETAS_COSTS_FAILED; - } - } - - return SUCCESS; -} - template status_t ComputeBetas( const Workspace& workspace, @@ -696,9 +430,6 @@ status_t ComputeBetas( r_buffer, WARP_SIZE, num_warps, - false, - nullptr, - nullptr, H); cudaDeviceSynchronize(); } @@ -710,118 +441,6 @@ status_t ComputeBetas( return SUCCESS; } -template -status_t ComputeBetasSparse( - const Workspace& workspace, - const DTYPE* logits, - const int* targets, - const int* srcLengths, - const int* tgtLengths, - DTYPE* costs, - DTYPE* betas, - const int* wpEnds = nullptr, - const int* validRanges = nullptr, - const int* cellsPerSample = nullptr) { - const Options& options = workspace.GetOptions(); - const cudaStream_t& stream = options.stream_; - const int& B = options.batchSize_; - const int& H = options.nHypos_; - const int& max_T = options.maxSrcLen_; - const int& max_U = options.maxTgtLen_; - const int& D = options.numTargets_; - const int& blank = options.blank_; - - const int& l_buffer = options.lBuffer_; - const int& r_buffer = options.rBuffer_; - - const int& sparseCells = options.sparseCells_; - - { // compute denominators. - // for sparse kernel, we would call kernel with sparseSize - status_t status = LogSumExp2D( - /*stream=*/stream, - /*N=*/sparseCells, // not B * max_T * max_U - /*D=*/D, - /*logits=*/logits, - /*denominators=*/workspace.GetPointerToDenominators()); - - if (status != SUCCESS) { - return status; - } - } - - { // compute log probability pairs (blank and target). - int num_segments = - (max_T + MAX_THREADS_PER_BLOCK - 1) / MAX_THREADS_PER_BLOCK; - dim3 block_dims(num_segments, max_U, B * H); - dim3 thread_dims(MAX_THREADS_PER_BLOCK); - - ComputeLogProbsSparse - <<>>( - max_T, - max_U, - /*num_targets=*/D, - /*blank=*/blank, - /*logits=*/logits, - /*targets=*/targets, - /*srcLengths=*/srcLengths, - /*tgtLengths=*/tgtLengths, - /*denominators=*/workspace.GetPointerToDenominators(), - /*log_probs=*/workspace.GetPointerToLogProbs(), - wpEnds, - validRanges, - cellsPerSample, - H); - - if (cudaGetLastError() != cudaSuccess) { - return COMPUTE_LOG_PROBS_FAILED; - } - } - { // compute alphas - // warp is usually a group of threads (32) - int num_warps = (max_T + WARP_SIZE - 1) / WARP_SIZE; - - // each block is identified by 3 d tuple. - // we are using num_warp * max_U * B blocks - // where num_warp is division among Time axis - dim3 block_dims(num_warps, max_U, B * H); - - // each thread is identified by a 2 d tuple - // 2nd dim is 1 for alpha only - dim3 thread_dims(WARP_SIZE, 1); - - // cudaMemset(alphas, 0, B * max_T * max_U * sizeof(DTYPE)); - ComputeBetasCostsRestrictedWrapper - <<>>( - max_T, - max_U, - D, - blank, - workspace.GetPointerToLogProbs(), - srcLengths, - tgtLengths, - workspace.GetPointerToBetaCounters(), - costs, - (volatile DTYPE*)betas, - wpEnds, - l_buffer, - r_buffer, - WARP_SIZE, - num_warps, - true, - validRanges, - cellsPerSample, - H); - cudaDeviceSynchronize(); - - if (cudaGetLastError() != cudaSuccess) { - return COMPUTE_ALPHAS_BETAS_COSTS_FAILED; - } - } - - return SUCCESS; -} - } // namespace gpu } // namespace rnnt } // namespace torchaudio diff --git a/torchaudio/csrc/rnnt/gpu/kernel_utils.h b/torchaudio/csrc/rnnt/gpu/kernel_utils.h index 89d681a22d..03eb3d33b4 100644 --- a/torchaudio/csrc/rnnt/gpu/kernel_utils.h +++ b/torchaudio/csrc/rnnt/gpu/kernel_utils.h @@ -55,63 +55,5 @@ struct Indexer4D { } }; - -struct SparseIndexer { - HOST_AND_DEVICE SparseIndexer( - const int& maxU, - const int* tgtLengths, - const int* validRanges, - const int* cellsPerSample) : - maxU_(maxU), - tgtLengths_(tgtLengths), - validRanges_(validRanges), - cellsPerSample_(cellsPerSample) {}; - - HOST_AND_DEVICE int operator() (int bIdx, int tIdx, int uIdx) { - // Returns the sparse index given bIdx, tIdx, uIdx; or -1 if t out of band. - - // increment the idx for valid cells in previous samples - // TODO: Inefficient in the inner loop; precompute this? - int idx = 0; - for(int b = 0 ; b < bIdx; b++) { - idx += cellsPerSample_[b]; - } - - // increment the idx for valid cells in current sample - // using pre-computed valid ranges - const int* validRangesB = validRanges_ + (maxU_ * 2) * bIdx; - int U = tgtLengths_[bIdx] + 1; - for (int u = 0 ; u < U ; u++) { - int startT = validRangesB[2*u]; - int endT = validRangesB[2*u + 1]; - if (u == uIdx) { - if (tIdx < startT || tIdx > endT) { - return -1; - } - idx += (tIdx - startT); - return idx; - } else { - idx += (endT - startT) + 1; - } - } - return -1; - } - - private: - const int& maxU_; - - // (vector of size B) contains the lengths of U for each sample in batch - const int* tgtLengths_; - - // (vector of size B*2*U) contains the valid time ranges (start_t, end_t) - // for each u in every sample, as per alignment restrictions - const int* validRanges_; - - // The total valid timesteps for each sample (sumed over all u in the sample). - // This is a quick loopup so we dont need to iterate on all previous u*b values. - const int* cellsPerSample_; - -}; - } // namespace rnnt } // namespace torchaudio diff --git a/torchaudio/csrc/rnnt/gpu/kernels.h b/torchaudio/csrc/rnnt/gpu/kernels.h index 2dbf6231b4..2cbef51327 100644 --- a/torchaudio/csrc/rnnt/gpu/kernels.h +++ b/torchaudio/csrc/rnnt/gpu/kernels.h @@ -9,68 +9,6 @@ namespace torchaudio { namespace rnnt { -template -FORCE_INLINE HOST_AND_DEVICE void ComputeLogProbsSparseElement( - int bTgt, - int t, - int u, - int maxT, - int maxU, - int numTargets, - int blank, - const DTYPE* logits, - const int* targets, - const int* srcLengths, - const int* tgtLengths, - const CAST_DTYPE* denominators, - CAST_DTYPE* logProbs, - const int* wpEnds, - const int* validRanges=nullptr, - const int* cellsPerSample=nullptr, - int H=1, - bool fusedLogSmax=true) { - - const int& D = numTargets; - - const int bSrc = bTgt / H; - const int T = srcLengths[bSrc]; - const int U = tgtLengths[bTgt] + 1; - - if (t >= T || u >= U) { // out of boundary. - return; - } - const int* validRangesB = validRanges + (maxU*2) * bTgt; - int start = validRangesB[2*u]; - int end = validRangesB[2*u + 1]; - - // out of boundary for alignment restriction condition - if (t < start || t > end) { - return; - } - SparseIndexer idxr(maxU, tgtLengths, validRanges, cellsPerSample); - int idx = idxr(bTgt, t, u); - logProbs[(idx << 1) + LOG_PROBS_SKIP_IDX] = - CAST_DTYPE(logits[idx * D + blank]) - denominators[idx]; - - if (!fusedLogSmax) { - logProbs[(idx << 1) + LOG_PROBS_SKIP_IDX] = - CAST_DTYPE(logits[idx * D + blank]); - } - - if (u < U - 1) { - // emit: log_prob(b, t, u).emit() = logits(b, t, u, tgt[u]) - denom(b, t, u). - int target = targets[Indexer2D(maxU - 1)(bTgt, u)]; - logProbs[(idx << 1) + LOG_PROBS_EMIT_IDX] = - CAST_DTYPE(logits[idx * D + target]) - denominators[idx]; - - if (!fusedLogSmax) { - logProbs[(idx << 1) + LOG_PROBS_EMIT_IDX] = - CAST_DTYPE(logits[idx * D + target]); - } - } -} - - template HOST_AND_DEVICE void ComputeGradientsElement( int bTgt, @@ -89,9 +27,6 @@ HOST_AND_DEVICE void ComputeGradientsElement( const CAST_DTYPE* alphas, const CAST_DTYPE* betas, DTYPE* gradients, - bool sparse = false, - const int* validRanges = nullptr, - const int* cellsPerSample = nullptr, int H = 1, bool fusedLogSmax = true) { @@ -104,10 +39,7 @@ HOST_AND_DEVICE void ComputeGradientsElement( const int U = tgtLengths[bTgt] + 1; if (t >= T || u >= U) { // out of boundary. - if (sparse) { - // no extra elements needs to be set to 0 - return; - } else if (gradients == logits && t < maxT && u < maxU) { + if (gradients == logits && t < maxT && u < maxU) { // gradients and logits are pointing to the same memory location Indexer3D idxr3(maxT, maxU); int idx_b_t_u_zero = idxr3(bTgt, t, u); @@ -121,32 +53,18 @@ HOST_AND_DEVICE void ComputeGradientsElement( return; } - int costIdx; - if (!sparse) { - costIdx = bTgt * maxT * maxU; - } else { - SparseIndexer idxr(maxU, tgtLengths, validRanges, cellsPerSample); - costIdx = idxr(bTgt, 0, 0); - } + int costIdx = bTgt * maxT * maxU; CAST_DTYPE cost = -(betas[costIdx]); Indexer2D idxr2(maxU - 1); int idx_b_t_u, idx_b_t_up1, idx_b_tp1_u, idx_b_tp1_up1; - if (sparse) { - SparseIndexer idxr(maxU, tgtLengths, validRanges, cellsPerSample); - idx_b_t_u = idxr(bTgt, t, u); - idx_b_t_up1 = idxr(bTgt, t, u+1); - idx_b_tp1_u = idxr(bTgt, t+1, u); - idx_b_tp1_up1 = idxr(bTgt, t+1, u+1); - } else { - Indexer3D idxr3(maxT, maxU); - idx_b_t_u = idxr3(bTgt, t, u); - idx_b_t_up1 = idxr3(bTgt, t, u+1); - idx_b_tp1_u = idxr3(bTgt, t+1, u); - idx_b_tp1_up1 = idxr3(bTgt, t+1, u+1); - } + Indexer3D idxr3(maxT, maxU); + idx_b_t_u = idxr3(bTgt, t, u); + idx_b_t_up1 = idxr3(bTgt, t, u+1); + idx_b_tp1_u = idxr3(bTgt, t+1, u); + idx_b_tp1_up1 = idxr3(bTgt, t+1, u+1); if (idx_b_t_u == -1 ) { return; diff --git a/torchaudio/csrc/rnnt/options.h b/torchaudio/csrc/rnnt/options.h index 4debce21df..c7ea63eda9 100644 --- a/torchaudio/csrc/rnnt/options.h +++ b/torchaudio/csrc/rnnt/options.h @@ -48,11 +48,6 @@ typedef struct Options { // num_targets = D. int numTargets_; - // whether to use sparse layout for ar-rnnt - bool sparse_; - - int sparseCells_; - // if set to true, inputs are logits and gradients are // fused with logsoftmax gradients. // if set to false, log_softmax is computed outside of loss @@ -72,8 +67,6 @@ typedef struct Options { maxSrcLen_(0), maxTgtLen_(0), numTargets_(0), - sparse_(false), - sparseCells_(0), fusedLogSmax_(true) {} int BU() const { diff --git a/torchaudio/csrc/rnnt/transducer.h b/torchaudio/csrc/rnnt/transducer.h index 8384fd5a9d..c69067a000 100644 --- a/torchaudio/csrc/rnnt/transducer.h +++ b/torchaudio/csrc/rnnt/transducer.h @@ -49,41 +49,6 @@ status_t Compute( }; } -template -status_t ComputeSparse( - const Workspace& workspace, - const DTYPE* logits, - const int* targets, - const int* srcLengths, - const int* tgtLengths, - DTYPE* costs, - DTYPE* gradients = nullptr, - const int* wp_ends=nullptr, - const int* validRanges=nullptr, - const int* cellsPerSample=nullptr) { - switch (workspace.GetOptions().device_) { - case GPU: { - status_t status = gpu::ComputeSparse( - /*workspace=*/workspace, - /*logits=*/logits, - /*targets=*/targets, - /*srcLengths=*/srcLengths, - /*tgtLengths=*/tgtLengths, - /*costs=*/costs, - /*gradients=*/gradients, - /*wp_ends =*/wp_ends, - validRanges, - cellsPerSample); - return status; - } - default: { - LOG(ERROR) << "unsupported workspace.GetOptions().device = " - << workspace.GetOptions().device_; - return FAILURE; - } - }; -} - template status_t ComputeAlphas( const Workspace& workspace, @@ -124,39 +89,6 @@ status_t ComputeAlphas( }; } -template -status_t ComputeAlphasSparse( - const Workspace& workspace, - const DTYPE* logits, - const int* targets, - const int* srcLengths, - const int* tgtLengths, - DTYPE* alphas, - const int* wp_ends=nullptr, - const int* validRanges=nullptr, - const int* cellsPerSample=nullptr) { - switch (workspace.GetOptions().device_) { - case GPU: { - status_t status = gpu::ComputeAlphasSparse( - /*workspace=*/workspace, - /*logits=*/logits, - /*targets=*/targets, - /*srcLengths=*/srcLengths, - /*tgtLengths=*/tgtLengths, - /*costs=*/alphas, - /*wp_ends =*/wp_ends, - validRanges, - cellsPerSample); - return status; - } - default: { - LOG(ERROR) << "unsupported workspace.GetOptions().device = " - << workspace.GetOptions().device_; - return FAILURE; - } - }; -} - template status_t ComputeBetas( const Workspace& workspace, @@ -200,40 +132,5 @@ status_t ComputeBetas( }; } -template -status_t ComputeBetasSparse( - const Workspace& workspace, - const DTYPE* logits, - const int* targets, - const int* srcLengths, - const int* tgtLengths, - DTYPE* costs, - DTYPE* betas, - const int* wp_ends=nullptr, - const int* validRanges=nullptr, - const int* cellsPerSample=nullptr) { - switch (workspace.GetOptions().device_) { - case GPU: { - status_t status = gpu::ComputeBetasSparse( - /*workspace=*/workspace, - /*logits=*/logits, - /*targets=*/targets, - /*srcLengths=*/srcLengths, - /*tgtLengths=*/tgtLengths, - /*costs=*/costs, - /*betas=*/betas, - /*wp_ends =*/wp_ends, - validRanges, - cellsPerSample); - return status; - } - default: { - LOG(ERROR) << "unsupported workspace.GetOptions().device = " - << workspace.GetOptions().device_; - return FAILURE; - } - }; -} - } // namespace rnnt } // namespace torchaudio diff --git a/torchaudio/csrc/rnnt/workspace.h b/torchaudio/csrc/rnnt/workspace.h index 243b836a93..95a1fcf0c4 100644 --- a/torchaudio/csrc/rnnt/workspace.h +++ b/torchaudio/csrc/rnnt/workspace.h @@ -60,19 +60,19 @@ class DtypeWorkspace { private: static int ComputeSizeForDenominators(const Options& options) { // B * T * U - return options.sparse_ ? options.sparseCells_ : options.BTU(); + return options.BTU(); } static int ComputeSizeForLogProbs(const Options& options) { // B * T * U * 2 - return options.sparse_ ? options.sparseCells_ * 2 : options.BTU() * 2; + return options.BTU() * 2; } static int ComputeSizeForAlphas(const Options& options) { // B * T * U - return options.sparse_ ? options.sparseCells_ : options.BTU(); + return options.BTU(); } static int ComputeSizeForBetas(const Options& options) { // B * T * U - return options.sparse_ ? options.sparseCells_ : options.BTU(); + return options.BTU(); } Options options_; diff --git a/torchaudio/prototype/rnnt_loss.py b/torchaudio/prototype/rnnt_loss.py index 0839290e0a..f69d328f53 100644 --- a/torchaudio/prototype/rnnt_loss.py +++ b/torchaudio/prototype/rnnt_loss.py @@ -16,9 +16,6 @@ def _rnnt_loss_alphas( wordpiece_ends=None, left_buffer=0, right_buffer=0, - sparse=False, - valid_ranges=None, - cells_per_sample=None, ): """ Compute alphas for RNN transducer loss. @@ -35,37 +32,18 @@ def _rnnt_loss_alphas( targets = targets.int() logit_lengths = logit_lengths.int() target_lengths = target_lengths.int() - if not sparse: - return torch.ops.torchaudio.rnnt_loss_alphas( - logits, - targets, - logit_lengths, - target_lengths, - blank, - clamp, - wordpiece_ends, - left_buffer, - right_buffer, - ) - else: - try: - return torch.ops.torchaudio.rnnt_loss_alphas_sparse( - logits, - targets, - logit_lengths, - target_lengths, - blank, - clamp, - torch.max(logit_lengths).item(), - torch.max(target_lengths).item() + 1, - wordpiece_ends, - left_buffer, - right_buffer, - valid_ranges, - cells_per_sample, - ) - except RuntimeError: - raise RuntimeError("sparse is only supported on GPU with torchaudio compiled with GPU support") + + return torch.ops.torchaudio.rnnt_loss_alphas( + logits, + targets, + logit_lengths, + target_lengths, + blank, + clamp, + wordpiece_ends, + left_buffer, + right_buffer, + ) def _rnnt_loss_betas( @@ -78,9 +56,6 @@ def _rnnt_loss_betas( wordpiece_ends=None, left_buffer=0, right_buffer=0, - sparse=False, - valid_ranges=None, - cells_per_sample=None, ): """ Compute betas for RNN transducer loss @@ -97,37 +72,18 @@ def _rnnt_loss_betas( targets = targets.int() logit_lengths = logit_lengths.int() target_lengths = target_lengths.int() - if not sparse: - return torch.ops.torchaudio.rnnt_loss_betas( - logits, - targets, - logit_lengths, - target_lengths, - blank, - clamp, - wordpiece_ends, - left_buffer, - right_buffer, - ) - else: - try: - return torch.ops.torchaudio.rnnt_loss_betas_sparse( - logits, - targets, - logit_lengths, - target_lengths, - blank, - clamp, - torch.max(logit_lengths).item(), - torch.max(target_lengths).item() + 1, - wordpiece_ends, - left_buffer, - right_buffer, - valid_ranges, - cells_per_sample, - ) - except RuntimeError: - raise RuntimeError("sparse is only supported on GPU with torchaudio compiled with GPU support") + + return torch.ops.torchaudio.rnnt_loss_betas( + logits, + targets, + logit_lengths, + target_lengths, + blank, + clamp, + wordpiece_ends, + left_buffer, + right_buffer, + ) class _RNNT(torch.autograd.Function): @@ -144,9 +100,6 @@ def forward( wordpiece_ends=None, left_buffer=0, right_buffer=0, - sparse=False, - valid_ranges=None, - cells_per_sample=None, fused_log_softmax=True, reuse_logits_for_grads=True, ): @@ -160,10 +113,6 @@ def forward( target_lengths = target_lengths.to(device=logits.device) if wordpiece_ends is not None: wordpiece_ends = wordpiece_ends.to(device=logits.device) - if valid_ranges is not None: - valid_ranges = valid_ranges.to(device=logits.device) - if cells_per_sample is not None: - cells_per_sample = cells_per_sample.to(device=logits.device) # make sure all int tensors are of type int32. targets = targets.int() @@ -181,67 +130,29 @@ def forward( target_lengths=target_lengths, blank=blank, ) - if sparse: - try: - rnnt_loss_sparse = torch.ops.torchaudio.rnnt_loss_sparse - except RuntimeError: - raise RuntimeError("sparse is only supported on GPU with torchaudio compiled with GPU support") - - max_T = torch.max(logit_lengths).item() # note: not used for indexing - max_U = targets.shape[1] + 1 # used for indexing, e.g. wordpiece_ends - assert max_U >= torch.max(target_lengths).item() + 1 - assert max_U == wordpiece_ends.shape[1] and max_U == valid_ranges.shape[1] - costs, gradients = rnnt_loss_sparse( - logits=logits, - targets=targets, - src_lengths=logit_lengths, - tgt_lengths=target_lengths, - blank=blank, - clamp=clamp, - wp_ends=wordpiece_ends, - l_buffer=left_buffer, - r_buffer=right_buffer, - max_T=max_T, - max_U=max_U, - valid_ranges=valid_ranges, - cells_per_sample=cells_per_sample, - fused_log_smax=fused_log_softmax, - reuse_logits_for_grads=reuse_logits_for_grads, - ) - ctx.cells_per_sample = cells_per_sample - else: - costs, gradients = torch.ops.torchaudio.rnnt_loss( - logits=logits, - targets=targets, - src_lengths=logit_lengths, - tgt_lengths=target_lengths, - blank=blank, - clamp=clamp, - wp_ends=wordpiece_ends, - l_buffer=left_buffer, - r_buffer=right_buffer, - fused_log_smax=fused_log_softmax, - reuse_logits_for_grads=reuse_logits_for_grads, - ) + + costs, gradients = torch.ops.torchaudio.rnnt_loss( + logits=logits, + targets=targets, + src_lengths=logit_lengths, + tgt_lengths=target_lengths, + blank=blank, + clamp=clamp, + wp_ends=wordpiece_ends, + l_buffer=left_buffer, + r_buffer=right_buffer, + fused_log_smax=fused_log_softmax, + reuse_logits_for_grads=reuse_logits_for_grads, + ) ctx.grads = gradients - ctx.sparse = sparse return costs @staticmethod def backward(ctx, output_gradients): - if ctx.sparse: - output_gradients = output_gradients.view(-1, 1).to(ctx.grads) - offset = 0 - count = 0 - for ncells in ctx.cells_per_sample: - ctx.grads[offset : offset + ncells, :].mul_(output_gradients[count]) - offset += ncells - count += 1 - else: - output_gradients = output_gradients.view(-1, 1, 1, 1).to(ctx.grads) - ctx.grads.mul_(output_gradients).to(ctx.grads) + output_gradients = output_gradients.view(-1, 1, 1, 1).to(ctx.grads) + ctx.grads.mul_(output_gradients).to(ctx.grads) return ( ctx.grads, # logits @@ -254,9 +165,6 @@ def backward(ctx, output_gradients): None, # wordpiece_ends None, # left_buffer None, # right_buffer - None, # sparse - None, # valid_ranges - None, # cells_per_sample None, # fused_log_softmax None, # reuse_logits_for_grads ) @@ -273,9 +181,6 @@ def rnnt_loss( wordpiece_ends=None, left_buffer=0, right_buffer=0, - sparse=False, - valid_ranges=None, - cells_per_sample=None, fused_log_softmax=True, reuse_logits_for_grads=True, ): @@ -300,11 +205,6 @@ def rnnt_loss( Loss will not be imposed on frames smaller than wordpiece_end - left_buffer. (Default: ``0``) right_buffer (int): right buffer frames used for alignment restricted RNNT loss. Loss will not be imposed on frames greater than wordpiece_end + right_buffer. (Default: ``0``) - sparse (bool): set to true for sparse alignment restricted RNNT. (Default: ``False``) - valid_ranges (Tensor): Tensor of dimension (batch, target, 2) containing valid ranges for sparse AR-RNNT - (Default: ``None``) - cells_per_sample (Tensor): Tensor of dimension (batch) containing total valid cells for each (Default: ``None``) - sample while doing sparse AR-RNNT (Default: ``None``) fused_log_smax (bool): set to False if calling log_softmax outside loss (Default: ``True``) reuse_logits_for_grads (bool): whether to save memory by reusing logits memory for grads (Default: ``True``) """ @@ -325,9 +225,6 @@ def rnnt_loss( wordpiece_ends, left_buffer, right_buffer, - sparse, - valid_ranges, - cells_per_sample, fused_log_softmax, reuse_logits_for_grads, ) @@ -350,7 +247,6 @@ class RNNTLoss(torch.nn.Module): Loss will not be imposed on frames smaller than wordpiece_end - left_buffer. (Default: ``0``) right_buffer (int): right buffer frames used for alignment restricted RNNT loss. Loss will not be imposed on frames greater than wordpiece_end + right_buffer. (Default: ``0``) - sparse (bool): set to true for sparse alignment restricted RNNT. (Default: ``False``) fused_log_smax (bool): set to False if calling log_softmax outside loss (Default: ``True``) reuse_logits_for_grads (bool): whether to save memory by reusing logits memory for grads (Default: ``True``) """ @@ -362,7 +258,6 @@ def __init__( runtime_check=False, left_buffer=0, right_buffer=0, - sparse=False, fused_log_softmax=True, reuse_logits_for_grads=True, ): @@ -372,7 +267,6 @@ def __init__( self.runtime_check = runtime_check self.left_buffer = left_buffer self.right_buffer = right_buffer - self.sparse = sparse self.fused_log_softmax = fused_log_softmax self.reuse_logits_for_grads = reuse_logits_for_grads @@ -383,8 +277,6 @@ def forward( logit_lengths, target_lengths, wordpiece_ends=None, - valid_ranges=None, - cells_per_sample=None, left_buffer=None, right_buffer=None, ): @@ -396,10 +288,6 @@ def forward( target_lengths (Tensor): Tensor of dimension (batch) containing lengths of targets for each sequence wordpiece_ends (Tensor): Tensor of dimension (batch, target) containing the end frames of targets for each sequence (including bos end_frame = 0) (Default: ``None``) - valid_ranges (Tensor): Tensor of dimension (batch, target, 2) containing valid ranges for sparse AR-RNNT - (Default: ``None``) - cells_per_sample (Tensor): Tensor of dimension (batch) containing total valid cells for each - sample while doing sparse AR-RNNT (Default: ``None``) left_buffer (int): left buffer frames used for alignment restricted RNNT loss. Loss will not be imposed on frames smaller than wordpiece_end - left_buffer. (Default: ``None``) right_buffer (int): right buffer frames used for alignment restricted RNNT loss. @@ -425,9 +313,6 @@ def forward( wordpiece_ends, left_buffer, right_buffer, - self.sparse, - valid_ranges, - cells_per_sample, self.fused_log_softmax, self.reuse_logits_for_grads, ) From 66f3db297951f014a9479f89fbcccafb81d7e9ad Mon Sep 17 00:00:00 2001 From: Caroline Chen Date: Fri, 30 Apr 2021 12:53:14 -0700 Subject: [PATCH 46/73] Remove alignment restriction support Summary: we do not wish to support alignment-restriction for the first release. this diff removes alignment restriction support along with relevant parameters (`wordpiece_ends`, `left_buffer`, `right_buffer`) and unit tests Reviewed By: vincentqb Differential Revision: D28072228 fbshipit-source-id: daf62b10a1e004ab4c22d498811c8bee3f0a22e0 --- .../rnnt/numpy_transducer.py | 251 +-------- .../rnnt/rnnt_loss_cuda_test.py | 8 +- .../rnnt/rnnt_loss_impl.py | 288 +---------- test/torchaudio_unittest/rnnt/utils.py | 19 +- torchaudio/csrc/rnnt/compute.cpp | 3 - torchaudio/csrc/rnnt/compute_alphas.cpp | 5 +- torchaudio/csrc/rnnt/compute_betas.cpp | 5 +- .../csrc/rnnt/cpu/alignment_restrictions.cpp | 98 ---- .../csrc/rnnt/cpu/alignment_restrictions.h | 62 --- torchaudio/csrc/rnnt/cpu/compute.cpp | 11 +- torchaudio/csrc/rnnt/cpu/compute_alphas.cpp | 10 +- torchaudio/csrc/rnnt/cpu/compute_betas.cpp | 10 +- torchaudio/csrc/rnnt/cpu/cpu_kernels.h | 238 ++------- torchaudio/csrc/rnnt/cpu/cpu_transducer.h | 18 +- torchaudio/csrc/rnnt/gpu/compute.cu | 11 +- torchaudio/csrc/rnnt/gpu/compute_alphas.cu | 10 +- torchaudio/csrc/rnnt/gpu/compute_betas.cu | 10 +- .../rnnt/gpu/gpu_alignment_restrictions.cuh | 476 ------------------ torchaudio/csrc/rnnt/gpu/gpu_kernels.cuh | 46 +- torchaudio/csrc/rnnt/gpu/gpu_transducer.h | 117 ++--- torchaudio/csrc/rnnt/options.h | 8 - torchaudio/csrc/rnnt/transducer.h | 27 +- torchaudio/prototype/rnnt_loss.py | 68 --- 23 files changed, 108 insertions(+), 1691 deletions(-) delete mode 100644 torchaudio/csrc/rnnt/cpu/alignment_restrictions.cpp delete mode 100644 torchaudio/csrc/rnnt/cpu/alignment_restrictions.h delete mode 100644 torchaudio/csrc/rnnt/gpu/gpu_alignment_restrictions.cuh diff --git a/test/torchaudio_unittest/rnnt/numpy_transducer.py b/test/torchaudio_unittest/rnnt/numpy_transducer.py index 7a26013dd7..a284bc1a8d 100644 --- a/test/torchaudio_unittest/rnnt/numpy_transducer.py +++ b/test/torchaudio_unittest/rnnt/numpy_transducer.py @@ -11,9 +11,6 @@ def forward( target_lengths, targets, blank=-1, - wordpiece_ends=None, - left_buffer=0, - right_buffer=0, ): device = log_probs.device log_probs = log_probs.cpu().data.numpy() @@ -27,9 +24,6 @@ def forward( target_lengths=target_lengths, targets=targets, blank=blank, - wordpiece_ends=wordpiece_ends, - left_buffer=left_buffer, - right_buffer=right_buffer, ) costs = torch.FloatTensor(costs).to(device=device) @@ -61,51 +55,6 @@ def compute_alpha_one_sequence(log_probs, targets, blank=-1): cost = -(alpha[-1, -1] + log_probs[-1, -1, blank]) return alpha, cost - @staticmethod - def compute_alpha_one_sequence_restricted( - log_probs, targets, wordpiece_ends, blank=-1, left_buffer=0, right_buffer=0 - ): - # Note - this is a more generic case - # If we set left_buffer = right_buffer = inf this becomes same as - # `compute_alpha_one_sequence`. However keeping both versions, - # since without the checks, compute_alpha_one_sequence may be tiny - # bit faster than `compute_alpha_one_sequence_restricted` - - max_T, max_U, D = log_probs.shape - check = AlignmentRestrictionCheck( - max_U, max_T, wordpiece_ends, left_buffer, right_buffer - ) - - alpha = np.zeros((max_T, max_U), dtype=np.float32) - alpha.fill(float("-inf")) - alpha[0, 0] = 0.0 - for t in range(1, max_T): - if not check.alpha_blank_transition(t, 0): - break - alpha[t, 0] = log_probs[t - 1, 0, blank] + alpha[t - 1, 0] - - for u in range(1, max_U): - if not check.alpha_emit_transition(0, u): - break - alpha[0, u] = log_probs[0, u - 1, targets[u - 1]] + alpha[0, u - 1] - - for u in range(1, max_U): - start_t, end_t = check.valid_time_ranges(u) - for t in range(start_t, end_t + 1): - skip, emit = float("-inf"), float("-inf") - - if check.alpha_blank_transition(t, u): - skip = alpha[t - 1, u] + log_probs[t - 1, u, blank] - - if check.alpha_emit_transition(t, u): - emit = alpha[t, u - 1] + log_probs[t, u - 1, targets[u - 1]] - - if emit != float("-inf") or skip != float("-inf"): - alpha[t, u] = np.logaddexp(skip, emit) - - cost = -(alpha[-1, -1] + log_probs[-1, -1, blank]) - return alpha, cost - @staticmethod def compute_beta_one_sequence(log_probs, targets, blank=-1): max_T, max_U, D = log_probs.shape @@ -127,51 +76,6 @@ def compute_beta_one_sequence(log_probs, targets, blank=-1): cost = -beta[0, 0] return beta, cost - @staticmethod - def compute_beta_one_sequence_restricted( - log_probs, targets, wordpiece_ends, blank=-1, left_buffer=0, right_buffer=0 - ): - # Note - this is a more generic case - # If we set left_buffer = right_buffer = inf this becomes same as - # `compute_beta_one_sequence`. However keeping both versions, - # since without the checks, compute_beta_one_sequence may be tiny - # bit faster than `compute_beta_one_sequence_restricted` - max_T, max_U, D = log_probs.shape - - check = AlignmentRestrictionCheck( - max_U, max_T, wordpiece_ends, left_buffer, right_buffer - ) - beta = np.zeros((max_T, max_U), dtype=np.float32) - beta.fill(float("-inf")) - beta[-1, -1] = log_probs[-1, -1, blank] - - for t in reversed(range(max_T - 1)): - if not check.beta_blank_transition(t, max_U - 1): - break - beta[t, -1] = beta[t + 1, -1] + log_probs[t, -1, blank] - - for u in reversed(range(max_U - 1)): - if not check.beta_emit_transition(max_T - 1, u): - break - beta[-1, u] = beta[-1, u + 1] + log_probs[-1, u, targets[u]] - - for u in reversed(range(max_U - 1)): - start_t, end_t = check.valid_time_ranges(u) - for t in reversed(range(start_t, end_t + 1)): - skip, emit = float("-inf"), float("-inf") - - if check.beta_emit_transition(t, u): - emit = beta[t, u + 1] + log_probs[t, u, targets[u]] - - if check.beta_blank_transition(t, u): - skip = beta[t + 1, u] + log_probs[t, u, blank] - - if emit != float("-inf") or skip != float("-inf"): - beta[t, u] = np.logaddexp(skip, emit) - - cost = -beta[0, 0] - return beta, cost - @staticmethod def compute_gradients_one_sequence( log_probs, alpha, beta, targets, blank=-1 @@ -197,9 +101,6 @@ def compute( target_lengths, targets, blank=-1, - wordpiece_ends=None, - left_buffer=0, - right_buffer=0, ): gradients = np.zeros_like(log_probs) B_tgt, max_T, max_U, D = log_probs.shape @@ -220,35 +121,13 @@ def compute( seq_log_probs = log_probs[b_tgt, :T, :U, :] seq_targets = targets[b_tgt, : int(target_lengths[b_tgt])] - if wordpiece_ends is not None: - seq_wordpiece_ends = wordpiece_ends[b_tgt, : int(target_lengths[b_tgt]) + 1] - alpha, alpha_cost = __class__.compute_alpha_one_sequence_restricted( - log_probs=seq_log_probs, - targets=seq_targets, - blank=blank, - wordpiece_ends=seq_wordpiece_ends, - left_buffer=left_buffer, - right_buffer=right_buffer, - ) - else: - alpha, alpha_cost = __class__.compute_alpha_one_sequence( - log_probs=seq_log_probs, targets=seq_targets, blank=blank - ) + alpha, alpha_cost = __class__.compute_alpha_one_sequence( + log_probs=seq_log_probs, targets=seq_targets, blank=blank + ) - if wordpiece_ends is not None: - seq_wordpiece_ends = wordpiece_ends[b_tgt, : int(target_lengths[b_tgt]) + 1] - beta, beta_cost = __class__.compute_beta_one_sequence_restricted( - log_probs=seq_log_probs, - targets=seq_targets, - blank=blank, - wordpiece_ends=seq_wordpiece_ends, - left_buffer=left_buffer, - right_buffer=right_buffer, - ) - else: - beta, beta_cost = __class__.compute_beta_one_sequence( - log_probs=seq_log_probs, targets=seq_targets, blank=blank - ) + beta, beta_cost = __class__.compute_beta_one_sequence( + log_probs=seq_log_probs, targets=seq_targets, blank=blank + ) seq_gradients = __class__.compute_gradients_one_sequence( log_probs=seq_log_probs, @@ -277,9 +156,6 @@ def forward( logit_lengths, target_lengths, targets, - wordpiece_ends=None, - left_buffer=0, - right_buffer=0, ): log_probs = torch.nn.functional.log_softmax(logits, dim=-1) return _NumpyTransducer.apply( @@ -288,119 +164,4 @@ def forward( target_lengths, targets, self.blank, - wordpiece_ends, - left_buffer, - right_buffer, ) - - -class AlignmentRestrictionCheck(object): - """ - Helper class which returns locations where - blank / emit transitions are valid while - updating alpha / betas for Alignment - Restricted RNN Transducer loss. This class - will help test c++ code, the correctness has been - verified by thorough manual inspections in n268104 - - """ - - def __init__(self, U, T, wordpiece_ends, left_buffer, right_buffer): - self.U = U - self.T = T - # assume word_ends contains the ground truth end - # timestep of every word piece. - # assume 0th wordpiece_ends is and its endtime is 0 - assert wordpiece_ends[0] == 0 - assert len(wordpiece_ends) == U - self.wordpiece_ends = wordpiece_ends - self.left_buffer = left_buffer - self.right_buffer = right_buffer - - def valid_time_ranges(self, u): - # Returns ranges of valid paths which satisfy - # word boundary constraints - # For bos ranges are valid from 0 until end time of - # 1st symbol + right_buffer - start = max(self.wordpiece_ends[u] - self.left_buffer, 0) - if u == self.U - 1: - end = self.T - 1 - else: - end = min(self.wordpiece_ends[u + 1] + self.right_buffer, self.T - 1) - - return start, end - - def alpha_blank_transition(self, t, u): - # Examine if doing blank transition into (t, u) - # is allowed while updating alphas. - if u == 0 and t == 0: - return False - - # For alphas blank transitions are valid from: - # start time when current symbol is emitted - start = max(self.wordpiece_ends[u] - self.left_buffer + 1, 1) - - # For alphas blank transitions are valid until - # last timestep we can emit next symbol - if u == self.U - 1: - # for last symbol, allow blank transitions till end - end = self.T - 1 - else: - end = min(self.wordpiece_ends[u + 1] + self.right_buffer, self.T - 1) - - return start <= t and t <= end - - def alpha_emit_transition(self, t, u): - # Examine if doing emit transition into (t, u) - # is allowed while updating alphas. - if u == 0: - # emit transitions into (t, 0) for alpha are invalid - return False - - # For alphas emit are valid starting from: - # first time when current symbol can be emitted - start = max(self.wordpiece_ends[u] - self.left_buffer, 0) - - # For alphas emit are valid until: - # last timestep when current symbol can be emitted - end = min(self.wordpiece_ends[u] + self.right_buffer, self.T - 1) - - return start <= t and t <= end - - def beta_blank_transition(self, t, u): - # Examine if doing blank transition into (t, u) - # is allowed while updating betas. - - # for beta, blanks transitions are can start - # first timestep when we emit previous symbol - start = max(self.wordpiece_ends[u] - self.left_buffer, 0) - - # for beta, blanks transitions are valid until - # last timestep we can emit current symbol - # note: T-2, we init beta[-1, -1] by log_prob[-1, -1, blank] - if u == self.U - 1: - end = self.T - 2 - else: - # we cannot transition into beta for T-1 - end = min(self.wordpiece_ends[u + 1] + self.right_buffer - 1, self.T - 2) - - return start <= t and t <= end - - def beta_emit_transition(self, t, u): - # Examine if doing emit transition into (t, u) - # is allowed while updating betas - - # for last symbol, we do not allow emit transition, - # so beta into u-1, t is invalid - if u == self.U - 1: - return False - - # For betas we allow emit transition starting from - # first time we can emit next symbol - start = max(0, self.wordpiece_ends[u + 1] - self.left_buffer) - - # For betas we allow emit transitions to end with - # last time we can emit next symbol - end = min(self.wordpiece_ends[u + 1] + self.right_buffer, self.T - 1) - - return start <= t and t <= end diff --git a/test/torchaudio_unittest/rnnt/rnnt_loss_cuda_test.py b/test/torchaudio_unittest/rnnt/rnnt_loss_cuda_test.py index ea6e8eb513..c64fd687fe 100644 --- a/test/torchaudio_unittest/rnnt/rnnt_loss_cuda_test.py +++ b/test/torchaudio_unittest/rnnt/rnnt_loss_cuda_test.py @@ -1,5 +1,5 @@ import torch -from .rnnt_loss_impl import RNNTLossTest, RNNTLossCUDAOnly +from .rnnt_loss_impl import RNNTLossTest from torchaudio_unittest import common_utils from .utils import skipIfNoTransducer @@ -8,9 +8,3 @@ @common_utils.skipIfNoCuda class TestRNNTLoss(RNNTLossTest, common_utils.PytorchTestCase): device = torch.device('cuda') - - -@skipIfNoTransducer -@common_utils.skipIfNoCuda -class TestRNNTLossCUDAOnly(RNNTLossCUDAOnly, common_utils.PytorchTestCase): - device = torch.device('cuda') diff --git a/test/torchaudio_unittest/rnnt/rnnt_loss_impl.py b/test/torchaudio_unittest/rnnt/rnnt_loss_impl.py index dcab6def6f..2ac4d0836f 100644 --- a/test/torchaudio_unittest/rnnt/rnnt_loss_impl.py +++ b/test/torchaudio_unittest/rnnt/rnnt_loss_impl.py @@ -1,12 +1,5 @@ import numpy as np -import torch -from torchaudio.prototype.rnnt_loss import ( - RNNTLoss, - _rnnt_loss_alphas, - _rnnt_loss_betas, -) - -from .numpy_transducer import _NumpyTransducer +from torchaudio.prototype.rnnt_loss import RNNTLoss from .utils import ( compute_with_numpy_transducer, @@ -19,8 +12,6 @@ numpy_to_torch, ) -from torchaudio_unittest.common_utils import skipIfNoCuda - class RNNTLossTest: def _test_costs_and_gradients( @@ -108,281 +99,18 @@ def test_costs_and_gradients_random_data_with_numpy_fp32(self): data=data, ref_costs=ref_costs, ref_gradients=ref_gradients ) - def test_alphas_restricted_B1_T10_U3_D4(self): - for random in [True, False]: - for left_buffer in [0, 2, 10]: - for right_buffer in [0, 1, 2, 10]: - data = get_B1_T10_U3_D4_data(random=random) - logits = torch.tensor(data["logits"]) - log_probs = torch.nn.functional.log_softmax(logits, dim=-1).numpy() - ( - np_gradients, - np_costs, - np_alphas, - np_betas, - ) = _NumpyTransducer.compute( - log_probs=log_probs, - logit_lengths=data["logit_lengths"], - target_lengths=data["target_lengths"], - targets=data["targets"], - blank=data["blank"], - wordpiece_ends=data["wordpiece_ends"], - left_buffer=left_buffer, - right_buffer=right_buffer, - ) - - data = numpy_to_torch( - data=data, device=self.device, requires_grad=True - ) - alphas = _rnnt_loss_alphas( - logits=data["logits"], - logit_lengths=data["logit_lengths"], - target_lengths=data["target_lengths"], - targets=data["targets"], - wordpiece_ends=data.get("wordpiece_ends", None), - blank=data["blank"], - left_buffer=left_buffer, - right_buffer=right_buffer, - ) - np.testing.assert_allclose( - alphas.cpu().data.numpy(), np_alphas, atol=1e-6, rtol=1e-2 - ) - - def test_betas_restricted_B1_T10_U3_D4(self): - for random in [True, False]: - for left_buffer in [0, 2, 10]: - for right_buffer in [0, 1, 2, 10]: - data = get_B1_T10_U3_D4_data(random=random) - logits = torch.tensor(data["logits"]) - log_probs = torch.nn.functional.log_softmax(logits, dim=-1).numpy() - ( - np_gradients, - np_costs, - np_alphas, - np_betas, - ) = _NumpyTransducer.compute( - log_probs=log_probs, - logit_lengths=data["logit_lengths"], - target_lengths=data["target_lengths"], - targets=data["targets"], - blank=data["blank"], - wordpiece_ends=data["wordpiece_ends"], - left_buffer=left_buffer, - right_buffer=right_buffer, - ) - - data = numpy_to_torch( - data=data, device=self.device, requires_grad=True - ) - betas = _rnnt_loss_betas( - logits=data["logits"], - logit_lengths=data["logit_lengths"], - target_lengths=data["target_lengths"], - targets=data["targets"], - wordpiece_ends=data.get("wordpiece_ends", None), - blank=data["blank"], - left_buffer=left_buffer, - right_buffer=right_buffer, - ) - np.testing.assert_allclose( - betas.cpu().data.numpy(), np_betas, atol=1e-6, rtol=1e-2 - ) - - def test_rnnt_restricted_B1_T10_U3_D4(self): - for left_buffer in [0, 1, 10]: - for right_buffer in [0, 1, 2, 5, 10]: - data = get_B1_T10_U3_D4_data(random=False) - data = numpy_to_torch( - data=data, device=self.device, requires_grad=True - ) - data["left_buffer"] = left_buffer - data["right_buffer"] = right_buffer - ref_costs, ref_gradients = compute_with_numpy_transducer( - data=data - ) - self._test_costs_and_gradients( - data=data, ref_costs=ref_costs, ref_gradients=ref_gradients - ) - - def test_rnnt_restricted_B2_T4_U3_D3(self): - # Note - this test just ensures that the numpy and c++ implementations match. - # Probably a hand constructed test for gradients will be more thorough - data, _, _ = get_numpy_data_B2_T4_U3_D3(dtype=np.float32) - data = numpy_to_torch(data=data, device=self.device, requires_grad=True) - data["wordpiece_ends"] = torch.tensor([[0, 1, 2], [0, 1, 2]]).int() - - for left_buffer in [0]: - for right_buffer in [0, 1, 2]: - data["left_buffer"] = left_buffer - data["right_buffer"] = right_buffer - ref_costs, ref_gradients = compute_with_numpy_transducer( - data=data - ) - - self._test_costs_and_gradients( - data=data, ref_costs=ref_costs, ref_gradients=ref_gradients - ) - - def test_restricted_parity_with_unrestricted_B1_T10_U3_D4(self): - for random in [False, True]: - data = get_B1_T10_U3_D4_data(random=random) - data = numpy_to_torch(data=data, device=self.device, requires_grad=True) - wordpiece_ends = data["wordpiece_ends"] - del data["wordpiece_ends"] - ref_costs, ref_gradients = compute_with_pytorch_transducer(data=data) - data["wordpiece_ends"] = wordpiece_ends - data["left_buffer"] = 100 - data["right_buffer"] = 100 - wp_costs, wp_gradients = compute_with_pytorch_transducer(data=data) - np.testing.assert_allclose(ref_costs, wp_costs, atol=1e-2, rtol=1e-2) - np.testing.assert_allclose( - ref_gradients, wp_gradients, atol=1e-2, rtol=1e-2 - ) - - def test_restricted_parity_with_unrestricted_alpha_B1_T10_U3_D4(self): - for random in [False, True]: - data = get_B1_T10_U3_D4_data(random=random) - data = numpy_to_torch(data=data, device=self.device, requires_grad=True) - - ref_alphas = _rnnt_loss_alphas( - blank=data["blank"], - logits=data["logits"], - logit_lengths=data["logit_lengths"], - target_lengths=data["target_lengths"], - targets=data["targets"], - ) - - wp_alphas = _rnnt_loss_alphas( - blank=data["blank"], - left_buffer=100, - right_buffer=100, - logits=data["logits"], - logit_lengths=data["logit_lengths"], - target_lengths=data["target_lengths"], - targets=data["targets"], - wordpiece_ends=data["wordpiece_ends"], - ) - np.testing.assert_allclose( - ref_alphas.cpu().data.numpy(), - wp_alphas.cpu().data.numpy(), - atol=1e-2, - rtol=1e-2, - ) - - def test_restricted_parity_with_unrestricted_beta_B1_T10_U3_D4(self): + def test_rnnt_nonfused_log_softmax(self): for random in [False, True]: - data = get_B1_T10_U3_D4_data(random=random) - data = numpy_to_torch(data=data, device=self.device, requires_grad=True) - - ref_betas = _rnnt_loss_betas( - blank=data["blank"], - logits=data["logits"], - logit_lengths=data["logit_lengths"], - target_lengths=data["target_lengths"], - targets=data["targets"], - ) - wp_betas = _rnnt_loss_betas( - blank=data["blank"], - left_buffer=100, - right_buffer=100, - logits=data["logits"], - logit_lengths=data["logit_lengths"], - target_lengths=data["target_lengths"], - targets=data["targets"], - wordpiece_ends=data["wordpiece_ends"], - ) - np.testing.assert_allclose( - ref_betas.cpu().data.numpy(), - wp_betas.cpu().data.numpy(), - atol=1e-2, - rtol=1e-2, - ) - - -@skipIfNoCuda -class RNNTLossCUDAOnly: - def _test_costs_and_gradients( - self, data, ref_costs, ref_gradients, atol=1e-6, rtol=1e-2 - ): - logits_shape = data["logits"].shape - for reuse_logits_for_grads in [False, True]: - with self.subTest(reuse_logits_for_grads=reuse_logits_for_grads): - costs, gradients = compute_with_pytorch_transducer( - data=data, reuse_logits_for_grads=reuse_logits_for_grads - ) - np.testing.assert_allclose(costs, ref_costs, atol=atol, rtol=rtol) - self.assertEqual(logits_shape, gradients.shape) - if not np.allclose(gradients, ref_gradients, atol=atol, rtol=rtol): - for b in range(len(gradients)): - T = data["logit_lengths"][b] - U = data["target_lengths"][b] - for t in range(gradients.shape[1]): - for u in range(gradients.shape[2]): - np.testing.assert_allclose( - gradients[b, t, u], - ref_gradients[b, t, u], - atol=atol, - rtol=rtol, - err_msg=f"failed on b={b}, t={t}/T={T}, u={u}/U={U}", - ) - - def test_nan_logits(self): - for reuse_logits_for_grads in [False, True]: data = get_B1_T10_U3_D4_data( - random=True, left_buffer=10, right_buffer=10, nan=True + random=random, ) data = numpy_to_torch( data=data, device=self.device, requires_grad=True ) - data["left_buffer"] = 10 - data["right_buffer"] = 10 - costs, gradients = compute_with_pytorch_transducer( - data=data, reuse_logits_for_grads=reuse_logits_for_grads + data["fused_log_softmax"] = False + ref_costs, ref_gradients = compute_with_numpy_transducer( + data=data ) - self.assertTrue(np.all(costs == 0)) - self.assertTrue(np.all(gradients == 0)) - - def test_rnnt_restricted_betas_with_random_data(self): - for u in range(50, 60): - data = get_numpy_random_data(max_B=5, max_T=499, max_U=u, max_D=4096) - data = numpy_to_torch( - data=data, device=self.device, requires_grad=True - ) - targets = data["targets"] - target_lengths = data["target_lengths"] - B, max_U = targets.size() - wordpiece_ends = np.zeros((B, max_U + 1), dtype=np.int32) - for b in range(B): - u = target_lengths[b] - wordpiece_ends[b, : u + 1] = np.array([0] + list(range(u)), dtype=np.int32) - wordpiece_ends = torch.from_numpy(wordpiece_ends) - _ = _rnnt_loss_betas( - logits=data["logits"], - logit_lengths=data["logit_lengths"], - target_lengths=data["target_lengths"], - targets=data["targets"], - wordpiece_ends=wordpiece_ends, - blank=4095, + self._test_costs_and_gradients( + data=data, ref_costs=ref_costs, ref_gradients=ref_gradients ) - - def test_rnnt_nonfused_log_softmax(self): - for random in [False, True]: - for left_buffer in [1, 2, 10]: - for right_buffer in [1, 2, 5, 10]: - data = get_B1_T10_U3_D4_data( - random=random, - left_buffer=left_buffer, - right_buffer=right_buffer, - ) - data = numpy_to_torch( - data=data, device=self.device, requires_grad=True - ) - data["left_buffer"] = left_buffer - data["right_buffer"] = right_buffer - data["fused_log_softmax"] = False - ref_costs, ref_gradients = compute_with_numpy_transducer( - data=data - ) - self._test_costs_and_gradients( - data=data, ref_costs=ref_costs, ref_gradients=ref_gradients - ) diff --git a/test/torchaudio_unittest/rnnt/utils.py b/test/torchaudio_unittest/rnnt/utils.py index d8030c4989..8e93d28032 100644 --- a/test/torchaudio_unittest/rnnt/utils.py +++ b/test/torchaudio_unittest/rnnt/utils.py @@ -4,10 +4,7 @@ import torch from torchaudio.prototype.rnnt_loss import RNNTLoss -from .numpy_transducer import ( - AlignmentRestrictionCheck, - NumpyTransducerLoss, -) +from .numpy_transducer import NumpyTransducerLoss def compute_with_numpy_transducer(data): @@ -18,9 +15,6 @@ def compute_with_numpy_transducer(data): logit_lengths=data["logit_lengths"], target_lengths=data["target_lengths"], targets=data["targets"], - wordpiece_ends=data.get("wordpiece_ends", None), - left_buffer=data.get("left_buffer", 0), - right_buffer=data.get("right_buffer", 0), ) loss = torch.sum(costs) @@ -33,13 +27,8 @@ def compute_with_numpy_transducer(data): def compute_with_pytorch_transducer(data, reuse_logits_for_grads=False): - left_buffer = data.get("left_buffer", 0) - right_buffer = data.get("right_buffer", 0) - costs = RNNTLoss( blank=data["blank"], - left_buffer=left_buffer, - right_buffer=right_buffer, fused_log_softmax=data.get("fused_log_softmax", True), reuse_logits_for_grads=reuse_logits_for_grads, )( @@ -47,7 +36,6 @@ def compute_with_pytorch_transducer(data, reuse_logits_for_grads=False): logit_lengths=data["logit_lengths"], target_lengths=data["target_lengths"], targets=data["targets"], - wordpiece_ends=data.get("wordpiece_ends", None), ) loss = torch.sum(costs) @@ -95,8 +83,6 @@ def get_data_basic(device): def get_B1_T10_U3_D4_data( random=False, - left_buffer=0, - right_buffer=0, dtype=np.float32, nan=False, ): @@ -112,7 +98,6 @@ def get_B1_T10_U3_D4_data( data["target_lengths"] = np.array([2, 2], dtype=np.int32) data["targets"] = np.array([[1, 2], [1, 2]], dtype=np.int32) data["blank"] = 0 - data["wordpiece_ends"] = np.array([[0, 2, 7], [0, 2, 7]], dtype=np.int32) return data @@ -425,8 +410,6 @@ def numpy_to_torch(data, device, requires_grad=True): logit_lengths = torch.from_numpy(data["logit_lengths"]) target_lengths = torch.from_numpy(data["target_lengths"]) - if "wordpiece_ends" in data: - data["wordpiece_ends"] = torch.from_numpy(data["wordpiece_ends"]).to(device=device) if "nbest_wers" in data: data["nbest_wers"] = torch.from_numpy(data["nbest_wers"]).to(device=device) if "nbest_scores" in data: diff --git a/torchaudio/csrc/rnnt/compute.cpp b/torchaudio/csrc/rnnt/compute.cpp index 5ca69a24c7..91ce8cceb6 100644 --- a/torchaudio/csrc/rnnt/compute.cpp +++ b/torchaudio/csrc/rnnt/compute.cpp @@ -7,9 +7,6 @@ TORCH_LIBRARY_FRAGMENT(torchaudio, m) { "Tensor tgt_lengths," "int blank," "float clamp," - "Tensor? wp_ends=None," - "int l_buffer=0," - "int r_buffer=0," "bool fused_log_smax=True," "bool reuse_logits_for_grads=True) -> (Tensor, Tensor?)"); } diff --git a/torchaudio/csrc/rnnt/compute_alphas.cpp b/torchaudio/csrc/rnnt/compute_alphas.cpp index 80d53995cc..a52d49b8a1 100644 --- a/torchaudio/csrc/rnnt/compute_alphas.cpp +++ b/torchaudio/csrc/rnnt/compute_alphas.cpp @@ -6,8 +6,5 @@ TORCH_LIBRARY_FRAGMENT(torchaudio, m) { "Tensor src_lengths," "Tensor tgt_lengths," "int blank," - "float clamp," - "Tensor? wp_ends=None," - "int l_buffer=0," - "int r_buffer=0) -> Tensor"); + "float clamp) -> Tensor"); } diff --git a/torchaudio/csrc/rnnt/compute_betas.cpp b/torchaudio/csrc/rnnt/compute_betas.cpp index f4312c59cf..234dd909b5 100644 --- a/torchaudio/csrc/rnnt/compute_betas.cpp +++ b/torchaudio/csrc/rnnt/compute_betas.cpp @@ -6,8 +6,5 @@ TORCH_LIBRARY_FRAGMENT(torchaudio, m) { "Tensor src_lengths," "Tensor tgt_lengths," "int blank," - "float clamp," - "Tensor? wp_ends=None," - "int l_buffer=0," - "int r_buffer=0) -> Tensor"); + "float clamp) -> Tensor"); } diff --git a/torchaudio/csrc/rnnt/cpu/alignment_restrictions.cpp b/torchaudio/csrc/rnnt/cpu/alignment_restrictions.cpp deleted file mode 100644 index abef70409d..0000000000 --- a/torchaudio/csrc/rnnt/cpu/alignment_restrictions.cpp +++ /dev/null @@ -1,98 +0,0 @@ -#include - -namespace torchaudio { -namespace rnnt { -namespace cpu { - -void AlignmentRestrictionCheck::validTimeRanges( - const int u, - int& t_start, - int& t_end) { - t_start = std::max(wpEnds_[u] - lBuffer_, 0); - t_end = (u == U - 1) ? T - 1 : std::min(wpEnds_[u + 1] + rBuffer_, T - 1); - return; -} - -bool AlignmentRestrictionCheck::alphaBlankTransition( - const int t, - const int u) { - if (u == 0 && t == 0) { - return false; - } - - // for alpha blank updates we move from left to right - // blank transitions are valid from: - // start time when current symbol is emitted - // **offset to right by 1** - int start = std::max(wpEnds_[u] - lBuffer_ + 1, 1); - - // blank transitions are valid until: - // for U-1: last allowed timestep i.e. T - 1 - // for other cases: last time we may emit the next symbol - int end = (u == U - 1) ? T - 1 : std::min(wpEnds_[u + 1] + rBuffer_, T - 1); - - return start <= t && t <= end; -} - -bool AlignmentRestrictionCheck::alphaEmitTransition( - const int t, - const int u) { - // For alphas we move from bottom to top - // emit transitions into (t, 0) for alpha are invalid - if (u == 0) { - return false; - } - - // For alphas emit are valid starting from: - // first time when current symbol can be emitted - int start = std::max(wpEnds_[u] - lBuffer_, 0); - - // For alphas emit are valid until: - // last timestep when current symbol can be emitted - int end = std::min(wpEnds_[u] + rBuffer_, T - 1); - - return start <= t && t <= end; -} - -bool AlignmentRestrictionCheck::betaBlankTransition( - const int t, - const int u) { - // For updating betas with blank transition - // we move from right to left - - // for beta, blanks transitions are can start - // first timestep when we emit previous symbol - int start = std::max(wpEnds_[u] - lBuffer_, 0); - - // for beta, blanks transitions are valid until - // we can emit current symbol **offset to left by 1** - // note: T-2, we init beta[-1, -1] by log_prob[-1, -1, blank] - int end = - (u == U - 1) ? T - 2 : std::min(wpEnds_[u + 1] + rBuffer_ - 1, T - 2); - - return start <= t && t <= end; -} - -bool AlignmentRestrictionCheck::betaEmitTransition(const int t, const int u) { - // While updating betas we go from top to bottom. - - // for last symbol, we do not allow emit transition, - // so beta into u-1, t is invalid - if (u == U - 1) { - return false; - } - - // For betas we allow emit transition starting from - // first time we can emit next symbol - int start = std::max(0, wpEnds_[u + 1] - lBuffer_); - - // For betas we allow emit transitions to end with - // last time we can emit next symbol - int end = std::min(wpEnds_[u + 1] + rBuffer_, T - 1); - - return start <= t and t <= end; -} - -} // namespace cpu -} // namespace rnnt -} // namespace torchaudio diff --git a/torchaudio/csrc/rnnt/cpu/alignment_restrictions.h b/torchaudio/csrc/rnnt/cpu/alignment_restrictions.h deleted file mode 100644 index 0c265b10be..0000000000 --- a/torchaudio/csrc/rnnt/cpu/alignment_restrictions.h +++ /dev/null @@ -1,62 +0,0 @@ -#pragma once -#include -#include - -namespace torchaudio { -namespace rnnt { -namespace cpu { - -// Helper class which returns locations where -// blank / emit transitions are valid while -// updating alpha / betas for Alignment -// Restricted Transducer loss -class AlignmentRestrictionCheck { - public: - AlignmentRestrictionCheck( - const int* wpEnds, - int T, - int U, - int lBuffer, - int rBuffer) - : wpEnds_(wpEnds), T(T), U(U), lBuffer_(lBuffer), rBuffer_(rBuffer) { - } - - // Returns ranges of valid timesteps which satisfy - // alignment boundary constraints - void validTimeRanges(const int u, int& t_start, int& t_end); - - // Examine if doing blank transition into (t, u) - // is allowed while updating alphas - // Note that while doing blank transitions for alpha - // we move from left to right - bool alphaBlankTransition(const int t, const int u); - - // Examine if doing emit transition into (t, u) - // is allowed while updating alphas - // Note that while doing emit transitions for alpha - // we move from bottom to top - bool alphaEmitTransition(const int t, const int u); - - // Examine if doing blank transition into (t, u) - // is allowed while updating betas - // Note that while doing blank transitions for beta - // we move from right to left - bool betaBlankTransition(const int t, const int u); - - // Examine if doing emit transition into (t, u) - // is allowed while updating betas - // Note that while doing emit transitions for beta - // we move from top to bottom - bool betaEmitTransition(const int t, const int u); - - private: - const int* wpEnds_; - int T; - int U; - int lBuffer_; - int rBuffer_; -}; - -} // namespace cpu -} // namespace rnnt -} // namespace torchaudio diff --git a/torchaudio/csrc/rnnt/cpu/compute.cpp b/torchaudio/csrc/rnnt/cpu/compute.cpp index c8002c3bff..1cd9801d18 100644 --- a/torchaudio/csrc/rnnt/cpu/compute.cpp +++ b/torchaudio/csrc/rnnt/cpu/compute.cpp @@ -13,9 +13,6 @@ std::tuple> compute( const torch::Tensor& tgt_lengths, int64_t blank, double clamp, - const c10::optional& wp_ends = c10::nullopt, - int64_t l_buffer = 0, - int64_t r_buffer = 0, bool fused_log_smax = true, bool reuse_logits_for_grads = true) { @@ -27,8 +24,6 @@ std::tuple> compute( options.numTargets_ = logits.size(3); options.blank_ = blank; options.clamp_ = clamp; - options.lBuffer_ = l_buffer; - options.rBuffer_ = r_buffer; options.fusedLogSmax_ = fused_log_smax; CHECK_EQ(logits.device().type(), torch::DeviceType::CPU); @@ -71,8 +66,7 @@ std::tuple> compute( /*src_lengths=*/src_lengths.data(), /*tgt_lengths=*/tgt_lengths.data(), /*costs=*/costs.data(), - /*gradients=*/(gradients == c10::nullopt)? nullptr : gradients->data(), - /*wp_ends=*/(wp_ends == c10::nullopt)? nullptr : wp_ends->data()); + /*gradients=*/(gradients == c10::nullopt)? nullptr : gradients->data()); break; } case torch::ScalarType::Half: @@ -84,8 +78,7 @@ std::tuple> compute( /*src_lengths=*/src_lengths.data(), /*tgt_lengths=*/tgt_lengths.data(), /*costs=*/costs.data(), - /*gradients=*/(gradients == c10::nullopt)? nullptr : gradients->data(), - /*wp_ends=*/(wp_ends == c10::nullopt)? nullptr : wp_ends->data()); + /*gradients=*/(gradients == c10::nullopt)? nullptr : gradients->data()); break; } default: diff --git a/torchaudio/csrc/rnnt/cpu/compute_alphas.cpp b/torchaudio/csrc/rnnt/cpu/compute_alphas.cpp index 7bc462c239..fed1dec5cd 100644 --- a/torchaudio/csrc/rnnt/cpu/compute_alphas.cpp +++ b/torchaudio/csrc/rnnt/cpu/compute_alphas.cpp @@ -11,10 +11,7 @@ torch::Tensor compute_alphas( const torch::Tensor& src_lengths, const torch::Tensor& tgt_lengths, int64_t blank, - double clamp, - const c10::optional& wp_ends = c10::nullopt, - int64_t l_buffer = 0, - int64_t r_buffer = 0) { + double clamp) { Options options; options.batchSize_ = src_lengths.size(0); options.nHypos_ = tgt_lengths.size(0) / src_lengths.size(0); @@ -23,8 +20,6 @@ torch::Tensor compute_alphas( options.numTargets_ = logits.size(3); options.blank_ = blank; options.clamp_ = clamp; - options.lBuffer_ = l_buffer; - options.rBuffer_ = r_buffer; CHECK_EQ(logits.device().type(), torch::DeviceType::CPU); options.device_ = CPU; @@ -62,8 +57,7 @@ torch::Tensor compute_alphas( /*targets=*/targets.data(), /*src_lengths=*/src_lengths.data(), /*tgt_lengths=*/tgt_lengths.data(), - /*alphas=*/alphas.data(), - /*wp_ends=*/(wp_ends == c10::nullopt) ? nullptr : wp_ends->data()); + /*alphas=*/alphas.data()); return alphas; } diff --git a/torchaudio/csrc/rnnt/cpu/compute_betas.cpp b/torchaudio/csrc/rnnt/cpu/compute_betas.cpp index 1c7e3d187a..3789dec895 100644 --- a/torchaudio/csrc/rnnt/cpu/compute_betas.cpp +++ b/torchaudio/csrc/rnnt/cpu/compute_betas.cpp @@ -11,10 +11,7 @@ torch::Tensor compute_betas( const torch::Tensor& src_lengths, const torch::Tensor& tgt_lengths, int64_t blank, - double clamp, - const c10::optional& wp_ends = c10::nullopt, - int64_t l_buffer = 0, - int64_t r_buffer = 0) { + double clamp) { Options options; options.batchSize_ = src_lengths.size(0); options.nHypos_ = tgt_lengths.size(0) / src_lengths.size(0); @@ -23,8 +20,6 @@ torch::Tensor compute_betas( options.numTargets_ = logits.size(3); options.blank_ = blank; options.clamp_ = clamp; - options.lBuffer_ = l_buffer; - options.rBuffer_ = r_buffer; CHECK_EQ(logits.device().type(), torch::DeviceType::CPU); options.device_ = CPU; @@ -67,8 +62,7 @@ torch::Tensor compute_betas( /*src_lengths=*/src_lengths.data(), /*tgt_lengths=*/tgt_lengths.data(), /*costs=*/costs.data(), - /*betas=*/betas.data(), - /*wp_ends=*/(wp_ends == c10::nullopt) ? nullptr : wp_ends->data()); + /*betas=*/betas.data()); return betas; } diff --git a/torchaudio/csrc/rnnt/cpu/cpu_kernels.h b/torchaudio/csrc/rnnt/cpu/cpu_kernels.h index 6d2084d24d..bb63b97ce2 100644 --- a/torchaudio/csrc/rnnt/cpu/cpu_kernels.h +++ b/torchaudio/csrc/rnnt/cpu/cpu_kernels.h @@ -1,6 +1,5 @@ #pragma once -#include #include #include #include @@ -187,67 +186,6 @@ DTYPE ComputeAlphaOneSequence( return forward_score; } -template -DTYPE ComputeAlphaOneSequenceRestricted( - const Options& options, - TensorView>& logProbs, - int srcLen, - int tgtLen, - TensorView& alpha, - const int* wpEnds) { - const int& T = srcLen; - const int& U = tgtLen; - - const int& lBuffer = options.lBuffer_; - const int& r_buffer = options.rBuffer_; - - AlignmentRestrictionCheck check(wpEnds, T, U, lBuffer, r_buffer); - - for (int t = 0; t < T; t++) { - for (int u = 0; u < U; u++) { - alpha({t, u}) = DTYPE(-INFINITY); - } - } - alpha({0, 0}) = DTYPE(0); - - for (int t = 1; t < T; ++t) { // u == 0. - if (!check.alphaBlankTransition(t, 0)) { - break; - } - alpha({t, 0}) = alpha({t - 1, 0}) + logProbs({t - 1, 0}).skip(); - } - - for (int u = 1; u < U; ++u) { // t == 0. - if (!check.alphaEmitTransition(0, u)) { - break; - } - alpha({0, u}) = alpha({0, u - 1}) + logProbs({0, u - 1}).emit(); - } - - for (int u = 1; u < U; ++u) { - int start_t = 0, end_t = 0; - check.validTimeRanges(u, start_t, end_t); - for (int t = start_t; t < end_t + 1; ++t) { - DTYPE skip = DTYPE(-INFINITY), emit = DTYPE(-INFINITY); - - if (check.alphaBlankTransition(t, u)) { - skip = alpha({t - 1, u}) + logProbs({t - 1, u}).skip(); - } - - if (check.alphaEmitTransition(t, u)) { - emit = alpha({t, u - 1}) + logProbs({t, u - 1}).emit(); - } - - if (skip != DTYPE(-INFINITY) || emit != DTYPE(-INFINITY)) { - alpha({t, u}) = math::lse(skip, emit); - } - } - } - DTYPE forward_score = alpha({T - 1, U - 1}) + logProbs({T - 1, U - 1}).skip(); - - return forward_score; -} - template DTYPE ComputeBetaOneSequence( const Options& options, @@ -281,64 +219,6 @@ DTYPE ComputeBetaOneSequence( return backward_score; } -template -DTYPE ComputeBetaOneSequenceRestricted( - const Options& options, - TensorView>& logProbs, - int srcLen, - int tgtLen, - TensorView& beta, - const int* wpEnds = nullptr) { - const int& T = srcLen; - const int& U = tgtLen; - const int& lBuffer = options.lBuffer_; - const int& r_buffer = options.rBuffer_; - AlignmentRestrictionCheck check(wpEnds, T, U, lBuffer, r_buffer); - - for (int t = 0; t < T; t++) { - for (int u = 0; u < U; u++) { - beta({t, u}) = DTYPE(-INFINITY); - } - } - - beta({T - 1, U - 1}) = logProbs({T - 1, U - 1}).skip(); - - for (int t = T - 2; t >= 0; --t) { // u == U - 1. - if (!check.betaBlankTransition(t, U - 1)) { - break; - } - beta({t, U - 1}) = beta({t + 1, U - 1}) + logProbs({t, U - 1}).skip(); - } - - for (int u = U - 2; u >= 0; --u) { // t == T - 1. - if (!check.betaEmitTransition(T - 1, u)) { - break; - } - beta({T - 1, u}) = beta({T - 1, u + 1}) + logProbs({T - 1, u}).emit(); - } - for (int u = U - 2; u >= 0; --u) { - int start_t = 0, end_t = 0; - check.validTimeRanges(u, start_t, end_t); - for (int t = end_t; t >= start_t; --t) { - DTYPE skip = DTYPE(-INFINITY), emit = DTYPE(-INFINITY); - if (check.betaBlankTransition(t, u)) { - skip = beta({t + 1, u}) + logProbs({t, u}).skip(); - } - - if (check.betaEmitTransition(t, u)) { - emit = beta({t, u + 1}) + logProbs({t, u}).emit(); - } - - if (skip != DTYPE(-INFINITY) || emit != DTYPE(-INFINITY)) { - beta({t, u}) = math::lse(skip, emit); - } - } - } - DTYPE backward_score = beta({0, 0}); - - return backward_score; -} - template DTYPE ComputeAlphaOrBetaOneSequence( int thread, @@ -347,42 +227,21 @@ DTYPE ComputeAlphaOrBetaOneSequence( int srcLen, int tgtLen, TensorView& alpha, - TensorView& beta, - const int* wpEnds = nullptr) { - if (wpEnds == nullptr) { - if (thread & 1) { - return ComputeAlphaOneSequence( - /*options=*/options, - /*logProbs=*/logProbs, - /*srcLen=*/srcLen, - /*tgtLen=*/tgtLen, - /*alpha=*/alpha); - } else { - return ComputeBetaOneSequence( - /*options=*/options, - /*logProbs=*/logProbs, - /*srcLen=*/srcLen, - /*tgtLen=*/tgtLen, - /*beta=*/beta); - } + TensorView& beta) { + if (thread & 1) { + return ComputeAlphaOneSequence( + /*options=*/options, + /*logProbs=*/logProbs, + /*srcLen=*/srcLen, + /*tgtLen=*/tgtLen, + /*alpha=*/alpha); } else { - if (thread & 1) { - return ComputeAlphaOneSequenceRestricted( - /*options=*/options, - /*logProbs=*/logProbs, - /*srcLen=*/srcLen, - /*tgtLen=*/tgtLen, - /*alpha=*/alpha, - /*wpEnds=*/wpEnds); - } else { - return ComputeBetaOneSequenceRestricted( - /*options=*/options, - /*logProbs=*/logProbs, - /*srcLen=*/srcLen, - /*tgtLen=*/tgtLen, - /*beta=*/beta, - /*wpEnds=*/wpEnds); - } + return ComputeBetaOneSequence( + /*options=*/options, + /*logProbs=*/logProbs, + /*srcLen=*/srcLen, + /*tgtLen=*/tgtLen, + /*beta=*/beta); } } @@ -394,12 +253,10 @@ void ComputeAlphasBetas( const int* tgtLengths, CAST_DTYPE* alphas, CAST_DTYPE* betas, - DTYPE* costs, - const int* wpEnds = nullptr) { + DTYPE* costs) { std::vector>> seqlogProbs; std::vector> seq_alphas; std::vector> seq_betas; - std::vector seq_wpEnds; const int& B = options.batchSize_; const int& maxT = options.maxSrcLen_; @@ -415,10 +272,6 @@ void ComputeAlphasBetas( TensorView({maxT, maxU}, alphas + b * maxT * maxU)); seq_betas.push_back( TensorView({maxT, maxU}, betas + b * maxT * maxU)); - - if (wpEnds != nullptr) { - seq_wpEnds.push_back(wpEnds + b * (maxU)); - } } std::vector scores(B << 1); @@ -432,8 +285,7 @@ void ComputeAlphasBetas( /*srcLen=*/srcLengths[i], /*tgtLen=*/tgtLengths[i] + 1, // with prepended blank. /*alpha=*/seq_alphas[i], - /*beta=*/seq_betas[i], - /*wpEnds=*/(wpEnds == nullptr) ? nullptr : seq_wpEnds[i]); + /*beta=*/seq_betas[i]); } for (int b = 0; b < B; ++b) { costs[b] = -scores[b << 1]; @@ -575,11 +427,9 @@ void ComputeAlphas( const CAST_DTYPE* logProbs, const int* srcLengths, const int* tgtLengths, - CAST_DTYPE* alphas, - const int* wpEnds = nullptr) { + CAST_DTYPE* alphas) { std::vector>> seqlogProbs; std::vector> seq_alphas; - std::vector seq_wpEnds; const int& B = options.batchSize_; const int& maxT = options.maxSrcLen_; @@ -593,30 +443,17 @@ void ComputeAlphas( b * maxT * maxU)); seq_alphas.push_back( TensorView({maxT, maxU}, alphas + b * maxT * maxU)); - if (wpEnds != nullptr) { - seq_wpEnds.push_back(wpEnds + b * (maxU)); - } } std::vector scores(B << 1); //#pragma omp parallel for for (int i = 0; i < B; ++i) { // use max 2 * B threads. - if (wpEnds == nullptr) { - ComputeAlphaOneSequence( - options, - /*logProbs=*/seqlogProbs[i], - /*srcLen=*/srcLengths[i], - /*tgtLen=*/tgtLengths[i] + 1, // with prepended blank. - /*alpha=*/seq_alphas[i]); - } else { - ComputeAlphaOneSequenceRestricted( - /*options=*/options, - /*logProbs=*/seqlogProbs[i], - /*srcLen=*/srcLengths[i], - /*tgtLen=*/tgtLengths[i] + 1, // with prepended blank. - /*alpha=*/seq_alphas[i], - /*wpEnds=*/seq_wpEnds[i]); - } + ComputeAlphaOneSequence( + options, + /*logProbs=*/seqlogProbs[i], + /*srcLen=*/srcLengths[i], + /*tgtLen=*/tgtLengths[i] + 1, // with prepended blank. + /*alpha=*/seq_alphas[i]); } } @@ -627,11 +464,9 @@ void ComputeBetas( const int* srcLengths, const int* tgtLengths, CAST_DTYPE* costs, - CAST_DTYPE* betas, - const int* wpEnds = nullptr) { + CAST_DTYPE* betas) { std::vector>> seqlogProbs; std::vector> seq_betas; - std::vector seq_wpEnds; const int& B = options.batchSize_; const int& maxT = options.maxSrcLen_; @@ -645,30 +480,17 @@ void ComputeBetas( b * maxT * maxU)); seq_betas.push_back( TensorView({maxT, maxU}, betas + b * maxT * maxU)); - if (wpEnds != nullptr) { - seq_wpEnds.push_back(wpEnds + b * (maxU)); - } } std::vector scores(B << 1); //#pragma omp parallel for for (int i = 0; i < B; ++i) { // use max 2 * B threads. - if (wpEnds == nullptr) { - ComputeBetaOneSequence( - options, - /*logProbs=*/seqlogProbs[i], - /*srcLen=*/srcLengths[i], - /*tgtLen=*/tgtLengths[i] + 1, // with prepended blank. - /*betas=*/seq_betas[i]); - } else { - ComputeBetaOneSequenceRestricted( - /*options=*/options, - /*logProbs=*/seqlogProbs[i], - /*srcLen=*/srcLengths[i], - /*tgtLen=*/tgtLengths[i] + 1, // with prepended blank. - /*betas=*/seq_betas[i], - /*wpEnds=*/seq_wpEnds[i]); - } + ComputeBetaOneSequence( + options, + /*logProbs=*/seqlogProbs[i], + /*srcLen=*/srcLengths[i], + /*tgtLen=*/tgtLengths[i] + 1, // with prepended blank. + /*betas=*/seq_betas[i]); } } diff --git a/torchaudio/csrc/rnnt/cpu/cpu_transducer.h b/torchaudio/csrc/rnnt/cpu/cpu_transducer.h index 72764325ee..47a058dc31 100644 --- a/torchaudio/csrc/rnnt/cpu/cpu_transducer.h +++ b/torchaudio/csrc/rnnt/cpu/cpu_transducer.h @@ -25,8 +25,7 @@ status_t Compute( const int* srcLengths, const int* tgtLengths, DTYPE* costs, - DTYPE* gradients = nullptr, - const int* wpEnds = nullptr) { + DTYPE* gradients = nullptr) { const Options& options = workspace.GetOptions(); CHECK_EQ(options.device_, CPU); @@ -63,8 +62,7 @@ status_t Compute( /*tgtLengths=*/tgtLengths, /*alphas=*/workspace.GetPointerToAlphas(), /*betas=*/workspace.GetPointerToBetas(), - /*costs=*/costs, - /*wpEnds=*/wpEnds); + /*costs=*/costs); } if (gradients != nullptr) { @@ -90,8 +88,7 @@ status_t ComputeAlphas( const int* targets, const int* srcLengths, const int* tgtLengths, - DTYPE* alphas, - const int* wpEnds = nullptr) { + DTYPE* alphas) { const Options& options = workspace.GetOptions(); CHECK_EQ(options.device_, CPU); @@ -126,8 +123,7 @@ status_t ComputeAlphas( /*log_probs=*/workspace.GetPointerToLogProbs(), /*srcLengths=*/srcLengths, /*tgtLengths=*/tgtLengths, - /*alphas=*/alphas, - /*wpEnds=*/wpEnds); + /*alphas=*/alphas); } return SUCCESS; @@ -143,8 +139,7 @@ status_t ComputeBetas( const int* srcLengths, const int* tgtLengths, DTYPE* costs, - DTYPE* betas, - const int* wpEnds = nullptr) { + DTYPE* betas) { const Options& options = workspace.GetOptions(); CHECK_EQ(options.device_, CPU); @@ -180,8 +175,7 @@ status_t ComputeBetas( /*srcLengths=*/srcLengths, /*tgtLengths=*/tgtLengths, /*costs=*/costs, - /*betas=*/betas, - /*wpEnds=*/wpEnds); + /*betas=*/betas); } return SUCCESS; diff --git a/torchaudio/csrc/rnnt/gpu/compute.cu b/torchaudio/csrc/rnnt/gpu/compute.cu index 98cf39e2cc..8582f36d48 100644 --- a/torchaudio/csrc/rnnt/gpu/compute.cu +++ b/torchaudio/csrc/rnnt/gpu/compute.cu @@ -15,9 +15,6 @@ compute( const torch::Tensor& tgt_lengths, int64_t blank, double clamp, - const c10::optional& wp_ends = c10::nullopt, - int64_t l_buffer = 0, - int64_t r_buffer = 0, bool fused_log_smax = true, bool reuse_logits_for_grads = true) { @@ -29,8 +26,6 @@ compute( options.numTargets_ = logits.size(3); options.blank_ = blank; options.clamp_ = clamp; - options.lBuffer_ = l_buffer; - options.rBuffer_ = r_buffer; options.fusedLogSmax_ = fused_log_smax; CHECK_EQ(logits.device().type(), torch::DeviceType::CUDA); @@ -75,8 +70,7 @@ compute( /*src_lengths=*/src_lengths.data(), /*tgt_lengths=*/tgt_lengths.data(), /*costs=*/costs.data(), - /*gradients=*/(gradients == c10::nullopt)? nullptr : gradients->data(), - /*wp_ends=*/(wp_ends == c10::nullopt)? nullptr : wp_ends->data()); + /*gradients=*/(gradients == c10::nullopt)? nullptr : gradients->data()); break; } case torch::ScalarType::Half: @@ -88,8 +82,7 @@ compute( /*src_lengths=*/src_lengths.data(), /*tgt_lengths=*/tgt_lengths.data(), /*costs=*/costs.data(), - /*gradients=*/(gradients == c10::nullopt)? nullptr : gradients->data(), - /*wp_ends=*/(wp_ends == c10::nullopt)? nullptr : wp_ends->data()); + /*gradients=*/(gradients == c10::nullopt)? nullptr : gradients->data()); break; } default: diff --git a/torchaudio/csrc/rnnt/gpu/compute_alphas.cu b/torchaudio/csrc/rnnt/gpu/compute_alphas.cu index 929434e19d..dc101b0ecb 100644 --- a/torchaudio/csrc/rnnt/gpu/compute_alphas.cu +++ b/torchaudio/csrc/rnnt/gpu/compute_alphas.cu @@ -12,10 +12,7 @@ torch::Tensor compute_alphas( const torch::Tensor& src_lengths, const torch::Tensor& tgt_lengths, int64_t blank, - double clamp, - const c10::optional& wp_ends = c10::nullopt, - int64_t l_buffer = 0, - int64_t r_buffer = 0) { + double clamp) { Options options; options.batchSize_ = src_lengths.size(0); options.nHypos_ = tgt_lengths.size(0) / src_lengths.size(0); @@ -24,8 +21,6 @@ torch::Tensor compute_alphas( options.numTargets_ = logits.size(3); options.blank_ = blank; options.clamp_ = clamp; - options.lBuffer_ = l_buffer; - options.rBuffer_ = r_buffer; CHECK_EQ(logits.device().type(), torch::DeviceType::CUDA); options.stream_ = at::cuda::getCurrentCUDAStream(); @@ -65,8 +60,7 @@ torch::Tensor compute_alphas( /*targets=*/targets.data(), /*src_lengths=*/src_lengths.data(), /*tgt_lengths=*/tgt_lengths.data(), - /*alphas=*/alphas.data(), - /*wp_ends=*/(wp_ends == c10::nullopt) ? nullptr : wp_ends->data()); + /*alphas=*/alphas.data()); return alphas; } diff --git a/torchaudio/csrc/rnnt/gpu/compute_betas.cu b/torchaudio/csrc/rnnt/gpu/compute_betas.cu index f906d1bbe3..63b8fd636a 100644 --- a/torchaudio/csrc/rnnt/gpu/compute_betas.cu +++ b/torchaudio/csrc/rnnt/gpu/compute_betas.cu @@ -12,10 +12,7 @@ torch::Tensor compute_betas( const torch::Tensor& src_lengths, const torch::Tensor& tgt_lengths, int64_t blank, - double clamp, - const c10::optional& wp_ends = c10::nullopt, - int64_t l_buffer = 0, - int64_t r_buffer = 0) { + double clamp) { Options options; options.batchSize_ = src_lengths.size(0); options.nHypos_ = tgt_lengths.size(0) / src_lengths.size(0); @@ -24,8 +21,6 @@ torch::Tensor compute_betas( options.numTargets_ = logits.size(3); options.blank_ = blank; options.clamp_ = clamp; - options.lBuffer_ = l_buffer; - options.rBuffer_ = r_buffer; CHECK_EQ(logits.device().type(), torch::DeviceType::CUDA); options.stream_ = at::cuda::getCurrentCUDAStream(); @@ -70,8 +65,7 @@ torch::Tensor compute_betas( /*src_lengths=*/src_lengths.data(), /*tgt_lengths=*/tgt_lengths.data(), /*costs=*/costs.data(), - /*betas=*/betas.data(), - /*wp_ends=*/(wp_ends == c10::nullopt) ? nullptr : wp_ends->data()); + /*betas=*/betas.data()); return betas; } diff --git a/torchaudio/csrc/rnnt/gpu/gpu_alignment_restrictions.cuh b/torchaudio/csrc/rnnt/gpu/gpu_alignment_restrictions.cuh deleted file mode 100644 index d5d927992f..0000000000 --- a/torchaudio/csrc/rnnt/gpu/gpu_alignment_restrictions.cuh +++ /dev/null @@ -1,476 +0,0 @@ -#pragma once - -#ifdef USE_CUDA - -#include - -#include -#include -#include - -namespace torchaudio { -namespace rnnt { - - -template -__device__ void ComputeAlphasRestricted( - int maxSrcLen, - int maxTgtLen, - int numTargets, - int blank, - const CAST_DTYPE* logProbs, - const int* srcLengths, - const int* tgtLengths, - int* alpha_counters, - volatile CAST_DTYPE* alphas, - const int* wpEnds, - int lBuffer, - int rBuffer, - int warp_size, - int H=1) { - - const int& maxT = maxSrcLen; - const int& maxU = maxTgtLen; - - // Block's 3d dim is batchsize - const int bTgt = blockIdx.z; // 0 <= b < B - const int bSrc = bTgt / H; - const int T = srcLengths[bSrc]; - const int U = tgtLengths[bTgt] + 1; - - assert(T <= maxT && "T must be < maxT"); - assert(U <= maxU && "U must be < maxU"); - - // Blocks 1st dim is T i.e. warpsize timesteps - // to find timestep, we index into correct block idx * dim - // then offset by the thread - const int t = blockIdx.x * blockDim.x + threadIdx.x; - - // Blocks 2nd dim is U. For u, we just offset by 2nd idx - const int u = blockIdx.y; - - // simply exit if we are out of bounds - // this happens typically when warp size is larger than T - if (t > T-1 || u > U-1 || t < 0 || u < 0) { - return; - } - - const int* wpEndsB = wpEnds + maxU * bTgt; - assert(wpEndsB[u] >= 0 && "wpEnds cannot be negative"); - if (u < U - 1) { - assert(wpEndsB[u+1] >= 0 && "wpEnds cannot be negative"); - } - - // below indexes are inclusive - // compute valid ranges for emit transitions in current warp - int emit_start = math::max(wpEndsB[u] - lBuffer, 0); - int emit_end = math::min(wpEndsB[u] + rBuffer, T - 1); - - // compute valid ranges for blank transitions in current warp - int blank_start = math::max(wpEndsB[u] - lBuffer + 1, 1); - int blank_end = (u == U - 1) ? T - 1 : math::min(wpEndsB[u + 1] + rBuffer, T - 1); - - // this is a useful pointer to track the last timestep - // for previous warp. - int prevWarpEndT = blockIdx.x * blockDim.x - 1; - - int* counter = alpha_counters + Indexer2D(maxU)(bTgt, blockIdx.y); - - - int idx_b_t_u = -1, idx_b_t_um1 = -1, idx_b_tm1_u = -1; - int idx_b_prevWarpEndT_u = -1; - - Indexer3D idxr(maxT, maxU); - idx_b_t_u = idxr(bTgt, t, u); - idx_b_t_um1 = idxr(bTgt, t, u - 1); - idx_b_tm1_u = idxr(bTgt, t - 1, u); - idx_b_prevWarpEndT_u = idxr(bTgt, prevWarpEndT, u); - - alphas[idx_b_t_u] = CAST_DTYPE(-INFINITY); - - // Initialization condition for alphas - if (t == 0 && u == 0) { - alphas[idx_b_t_u] = 0; - } - - // Synchronization routines: - // Below conditions make sure given t, u - // - threads in previous warp for u is complete - // - threads in the warp corresponding to t, u-1 is complete - // See https://github.com/1ytic/warp-rnnt for illustration - if (blockIdx.x > 0) { // wait for previous warp (in t-axis) is ready. - while (atomicAdd(counter, 0) < blockIdx.x) {} - } - - if (blockIdx.y > 0) { // wait for previous warp (in u-axis) is ready. - while (atomicAdd(counter - 1, 0) <= blockIdx.x) {} - } - - // This is initialization loop for t = 0, u - // i.e. emit condition while running alphas - if (t == 0 && u > 0) { - // Alignment Restriction check - if (in_range(emit_start, emit_end, t)) { - alphas[idx_b_t_u] = - alphas[idx_b_t_um1] - + logProbs[(idx_b_t_um1 << 1) + LOG_PROBS_EMIT_IDX]; - } - } - - // This is initialization loop for u = 0, t - if (u == 0 && t > 0) { - - // skip_prob stores the log probability of t, u - CAST_DTYPE skip_prob = logProbs[(idx_b_tm1_u << 1) + LOG_PROBS_SKIP_IDX]; - - #pragma unroll - // iterating on i = 1, 2, 4, 8.. - for (int i = 1; i < warp_size; i <<= 1) { - - // https://devblogs.nvidia.com/using-cuda-warp-level-primitives/ - // first param is a mask -1 indicates all threads in warp participate - // second param is the value being passed for current thread - // third param is the offset which will be used for addition of values - // copy from a thread with lower ID relative to the caller - CAST_DTYPE synced_val = __shfl_up_sync(0xffffffff, skip_prob, i); - - // Illustration with 8 threads in warp - // Initial: 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1 - // i == 1: 0.1, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2 - // i == 2: 0.1, 0.2, 0.3, 0.4, 0.4, 0.4, 0.4, 0.4 - // i == 4: 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8 - - // Alignment restriction check - // add to skip_prob only if *t-i* is within allowed range - if (i <= threadIdx.x && - in_range(blank_start, blank_end, t - i) ) { - skip_prob += synced_val; - } - } - - // update the values of alpha if *t* is within allowed range - if (in_range(blank_start, blank_end, t)) { - alphas[idx_b_t_u] = skip_prob; - } - - // Optionally add previous warp's end idx value if it is - // within range to get cumulative score for all previous timesteps, - // and not just within current warp - if (in_range(blank_start, blank_end, prevWarpEndT)) { - alphas[idx_b_t_u] += alphas[idx_b_prevWarpEndT_u]; - } - } - - // General case - if (t < T && u < U) { - - CAST_DTYPE skip_prob = CAST_DTYPE(-INFINITY); - if (in_range(blank_start, blank_end, t) && t > 0) { - skip_prob = logProbs[(idx_b_tm1_u << 1) + LOG_PROBS_SKIP_IDX]; - } - - // We check if the first index of current warp (prevWarpEndT+1) was within allowed - // timesteps, if so we add the alphas of previous warp's last timestep - // to skip score. - CAST_DTYPE skip = skip_prob; - if (in_range(blank_start, blank_end, prevWarpEndT+1) && prevWarpEndT >= 0) { - skip += alphas[idx_b_prevWarpEndT_u]; - } - - CAST_DTYPE emit = CAST_DTYPE(-INFINITY); - if (in_range(emit_start, emit_end, t) && u > 0) { - emit = alphas[idx_b_t_um1] + - logProbs[(idx_b_t_um1 << 1) + LOG_PROBS_EMIT_IDX]; - } - - CAST_DTYPE out_score = math::lse(skip, emit); - - - // Below we loop over warp_size updating the out score - // once per thread in each loop. - // shared memory is used to synchronize the values in threads - for(int i = 1; i < warp_size; i++) { - - CAST_DTYPE synced_val = __shfl_up_sync(0xffffffff, out_score, 1); - - // We will only update the out_score if t is within range - // of alignment constraints and it is the thread's turn in loop - if ((i == threadIdx.x) && in_range(blank_start, blank_end, t)) { - out_score = math::lse(synced_val + skip_prob, emit); - } - } - // update alphas if t was within range of blanks, or emits - if ( (in_range(blank_start, blank_end, t) || in_range(emit_start, emit_end, t) ) - && (t > 0 && u > 0)) { - alphas[idx_b_t_u] = out_score; - } - } - - // Synchronization mechanism - if (threadIdx.x == 0) { - __threadfence(); - atomicAdd(counter, 1); - } -} - - - -// This is a wrapper around ComputeAlphasRestricted -// kernel to enable unit testing -template -__global__ void ComputeAlphasRestrictedWrapper( - int maxSrcLen, - int maxTgtLen, - int numTargets, - int blank, - const CAST_DTYPE* logProbs, - const int* srcLengths, - const int* tgtLengths, - int* alpha_counters, - volatile CAST_DTYPE* alphas, - const int* wpEnds, - int lBuffer, - int rBuffer, - int warp_size, - int H=1) { - ComputeAlphasRestricted( - maxSrcLen, - maxTgtLen, - numTargets, - blank, - logProbs, - srcLengths, - tgtLengths, - alpha_counters, - alphas, - wpEnds, - lBuffer, - rBuffer, - warp_size, - H); -} - - -template -__device__ void ComputeBetasCostsRestricted( - int maxSrcLen, - int maxTgtLen, - int numTargets, - int blank, - const CAST_DTYPE* logProbs, - const int* srcLengths, - const int* tgtLengths, - int* beta_counters, - DTYPE* costs, - volatile CAST_DTYPE* betas, - const int* wpEnds, - int lBuffer, - int rBuffer, - int warp_size, - int num_warps, - int H=1) { - - const int& maxT = maxSrcLen; - const int& maxU = maxTgtLen; - - // Block's 3d dim is batchsize - const int bTgt = blockIdx.z; // 0 <= b < B - const int bSrc = bTgt / H; - const int T = srcLengths[bSrc]; - const int U = tgtLengths[bTgt] + 1; - - assert(T <= maxT); - assert(U <= maxU); - - const int t = T - 1 - blockIdx.x * blockDim.x - threadIdx.x; - const int u = U - 1 - blockIdx.y; - - if (t < 0 || u < 0) { // out of boundary. - return; - } - - const int* wpEndsB = wpEnds + maxU * bTgt; - - // below indexes are inclusive - // compute valid ranges for emit transitions in - // current warp - int emit_start = (u >= U - 1) ? -1 : math::max(0, wpEndsB[u + 1] - lBuffer); - int emit_end = (u >= U - 1) ? -1 : math::min(wpEndsB[u + 1] + rBuffer, T - 1); - - - // compute valid ranges for blank transitions in - // current warp - int blank_start = (u > U - 1) ? -1 : math::max(wpEndsB[u] - lBuffer, 0); - int blank_end = (u >= U - 1) ? T - 2 : math::min(wpEndsB[u + 1] + rBuffer - 1, T - 2); - - int rightBlockStartT = T - 1 - blockIdx.x * blockDim.x + 1; - int* counter = beta_counters + Indexer2D(maxU)(bTgt, blockIdx.y); - - int idx_b_t_u = -1, idx_b_t_up1 = -1; - int idx_b_tp1_up1 = -1, idx_b_rightBlockStartT_u = -1; - - Indexer3D idxr(maxT, maxU); - idx_b_t_u = idxr(bTgt, t, u); - idx_b_t_up1 = idxr(bTgt, t, u+1); - idx_b_tp1_up1 = idxr(bTgt, t+1, u+1); - idx_b_rightBlockStartT_u = idxr(bTgt, rightBlockStartT, u); - - if (t < T && u < U) { - betas[idx_b_t_u] = CAST_DTYPE(-INFINITY); - } - - // Initialization condition - if (t == T - 1 && u == U - 1) { - betas[idx_b_t_u] = - logProbs[(idx_b_t_u << 1) + LOG_PROBS_SKIP_IDX]; - } - - // For betas, we process warps from right to left - // blockIdx.x specifies the warp id for a given u - // here we want to wait until the warp to the right is done - if (blockIdx.x > 0) { // wait for previous warp (in t-axis) is ready. - while (atomicAdd(counter, 0) < blockIdx.x) {} - } - - if (blockIdx.y > 0) { // wait for previous warp (in u-axis) is ready. - while (atomicAdd(counter - 1, 0) <= blockIdx.x) {} - } - - // edge condition for emits - if (t == T - 1 && u < U - 1) { - if (emit_start <= t && t <= emit_end) { - betas[idx_b_t_u] = - betas[idx_b_t_up1] - + logProbs[(idx_b_t_u << 1) + LOG_PROBS_EMIT_IDX]; - } - } - - if (u == U - 1 && t <= T - 1) { - CAST_DTYPE skip_prob = logProbs[(idx_b_t_u << 1) + LOG_PROBS_SKIP_IDX]; - - #pragma unroll - for(int i = 1; i < warp_size; i <<= 1) { - - CAST_DTYPE synced_val = __shfl_up_sync(0xffffffff, skip_prob, i); - if (i <= threadIdx.x && in_range(blank_start, blank_end, t)) { - skip_prob = skip_prob + synced_val; - } - } - - if (in_range(blank_start, blank_end, t) && t < T - 1) { - // we add skipprob and right block's first value - // and assign it to beta - betas[idx_b_t_u] = skip_prob; - if (in_range(blank_start, blank_end, rightBlockStartT) || - in_range(emit_start, emit_end, rightBlockStartT)) { - betas[idx_b_t_u] += betas[idx_b_rightBlockStartT_u]; - } - } - } - - // General case - if (t < T && u < U) { - - CAST_DTYPE skip_prob = CAST_DTYPE(-INFINITY); - if (in_range(blank_start, blank_end, t)) { - skip_prob = logProbs[(idx_b_t_u << 1) + LOG_PROBS_SKIP_IDX]; - } - // We check if the first index of right warp is within allowed - // timesteps, if so we add the betas of right warp's first timestep - // to skip score - CAST_DTYPE skip = skip_prob; - if (in_range(blank_start, blank_end, rightBlockStartT) || in_range(emit_start, emit_end, rightBlockStartT)) { - skip += betas[idx_b_rightBlockStartT_u]; - } - - CAST_DTYPE emit = CAST_DTYPE(-INFINITY); - if (in_range(emit_start, emit_end, t) && u < U - 1) { - emit = betas[idx_b_t_up1] + - logProbs[(idx_b_t_u << 1) + LOG_PROBS_EMIT_IDX]; - } - - CAST_DTYPE out_score = CAST_DTYPE(-INFINITY); - if (skip != CAST_DTYPE(-INFINITY) || emit != CAST_DTYPE(-INFINITY)) { - out_score = math::lse(skip, emit); - } - - for(int i = 1; i < warp_size; i++) { - - CAST_DTYPE synced_val = __shfl_up_sync(0xffffffff, out_score, 1); - - if (i == threadIdx.x && - (in_range(blank_start, blank_end, t) || - in_range(emit_start, emit_end, t)) - ) { - out_score = math::lse(synced_val + skip_prob, emit); - } - } - - // bounds check for last warps - if (t < T - 1 && u < U - 1) { - // bound checks for t - if (in_range(blank_start, blank_end, t) || - in_range(emit_start, emit_end, t)) { - betas[idx_b_t_u] = out_score; - } - } - } - - if (t == 0 && u == 0) { // use -beta(0, 0) as cost. - if (isinf(-betas[idx_b_t_u]) || isnan(-betas[idx_b_t_u])) { - costs[bTgt] = 0; - } else { - costs[bTgt] = -betas[idx_b_t_u]; - } - } - - if (threadIdx.x == 0) { - __threadfence(); - atomicAdd(counter, 1); - } -} - - -// This is a wrapper around ComputeAlphasRestricted -// kernel to enable unit testing -template -__global__ void ComputeBetasCostsRestrictedWrapper( - int maxSrcLen, - int maxTgtLen, - int numTargets, - int blank, - const CAST_DTYPE* logProbs, - const int* srcLengths, - const int* tgtLengths, - int* beta_counters, - CAST_DTYPE* costs, - volatile CAST_DTYPE* betas, - const int* wpEnds, - int lBuffer, - int rBuffer, - int warp_size, - int num_warp, - int H=1) { - ComputeBetasCostsRestricted( - maxSrcLen, - maxTgtLen, - numTargets, - blank, - logProbs, - srcLengths, - tgtLengths, - beta_counters, - costs, - betas, - wpEnds, - lBuffer, - rBuffer, - warp_size, - num_warp, - H); -} - -} // namespace rnnt -} // namespace torchaudio - -#endif // USE_CUDA diff --git a/torchaudio/csrc/rnnt/gpu/gpu_kernels.cuh b/torchaudio/csrc/rnnt/gpu/gpu_kernels.cuh index 2969a7f790..a2d724bf8f 100644 --- a/torchaudio/csrc/rnnt/gpu/gpu_kernels.cuh +++ b/torchaudio/csrc/rnnt/gpu/gpu_kernels.cuh @@ -5,8 +5,8 @@ #include #include +#include #include -#include namespace torchaudio { namespace rnnt { @@ -285,9 +285,6 @@ __global__ void ComputeAlphasBetasCosts( int* betaCounters, volatile CAST_DTYPE* betas, DTYPE* costs, - const int* wpEnds=nullptr, - int lBuffer = 0, - int rBuffer = 0, int warpSize = 0, int numWarps=0, int H = 1) { @@ -295,7 +292,7 @@ __global__ void ComputeAlphasBetasCosts( assert(threadIdx.y == 0 || threadIdx.y == 1); if (threadIdx.y == 0) { - if (wpEnds == nullptr) { + ComputeAlphas( /*maxSrcLen=*/maxSrcLen, /*maxTgtLen=*/maxTgtLen, @@ -307,26 +304,7 @@ __global__ void ComputeAlphasBetasCosts( /*alpha_counters=*/alpha_counters, /*alphas=*/alphas, H); - } - else { - ComputeAlphasRestricted( - /*maxSrcLen=*/maxSrcLen, - /*maxTgtLen=*/maxTgtLen, - /*numTargets=*/numTargets, - /*blank=*/blank, - /*logProbs=*/logProbs, - /*srcLengths=*/srcLengths, - /*tgtLengths=*/tgtLengths, - /*alpha_counters=*/alpha_counters, - /*alphas=*/(CAST_DTYPE*)alphas, - /*wpEnds=*/wpEnds, - /*lBuffer=*/lBuffer, - /*rBuffer=*/rBuffer, - /*warpSize=*/warpSize, - H); - } } else { // threadIdx.y == 1 - if (wpEnds == nullptr) { ComputeBetasCosts( /*maxSrcLen=*/maxSrcLen, /*maxTgtLen=*/maxTgtLen, @@ -339,26 +317,6 @@ __global__ void ComputeAlphasBetasCosts( /*beta=*/betas, /*costs=*/costs, H); - } else { - ComputeBetasCostsRestricted( - maxSrcLen, - maxTgtLen, - numTargets, - blank, - logProbs, - srcLengths, - tgtLengths, - betaCounters, - costs, - betas, - wpEnds, - lBuffer, - rBuffer, - warpSize, - numWarps, - H); - } - } } diff --git a/torchaudio/csrc/rnnt/gpu/gpu_transducer.h b/torchaudio/csrc/rnnt/gpu/gpu_transducer.h index cde953a8ef..1720b55645 100644 --- a/torchaudio/csrc/rnnt/gpu/gpu_transducer.h +++ b/torchaudio/csrc/rnnt/gpu/gpu_transducer.h @@ -4,7 +4,6 @@ #include #include -#include #include namespace torchaudio { @@ -88,8 +87,7 @@ status_t Compute( const int* srcLengths, const int* tgtLengths, DTYPE* costs, - DTYPE* gradients = nullptr, - const int* wpEnds = nullptr) { + DTYPE* gradients = nullptr) { const Options& options = workspace.GetOptions(); const cudaStream_t& stream = options.stream_; @@ -101,8 +99,6 @@ status_t Compute( const int& blank = options.blank_; const CAST_DTYPE clamp = options.clamp_; - const int& l_buffer = options.lBuffer_; - const int& r_buffer = options.rBuffer_; const bool& fusedLogSmax = options.fusedLogSmax_; { // compute denominators. @@ -170,9 +166,6 @@ status_t Compute( /*beta_counters=*/workspace.GetPointerToBetaCounters(), /*betas=*/workspace.GetPointerToBetas(), /*costs=*/costs, - /*wpEnds=*/wpEnds, - /*l_buffer=*/l_buffer, - /*r_buffer=*/r_buffer, /*warp_size=*/WARP_SIZE, /*num_warps=*/num_warps, H); @@ -221,8 +214,7 @@ status_t ComputeAlphas( const int* targets, const int* srcLengths, const int* tgtLengths, - DTYPE* alphas, - const int* wpEnds = nullptr) { + DTYPE* alphas) { const Options& options = workspace.GetOptions(); const cudaStream_t& stream = options.stream_; @@ -233,9 +225,6 @@ status_t ComputeAlphas( const int& D = options.numTargets_; const int& blank = options.blank_; - const int& l_buffer = options.lBuffer_; - const int& r_buffer = options.rBuffer_; - { // compute denominators. status_t status = LogSumExp2D( /*stream=*/stream, @@ -285,39 +274,20 @@ status_t ComputeAlphas( // 2nd dim is 1 for alpha only dim3 thread_dims(WARP_SIZE, 1); - if (wpEnds == nullptr) { - ComputeAlphasWrapper - <<>>( - /*max_src_len=*/max_T, - /*max_tgt_len=*/max_U, - /*num_targets=*/D, - /*blank=*/blank, - /*log_probs=*/workspace.GetPointerToLogProbs(), - /*srcLengths=*/srcLengths, - /*tgtLengths=*/tgtLengths, - /*alpha_counters=*/workspace.GetPointerToAlphaCounters(), - /*alphas=*/(volatile DTYPE*)alphas, - H); - } else { - // cudaMemset(alphas, 0, B * max_T * max_U * sizeof(DTYPE)); - ComputeAlphasRestrictedWrapper - <<>>( - max_T, - max_U, - D, - blank, - workspace.GetPointerToLogProbs(), - srcLengths, - tgtLengths, - workspace.GetPointerToAlphaCounters(), - // workspace.GetPointerToAlphas(), - (volatile DTYPE*)alphas, - wpEnds, - l_buffer, - r_buffer, - WARP_SIZE, - H); - } + + ComputeAlphasWrapper + <<>>( + /*max_src_len=*/max_T, + /*max_tgt_len=*/max_U, + /*num_targets=*/D, + /*blank=*/blank, + /*log_probs=*/workspace.GetPointerToLogProbs(), + /*srcLengths=*/srcLengths, + /*tgtLengths=*/tgtLengths, + /*alpha_counters=*/workspace.GetPointerToAlphaCounters(), + /*alphas=*/(volatile DTYPE*)alphas, + H); + if (cudaGetLastError() != cudaSuccess) { return COMPUTE_ALPHAS_BETAS_COSTS_FAILED; } @@ -334,8 +304,7 @@ status_t ComputeBetas( const int* srcLengths, const int* tgtLengths, DTYPE* costs, - DTYPE* betas, - const int* wpEnds = nullptr) { + DTYPE* betas) { const Options& options = workspace.GetOptions(); const cudaStream_t& stream = options.stream_; @@ -346,9 +315,6 @@ status_t ComputeBetas( const int& D = options.numTargets_; const int& blank = options.blank_; - const int& l_buffer = options.lBuffer_; - const int& r_buffer = options.rBuffer_; - { // compute denominators. status_t status = LogSumExp2D( /*stream=*/stream, @@ -398,41 +364,20 @@ status_t ComputeBetas( // 2nd dim is 1 for betas only dim3 thread_dims(WARP_SIZE, 1); - if (wpEnds == nullptr) { - ComputeBetasWrapper - <<>>( - /*max_src_len=*/max_T, - /*max_tgt_len=*/max_U, - /*num_targets=*/D, - /*blank=*/blank, - /*log_probs=*/workspace.GetPointerToLogProbs(), - /*srcLengths=*/srcLengths, - /*tgtLengths=*/tgtLengths, - /*alpha_counters=*/workspace.GetPointerToBetaCounters(), - /*alphas=*/(volatile DTYPE*)betas, - costs, - H); - } else { - ComputeBetasCostsRestrictedWrapper - <<>>( - max_T, - max_U, - D, - blank, - workspace.GetPointerToLogProbs(), - srcLengths, - tgtLengths, - workspace.GetPointerToBetaCounters(), - costs, - (volatile DTYPE*)betas, - wpEnds, - l_buffer, - r_buffer, - WARP_SIZE, - num_warps, - H); - cudaDeviceSynchronize(); - } + ComputeBetasWrapper + <<>>( + /*max_src_len=*/max_T, + /*max_tgt_len=*/max_U, + /*num_targets=*/D, + /*blank=*/blank, + /*log_probs=*/workspace.GetPointerToLogProbs(), + /*srcLengths=*/srcLengths, + /*tgtLengths=*/tgtLengths, + /*alpha_counters=*/workspace.GetPointerToBetaCounters(), + /*alphas=*/(volatile DTYPE*)betas, + costs, + H); + if (cudaGetLastError() != cudaSuccess) { return COMPUTE_ALPHAS_BETAS_COSTS_FAILED; } diff --git a/torchaudio/csrc/rnnt/options.h b/torchaudio/csrc/rnnt/options.h index c7ea63eda9..f70a3c8c07 100644 --- a/torchaudio/csrc/rnnt/options.h +++ b/torchaudio/csrc/rnnt/options.h @@ -29,12 +29,6 @@ typedef struct Options { // gradient clamp value. float clamp_; - // alignment restricted loss l buffer - int lBuffer_; - - // alignment restricted loss r buffer - int rBuffer_; - // batch size = B. int batchSize_; @@ -60,8 +54,6 @@ typedef struct Options { blank_(-1), backtrack_(false), clamp_(-1), // negative for disabling clamping by default. - lBuffer_(0), - rBuffer_(0), batchSize_(0), nHypos_(1), maxSrcLen_(0), diff --git a/torchaudio/csrc/rnnt/transducer.h b/torchaudio/csrc/rnnt/transducer.h index c69067a000..82b84ce0ea 100644 --- a/torchaudio/csrc/rnnt/transducer.h +++ b/torchaudio/csrc/rnnt/transducer.h @@ -14,8 +14,7 @@ status_t Compute( const int* srcLengths, const int* tgtLengths, DTYPE* costs, - DTYPE* gradients = nullptr, - const int* wp_ends=nullptr) { + DTYPE* gradients = nullptr) { switch (workspace.GetOptions().device_) { case CPU: { status_t status = cpu::Compute( @@ -25,8 +24,7 @@ status_t Compute( /*srcLengths=*/srcLengths, /*tgtLengths=*/tgtLengths, /*costs=*/costs, - /*gradients=*/gradients, - /*wp_ends =*/wp_ends); + /*gradients=*/gradients); return status; } case GPU: { @@ -37,8 +35,7 @@ status_t Compute( /*srcLengths=*/srcLengths, /*tgtLengths=*/tgtLengths, /*costs=*/costs, - /*gradients=*/gradients, - /*wp_ends =*/wp_ends); + /*gradients=*/gradients); return status; } default: { @@ -56,8 +53,7 @@ status_t ComputeAlphas( const int* targets, const int* srcLengths, const int* tgtLengths, - DTYPE* alphas, - const int* wp_ends=nullptr) { + DTYPE* alphas) { switch (workspace.GetOptions().device_) { case CPU: { status_t status = cpu::ComputeAlphas( @@ -66,8 +62,7 @@ status_t ComputeAlphas( /*targets=*/targets, /*srcLengths=*/srcLengths, /*tgtLengths=*/tgtLengths, - /*alphas=*/alphas, - /*wp_ends =*/wp_ends); + /*alphas=*/alphas); return status; } case GPU: { @@ -77,8 +72,7 @@ status_t ComputeAlphas( /*targets=*/targets, /*srcLengths=*/srcLengths, /*tgtLengths=*/tgtLengths, - /*costs=*/alphas, - /*wp_ends =*/wp_ends); + /*costs=*/alphas); return status; } default: { @@ -97,8 +91,7 @@ status_t ComputeBetas( const int* srcLengths, const int* tgtLengths, DTYPE* costs, - DTYPE* betas, - const int* wp_ends=nullptr) { + DTYPE* betas) { switch (workspace.GetOptions().device_) { case CPU: { status_t status = cpu::ComputeBetas( @@ -108,8 +101,7 @@ status_t ComputeBetas( /*srcLengths=*/srcLengths, /*tgtLengths=*/tgtLengths, /*costs=*/costs, - /*betas=*/betas, - /*wp_ends =*/wp_ends); + /*betas=*/betas); return status; } case GPU: { @@ -120,8 +112,7 @@ status_t ComputeBetas( /*srcLengths=*/srcLengths, /*tgtLengths=*/tgtLengths, /*costs=*/costs, - /*betas=*/betas, - /*wp_ends =*/wp_ends); + /*betas=*/betas); return status; } default: { diff --git a/torchaudio/prototype/rnnt_loss.py b/torchaudio/prototype/rnnt_loss.py index f69d328f53..1da03bfb2a 100644 --- a/torchaudio/prototype/rnnt_loss.py +++ b/torchaudio/prototype/rnnt_loss.py @@ -13,9 +13,6 @@ def _rnnt_loss_alphas( target_lengths, blank=-1, clamp=-1, - wordpiece_ends=None, - left_buffer=0, - right_buffer=0, ): """ Compute alphas for RNN transducer loss. @@ -25,8 +22,6 @@ def _rnnt_loss_alphas( targets = targets.to(device=logits.device) logit_lengths = logit_lengths.to(device=logits.device) target_lengths = target_lengths.to(device=logits.device) - if wordpiece_ends is not None: - wordpiece_ends = wordpiece_ends.to(device=logits.device) # make sure all int tensors are of type int32. targets = targets.int() @@ -40,9 +35,6 @@ def _rnnt_loss_alphas( target_lengths, blank, clamp, - wordpiece_ends, - left_buffer, - right_buffer, ) @@ -53,9 +45,6 @@ def _rnnt_loss_betas( target_lengths, blank=-1, clamp=-1, - wordpiece_ends=None, - left_buffer=0, - right_buffer=0, ): """ Compute betas for RNN transducer loss @@ -65,8 +54,6 @@ def _rnnt_loss_betas( targets = targets.to(device=logits.device) logit_lengths = logit_lengths.to(device=logits.device) target_lengths = target_lengths.to(device=logits.device) - if wordpiece_ends is not None: - wordpiece_ends = wordpiece_ends.to(device=logits.device) # make sure all int tensors are of type int32. targets = targets.int() @@ -80,9 +67,6 @@ def _rnnt_loss_betas( target_lengths, blank, clamp, - wordpiece_ends, - left_buffer, - right_buffer, ) @@ -97,9 +81,6 @@ def forward( blank=-1, clamp=-1, runtime_check=False, - wordpiece_ends=None, - left_buffer=0, - right_buffer=0, fused_log_softmax=True, reuse_logits_for_grads=True, ): @@ -111,8 +92,6 @@ def forward( targets = targets.to(device=logits.device) logit_lengths = logit_lengths.to(device=logits.device) target_lengths = target_lengths.to(device=logits.device) - if wordpiece_ends is not None: - wordpiece_ends = wordpiece_ends.to(device=logits.device) # make sure all int tensors are of type int32. targets = targets.int() @@ -138,9 +117,6 @@ def forward( tgt_lengths=target_lengths, blank=blank, clamp=clamp, - wp_ends=wordpiece_ends, - l_buffer=left_buffer, - r_buffer=right_buffer, fused_log_smax=fused_log_softmax, reuse_logits_for_grads=reuse_logits_for_grads, ) @@ -162,9 +138,6 @@ def backward(ctx, output_gradients): None, # blank None, # clamp None, # runtime_check - None, # wordpiece_ends - None, # left_buffer - None, # right_buffer None, # fused_log_softmax None, # reuse_logits_for_grads ) @@ -178,9 +151,6 @@ def rnnt_loss( blank=-1, clamp=-1, runtime_check=False, - wordpiece_ends=None, - left_buffer=0, - right_buffer=0, fused_log_softmax=True, reuse_logits_for_grads=True, ): @@ -199,12 +169,6 @@ def rnnt_loss( blank (int, opt): blank label (Default: ``-1``) clamp (float): clamp for gradients (Default: ``-1``) runtime_check (bool): whether to do sanity check during runtime. (Default: ``False``) - wordpiece_ends (Tensor): Tensor of dimension (batch, target) containing the end frames of targets - for each sequence (including bos end_frame = 0) (Default: ``None``) - left_buffer (int): left buffer frames used for alignment restricted RNNT loss. - Loss will not be imposed on frames smaller than wordpiece_end - left_buffer. (Default: ``0``) - right_buffer (int): right buffer frames used for alignment restricted RNNT loss. - Loss will not be imposed on frames greater than wordpiece_end + right_buffer. (Default: ``0``) fused_log_smax (bool): set to False if calling log_softmax outside loss (Default: ``True``) reuse_logits_for_grads (bool): whether to save memory by reusing logits memory for grads (Default: ``True``) """ @@ -222,9 +186,6 @@ def rnnt_loss( blank, clamp, runtime_check, - wordpiece_ends, - left_buffer, - right_buffer, fused_log_softmax, reuse_logits_for_grads, ) @@ -243,10 +204,6 @@ class RNNTLoss(torch.nn.Module): blank (int, opt): blank label (Default: ``-1``) clamp (float): clamp for gradients (Default: ``-1``) runtime_check (bool): whether to do sanity check during runtime. (Default: ``False``) - left_buffer (int): left buffer frames used for alignment restricted RNNT loss. - Loss will not be imposed on frames smaller than wordpiece_end - left_buffer. (Default: ``0``) - right_buffer (int): right buffer frames used for alignment restricted RNNT loss. - Loss will not be imposed on frames greater than wordpiece_end + right_buffer. (Default: ``0``) fused_log_smax (bool): set to False if calling log_softmax outside loss (Default: ``True``) reuse_logits_for_grads (bool): whether to save memory by reusing logits memory for grads (Default: ``True``) """ @@ -256,8 +213,6 @@ def __init__( blank=-1, clamp=-1, runtime_check=False, - left_buffer=0, - right_buffer=0, fused_log_softmax=True, reuse_logits_for_grads=True, ): @@ -265,8 +220,6 @@ def __init__( self.blank = blank self.clamp = clamp self.runtime_check = runtime_check - self.left_buffer = left_buffer - self.right_buffer = right_buffer self.fused_log_softmax = fused_log_softmax self.reuse_logits_for_grads = reuse_logits_for_grads @@ -276,9 +229,6 @@ def forward( targets, logit_lengths, target_lengths, - wordpiece_ends=None, - left_buffer=None, - right_buffer=None, ): """ Args: @@ -286,22 +236,7 @@ def forward( targets (Tensor): Tensor of dimension (batch, max target length) containing targets with zero padded logit_lengths (Tensor): Tensor of dimension (batch) containing lengths of each sequence from encoder target_lengths (Tensor): Tensor of dimension (batch) containing lengths of targets for each sequence - wordpiece_ends (Tensor): Tensor of dimension (batch, target) containing the end frames of targets - for each sequence (including bos end_frame = 0) (Default: ``None``) - left_buffer (int): left buffer frames used for alignment restricted RNNT loss. - Loss will not be imposed on frames smaller than wordpiece_end - left_buffer. (Default: ``None``) - right_buffer (int): right buffer frames used for alignment restricted RNNT loss. - Loss will not be imposed on frames greater than wordpiece_end + right_buffer. (Default: ``None``) """ - # left_buffer / right_buffer is passed in forward, - # when we use dataset or sample specific left/right buffer - # self.left_buffer / right_buffer is used by default, or - # to preserve backward compatibility - if left_buffer is None: - left_buffer = self.left_buffer - if right_buffer is None: - right_buffer = self.right_buffer - return rnnt_loss( logits, targets, @@ -310,9 +245,6 @@ def forward( self.blank, self.clamp, self.runtime_check, - wordpiece_ends, - left_buffer, - right_buffer, self.fused_log_softmax, self.reuse_logits_for_grads, ) From d25de70f61bfc483ac4f17e466fbd71ca801c239 Mon Sep 17 00:00:00 2001 From: Caroline Chen Date: Fri, 30 Apr 2021 12:53:14 -0700 Subject: [PATCH 47/73] Remove GPU code Summary: to make fixing the CI build easier, we want to first remove the CPU code and export only the CPU code. we will add back GPU code after CPU code is merged into open source Reviewed By: vincentqb Differential Revision: D28076934 fbshipit-source-id: 9e12298b0ba8733853999c1127f0ee9d9368e25f --- .../rnnt/rnnt_loss_cuda_test.py | 10 - torchaudio/csrc/rnnt/gpu/compute.cu | 105 ----- torchaudio/csrc/rnnt/gpu/compute_alphas.cu | 73 --- torchaudio/csrc/rnnt/gpu/compute_betas.cu | 78 ---- torchaudio/csrc/rnnt/gpu/gpu_kernel_utils.cuh | 99 ---- torchaudio/csrc/rnnt/gpu/gpu_kernels.cuh | 431 ------------------ torchaudio/csrc/rnnt/gpu/gpu_transducer.h | 393 ---------------- torchaudio/csrc/rnnt/gpu/half.cuh | 38 -- torchaudio/csrc/rnnt/gpu/kernel_utils.h | 59 --- torchaudio/csrc/rnnt/gpu/kernels.h | 133 ------ torchaudio/csrc/rnnt/gpu/math.cuh | 41 -- 11 files changed, 1460 deletions(-) delete mode 100644 test/torchaudio_unittest/rnnt/rnnt_loss_cuda_test.py delete mode 100644 torchaudio/csrc/rnnt/gpu/compute.cu delete mode 100644 torchaudio/csrc/rnnt/gpu/compute_alphas.cu delete mode 100644 torchaudio/csrc/rnnt/gpu/compute_betas.cu delete mode 100644 torchaudio/csrc/rnnt/gpu/gpu_kernel_utils.cuh delete mode 100644 torchaudio/csrc/rnnt/gpu/gpu_kernels.cuh delete mode 100644 torchaudio/csrc/rnnt/gpu/gpu_transducer.h delete mode 100644 torchaudio/csrc/rnnt/gpu/half.cuh delete mode 100644 torchaudio/csrc/rnnt/gpu/kernel_utils.h delete mode 100644 torchaudio/csrc/rnnt/gpu/kernels.h delete mode 100644 torchaudio/csrc/rnnt/gpu/math.cuh diff --git a/test/torchaudio_unittest/rnnt/rnnt_loss_cuda_test.py b/test/torchaudio_unittest/rnnt/rnnt_loss_cuda_test.py deleted file mode 100644 index c64fd687fe..0000000000 --- a/test/torchaudio_unittest/rnnt/rnnt_loss_cuda_test.py +++ /dev/null @@ -1,10 +0,0 @@ -import torch -from .rnnt_loss_impl import RNNTLossTest -from torchaudio_unittest import common_utils -from .utils import skipIfNoTransducer - - -@skipIfNoTransducer -@common_utils.skipIfNoCuda -class TestRNNTLoss(RNNTLossTest, common_utils.PytorchTestCase): - device = torch.device('cuda') diff --git a/torchaudio/csrc/rnnt/gpu/compute.cu b/torchaudio/csrc/rnnt/gpu/compute.cu deleted file mode 100644 index 8582f36d48..0000000000 --- a/torchaudio/csrc/rnnt/gpu/compute.cu +++ /dev/null @@ -1,105 +0,0 @@ -#include -#include -#include - -namespace torchaudio { -namespace rnnt { -namespace gpu { - -// Entry point into RNNT Loss -std::tuple> -compute( - torch::Tensor& logits, - const torch::Tensor& targets, - const torch::Tensor& src_lengths, - const torch::Tensor& tgt_lengths, - int64_t blank, - double clamp, - bool fused_log_smax = true, - bool reuse_logits_for_grads = true) { - - Options options; - options.batchSize_ = src_lengths.size(0); - options.nHypos_ = tgt_lengths.size(0) / src_lengths.size(0); - options.maxSrcLen_ = logits.size(1); - options.maxTgtLen_ = logits.size(2); - options.numTargets_ = logits.size(3); - options.blank_ = blank; - options.clamp_ = clamp; - options.fusedLogSmax_ = fused_log_smax; - - CHECK_EQ(logits.device().type(), torch::DeviceType::CUDA); - options.stream_ = at::cuda::getCurrentCUDAStream(); - cudaSetDevice(logits.get_device()); - options.device_ = GPU; - - torch::Tensor costs = torch::empty( - options.batchSize_ * options.nHypos_, - torch::TensorOptions().device(logits.device()).dtype(logits.dtype())); - c10::optional gradients = c10::nullopt; - if (logits.requires_grad()) { - if (reuse_logits_for_grads) { - gradients = logits; - } else { - gradients = torch::zeros_like(logits); - } - } - - torch::Tensor int_workspace = torch::empty( - IntWorkspace::ComputeSizeFromOptions(options), - torch::TensorOptions().device(logits.device()).dtype(torch::ScalarType::Int)); - - torch::Tensor float_workspace = torch::empty( - DtypeWorkspace::ComputeSizeFromOptions(options), - torch::TensorOptions().device(logits.device()).dtype(torch::ScalarType::Float)); - - Workspace workspace( - /*options=*/options, - /*dtype_data=*/float_workspace.data(), - /*dtype_size=*/float_workspace.numel(), - /*int_data=*/int_workspace.data(), - /*int_size=*/int_workspace.numel()); - - switch (logits.type().scalarType()) { - case torch::ScalarType::Float: - { - Compute( - /*workspace=*/workspace, - /*logits=*/logits.data(), - /*targets=*/targets.data(), - /*src_lengths=*/src_lengths.data(), - /*tgt_lengths=*/tgt_lengths.data(), - /*costs=*/costs.data(), - /*gradients=*/(gradients == c10::nullopt)? nullptr : gradients->data()); - break; - } - case torch::ScalarType::Half: - { - Compute( - /*workspace=*/workspace, - /*logits=*/logits.data(), - /*targets=*/targets.data(), - /*src_lengths=*/src_lengths.data(), - /*tgt_lengths=*/tgt_lengths.data(), - /*costs=*/costs.data(), - /*gradients=*/(gradients == c10::nullopt)? nullptr : gradients->data()); - break; - } - default: - { - LOG(ERROR) << "unsupported logits.type().scalarType() = " - << logits.type().scalarType(); - break; - } - }; - - return std::make_tuple(costs, gradients); -} - -TORCH_LIBRARY_IMPL(torchaudio, CUDA, m) { - m.impl("rnnt_loss", &compute); -} - -} // namespace gpu -} // namespace rnnt -} // namespace torchaudio diff --git a/torchaudio/csrc/rnnt/gpu/compute_alphas.cu b/torchaudio/csrc/rnnt/gpu/compute_alphas.cu deleted file mode 100644 index dc101b0ecb..0000000000 --- a/torchaudio/csrc/rnnt/gpu/compute_alphas.cu +++ /dev/null @@ -1,73 +0,0 @@ -#include -#include -#include - -namespace torchaudio { -namespace rnnt { -namespace gpu { - -torch::Tensor compute_alphas( - const torch::Tensor& logits, - const torch::Tensor& targets, - const torch::Tensor& src_lengths, - const torch::Tensor& tgt_lengths, - int64_t blank, - double clamp) { - Options options; - options.batchSize_ = src_lengths.size(0); - options.nHypos_ = tgt_lengths.size(0) / src_lengths.size(0); - options.maxSrcLen_ = logits.size(1); - options.maxTgtLen_ = logits.size(2); - options.numTargets_ = logits.size(3); - options.blank_ = blank; - options.clamp_ = clamp; - - CHECK_EQ(logits.device().type(), torch::DeviceType::CUDA); - options.stream_ = at::cuda::getCurrentCUDAStream(); - cudaSetDevice(logits.get_device()); - options.device_ = GPU; - - torch::Tensor alphas = torch::zeros( - {options.batchSize_ * options.nHypos_, - options.maxSrcLen_, - options.maxTgtLen_}, - torch::TensorOptions().device(logits.device()).dtype(logits.dtype())); - - torch::Tensor int_workspace = torch::empty( - IntWorkspace::ComputeSizeFromOptions(options), - torch::TensorOptions() - .device(logits.device()) - .dtype(torch::ScalarType::Int)); - - torch::Tensor float_workspace = torch::empty( - DtypeWorkspace::ComputeSizeFromOptions(options), - torch::TensorOptions() - .device(logits.device()) - .dtype(torch::ScalarType::Float)); - - Workspace workspace( - /*options=*/options, - /*dtype_data=*/float_workspace.data(), - /*dtype_size=*/float_workspace.numel(), - /*int_data=*/int_workspace.data(), - /*int_size=*/int_workspace.numel()); - - // Only support float, this is mainly to enable easy - // unit-testing - ComputeAlphas( - /*workspace=*/workspace, - /*logits=*/logits.data(), - /*targets=*/targets.data(), - /*src_lengths=*/src_lengths.data(), - /*tgt_lengths=*/tgt_lengths.data(), - /*alphas=*/alphas.data()); - return alphas; -} - -TORCH_LIBRARY_IMPL(torchaudio, CUDA, m) { - m.impl("rnnt_loss_alphas", &compute_alphas); -} - -} // namespace gpu -} // namespace rnnt -} // namespace torchaudio diff --git a/torchaudio/csrc/rnnt/gpu/compute_betas.cu b/torchaudio/csrc/rnnt/gpu/compute_betas.cu deleted file mode 100644 index 63b8fd636a..0000000000 --- a/torchaudio/csrc/rnnt/gpu/compute_betas.cu +++ /dev/null @@ -1,78 +0,0 @@ -#include -#include -#include - -namespace torchaudio { -namespace rnnt { -namespace gpu { - -torch::Tensor compute_betas( - const torch::Tensor& logits, - const torch::Tensor& targets, - const torch::Tensor& src_lengths, - const torch::Tensor& tgt_lengths, - int64_t blank, - double clamp) { - Options options; - options.batchSize_ = src_lengths.size(0); - options.nHypos_ = tgt_lengths.size(0) / src_lengths.size(0); - options.maxSrcLen_ = logits.size(1); - options.maxTgtLen_ = logits.size(2); - options.numTargets_ = logits.size(3); - options.blank_ = blank; - options.clamp_ = clamp; - - CHECK_EQ(logits.device().type(), torch::DeviceType::CUDA); - options.stream_ = at::cuda::getCurrentCUDAStream(); - cudaSetDevice(logits.get_device()); - options.device_ = GPU; - - torch::Tensor costs = torch::empty( - tgt_lengths.size(0), - torch::TensorOptions().device(logits.device()).dtype(logits.dtype())); - - torch::Tensor betas = torch::zeros( - {options.batchSize_ * options.nHypos_, - options.maxSrcLen_, - options.maxTgtLen_}, - torch::TensorOptions().device(logits.device()).dtype(logits.dtype())); - - torch::Tensor int_workspace = torch::empty( - IntWorkspace::ComputeSizeFromOptions(options), - torch::TensorOptions() - .device(logits.device()) - .dtype(torch::ScalarType::Int)); - - torch::Tensor float_workspace = torch::empty( - DtypeWorkspace::ComputeSizeFromOptions(options), - torch::TensorOptions() - .device(logits.device()) - .dtype(torch::ScalarType::Float)); - - Workspace workspace( - /*options=*/options, - /*dtype_data=*/float_workspace.data(), - /*dtype_size=*/float_workspace.numel(), - /*int_data=*/int_workspace.data(), - /*int_size=*/int_workspace.numel()); - - // Only support float, this is mainly to enable easy - // unit-testing - ComputeBetas( - /*workspace=*/workspace, - /*logits=*/logits.data(), - /*targets=*/targets.data(), - /*src_lengths=*/src_lengths.data(), - /*tgt_lengths=*/tgt_lengths.data(), - /*costs=*/costs.data(), - /*betas=*/betas.data()); - return betas; -} - -TORCH_LIBRARY_IMPL(torchaudio, CUDA, m) { - m.impl("rnnt_loss_betas", &compute_betas); -} - -} // namespace gpu -} // namespace rnnt -} // namespace torchaudio diff --git a/torchaudio/csrc/rnnt/gpu/gpu_kernel_utils.cuh b/torchaudio/csrc/rnnt/gpu/gpu_kernel_utils.cuh deleted file mode 100644 index f42e35b46f..0000000000 --- a/torchaudio/csrc/rnnt/gpu/gpu_kernel_utils.cuh +++ /dev/null @@ -1,99 +0,0 @@ -#pragma once - -#ifdef USE_CUDA - -#include - -namespace torchaudio { -namespace rnnt { - -template -__global__ void ReduceMax2D( - int dim, - const DTYPE* inputs, // [N, dim] - CAST_DTYPE* outputs) { - - __shared__ CAST_DTYPE shared[NUM_THREADS]; - - // each thread reduces one matrix row - int offset = blockIdx.x * dim; // [n, 0] - CAST_DTYPE val = inputs[offset]; // default = inputs(n, 0) - for (int d = threadIdx.x; d < dim; d += NUM_THREADS) { - CAST_DTYPE next = inputs[offset + d]; - if (next > val) { - val = next; - } - } - - shared[threadIdx.x] = val; - __syncthreads(); - - for (int stride = (NUM_THREADS >> 1); stride >= WARP_SIZE; stride >>= 1) { - if (threadIdx.x < stride && threadIdx.x + stride < dim) { - if (shared[threadIdx.x + stride] > shared[threadIdx.x]) { - shared[threadIdx.x] = shared[threadIdx.x + stride]; - val = shared[threadIdx.x]; - } - } - __syncthreads(); - } - - CAST_DTYPE shf; - for (int stride = (WARP_SIZE >> 1); stride > 0; stride >>= 1) { - shf = __shfl_down_sync(0xFFFFFFFF, val, stride); - if (threadIdx.x < stride && threadIdx.x + stride < dim) { - if (shf > val) { - val = shf; - } - } - } - - if (threadIdx.x == 0) { - outputs[blockIdx.x] = val; - } -} - -template -__global__ void ReduceLogSumExpGivenMax2D( - int dim, - const DTYPE* inputs, // [N, dim] - CAST_DTYPE* outputs) { // in: max -> out: logsum - - __shared__ CAST_DTYPE shared[NUM_THREADS]; - - CAST_DTYPE max = outputs[blockIdx.x]; - CAST_DTYPE val = 0; - - int offset = blockIdx.x * dim; - for (int d = threadIdx.x; d < dim; d += NUM_THREADS) { - val = val + std::exp(CAST_DTYPE(inputs[offset + d]) - max); - } - - shared[threadIdx.x] = val; - __syncthreads(); - - for (int stride = (NUM_THREADS >> 1); stride >= WARP_SIZE; stride >>= 1) { - if (threadIdx.x < stride && threadIdx.x + stride < dim) { - val = shared[threadIdx.x] + shared[threadIdx.x + stride]; - shared[threadIdx.x] = val; - } - __syncthreads(); - } - - CAST_DTYPE shf; - for (int stride = (WARP_SIZE >> 1); stride > 0; stride >>= 1) { - shf = __shfl_down_sync(0xFFFFFFFF, val, stride); - if (threadIdx.x < stride && threadIdx.x + stride < dim) { - val = val + shf; - } - } - - if (threadIdx.x == 0) { - outputs[blockIdx.x] = max + std::log(val); - } -} - -} // namespace rnnt -} // namespace torchaudio - -#endif // USE_CUDA diff --git a/torchaudio/csrc/rnnt/gpu/gpu_kernels.cuh b/torchaudio/csrc/rnnt/gpu/gpu_kernels.cuh deleted file mode 100644 index a2d724bf8f..0000000000 --- a/torchaudio/csrc/rnnt/gpu/gpu_kernels.cuh +++ /dev/null @@ -1,431 +0,0 @@ -#pragma once - -#ifdef USE_CUDA - -#include - -#include -#include -#include - -namespace torchaudio { -namespace rnnt { - - -template -__global__ void ComputeLogProbs( - int maxSrcLen, - int maxTgtLen, - int numTargets, - int blank, - const DTYPE* logits, - const int* targets, - const int* srcLengths, - const int* tgtLengths, - const CAST_DTYPE* denominators, - CAST_DTYPE* logProbs, - int H=1, - bool fusedLogSmax=true) { - - const int& maxT = maxSrcLen; - const int& maxU = maxTgtLen; - const int& D = numTargets; - - const int bTgt = blockIdx.z; // 0 <= b < B - const int bSrc = bTgt / H; - const int T = srcLengths[bSrc]; - const int U = tgtLengths[bTgt] + 1; - - const int t = blockIdx.x * blockDim.x + threadIdx.x; - const int u = blockIdx.y; - - if (t >= T || u >= U) { // out of boundary. - return; - } - - Indexer3D indexer(maxT, maxU); - - int idx = indexer(bTgt, t, u); - - // skip: log_prob(b, t, u).skip() = logits(b, t, u, blank) - denom(b, t, u). - logProbs[(idx << 1) + LOG_PROBS_SKIP_IDX] = - CAST_DTYPE(logits[idx * D + blank]) - denominators[idx]; - - if (!fusedLogSmax) { - logProbs[(idx << 1) + LOG_PROBS_SKIP_IDX] = - CAST_DTYPE(logits[idx * D + blank]); - } - - if (u < U - 1) { - // emit: log_prob(b, t, u).emit() = logits(b, t, u, tgt[u]) - denom(b, t, u). - int target = targets[Indexer2D(maxU - 1)(bTgt, u)]; - logProbs[(idx << 1) + LOG_PROBS_EMIT_IDX] = - CAST_DTYPE(logits[idx * D + target]) - denominators[idx]; - - if (!fusedLogSmax) { - logProbs[(idx << 1) + LOG_PROBS_EMIT_IDX] = - CAST_DTYPE(logits[idx * D + target]); - } - } - - -} - - -template -__device__ void ComputeAlphas( - int maxSrcLen, - int maxTgtLen, - int numTargets, - int blank, - const CAST_DTYPE* logProbs, - const int* srcLengths, - const int* tgtLengths, - int* alpha_counters, - volatile CAST_DTYPE* alphas, - int H=1) { - - const int& maxT = maxSrcLen; - const int& maxU = maxTgtLen; - - const int bTgt = blockIdx.z; // 0 <= b < B - const int bSrc = bTgt / H; - const int T = srcLengths[bSrc]; - const int U = tgtLengths[bTgt] + 1; - - const int t = blockIdx.x * blockDim.x + threadIdx.x + 1; - const int u = blockIdx.y + 1; - - if (t >= T || u >= U) { // out of boundary. - return; - } - - int* counter = alpha_counters + Indexer2D(maxU)(bTgt, blockIdx.y); - - Indexer3D idxr(maxT, maxU); - - if (t == 1 && u == 1) { - alphas[idxr(bTgt, 0, 0)] = 0; - } - - if (blockIdx.x > 0) { // wait for previous warp (in t-axis) is ready. - while (atomicAdd(counter, 0) < blockIdx.x) {} - } - - if (blockIdx.y > 0) { // wait for previous warp (in u-axis) is ready. - while (atomicAdd(counter - 1, 0) <= blockIdx.x) {} - } - - if (t == 1 && u < U) { - - // alpha(0, u) = alpha(0, u - 1) + logProbs(0, u - 1).emit(). - alphas[idxr(bTgt, 0, u)] = - alphas[idxr(bTgt, 0, u - 1)] - + logProbs[(idxr(bTgt, 0, u - 1) << 1) + LOG_PROBS_EMIT_IDX]; - } - - if (blockIdx.y == 0 && t < T) { - CAST_DTYPE skip_prob = logProbs[(idxr(bTgt, t - 1, 0) << 1) + LOG_PROBS_SKIP_IDX]; - CAST_DTYPE val; - -#pragma unroll - for (int i = 1; i < warpSize; i <<= 1) { - val = __shfl_up_sync(0xffffffff, skip_prob, i); - if (i <= threadIdx.x) { - skip_prob = skip_prob + val; - } - } - - val = alphas[idxr(bTgt, blockIdx.x * blockDim.x, 0)]; - alphas[idxr(bTgt, t, 0)] = skip_prob + val; - } - - if (t < T && u < U) { - - CAST_DTYPE skip_prob = logProbs[(idxr(bTgt, t - 1, u) << 1) + LOG_PROBS_SKIP_IDX]; - CAST_DTYPE emit_prob = logProbs[(idxr(bTgt, t, u - 1) << 1) + LOG_PROBS_EMIT_IDX]; - - CAST_DTYPE skip = alphas[idxr(bTgt, blockIdx.x * blockDim.x, u)] + skip_prob; - CAST_DTYPE emit = alphas[idxr(bTgt, t, u - 1)] + emit_prob; - - CAST_DTYPE val = math::lse(skip, emit); - CAST_DTYPE out = val; - - for(int i = 1; i < warpSize; ++i) { - val = __shfl_up_sync(0xffffffff, val, 1); - if (i == threadIdx.x) { - val = math::lse(val + skip_prob, emit); - out = val; - } - } - - alphas[idxr(bTgt, t, u)] = out; - } - - if (threadIdx.x == 0) { - __threadfence(); - atomicAdd(counter, 1); - } -} - - -template -__device__ void ComputeBetasCosts( - int maxSrcLen, - int maxTgtLen, - int numTargets, - int blank, - const CAST_DTYPE* logProbs, - const int* srcLengths, - const int* tgtLengths, - int* betaCounters, - volatile CAST_DTYPE* betas, - DTYPE* costs, - int H=1) { - - const int& maxT = maxSrcLen; - const int& maxU = maxTgtLen; - - const int bTgt = blockIdx.z; // 0 <= b < B - const int bSrc = bTgt / H; - const int T = srcLengths[bSrc]; - const int U = tgtLengths[bTgt] + 1; - - const int t = T - 2 - blockIdx.x * blockDim.x - threadIdx.x; - const int u = U - 2 - blockIdx.y; - - if (t < 0 || u < 0) { // out of boundary. - return; - } - - int* counter = betaCounters + Indexer2D(maxU)(bTgt, blockIdx.y); - - Indexer3D idxr(maxT, maxU); - - if (t == T - 2 && u == U - 2) { - betas[idxr(bTgt, T - 1, U - 1)] = - logProbs[(idxr(bTgt, T - 1, U - 1) << 1) + LOG_PROBS_SKIP_IDX]; - } - - if (blockIdx.x > 0) { // wait for previous warp (in t-axis) is ready. - while (atomicAdd(counter, 0) < blockIdx.x) {} - } - - if (blockIdx.y > 0) { // wait for previous warp (in u-axis) is ready. - while (atomicAdd(counter - 1, 0) <= blockIdx.x) {} - } - - if (t == T - 2 && u >= 0) { - - betas[idxr(bTgt, T - 1, u)] = - betas[idxr(bTgt, T - 1, u + 1)] - + logProbs[(idxr(bTgt, T - 1, u) << 1) + LOG_PROBS_EMIT_IDX]; - } - - if (blockIdx.y == 0 && t >= 0) { - CAST_DTYPE skip_prob = logProbs[(idxr(bTgt, t, U - 1) << 1) + LOG_PROBS_SKIP_IDX]; - CAST_DTYPE val; - -#pragma unroll - for(int i = 1; i < warpSize; i <<= 1) { - val = __shfl_up_sync(0xffffffff, skip_prob, i); - if (i <= threadIdx.x) { - skip_prob = skip_prob + val; - } - } - - betas[idxr(bTgt, t, U - 1)] = - betas[idxr(bTgt, T - 1 - blockIdx.x * blockDim.x, U - 1)] + skip_prob; - } - - if (t >= 0 && u >= 0) { - - CAST_DTYPE skip_prob = logProbs[(idxr(bTgt, t, u) << 1) + LOG_PROBS_SKIP_IDX]; - CAST_DTYPE emit_prob = logProbs[(idxr(bTgt, t, u) << 1) + LOG_PROBS_EMIT_IDX]; - - CAST_DTYPE skip = betas[idxr(bTgt, t + threadIdx.x + 1, u)] + skip_prob; - CAST_DTYPE emit = betas[idxr(bTgt, t, u + 1)] + emit_prob; - - CAST_DTYPE val = math::lse(skip, emit); - CAST_DTYPE out = val; - - for(int i = 1; i < warpSize; ++i) { - val = __shfl_up_sync(0xffffffff, val, 1); - if (i == threadIdx.x) { - val = math::lse(val + skip_prob, emit); - out = val; - } - } - - betas[idxr(bTgt, t, u)] = out; - - if (t == 0 && u == 0) { // use -beta(0, 0) as cost. - costs[bTgt] = DTYPE(-out); - } - } - - if (threadIdx.x == 0) { - __threadfence(); - atomicAdd(counter, 1); - } -} - - -template -__global__ void ComputeAlphasBetasCosts( - int maxSrcLen, - int maxTgtLen, - int numTargets, - int blank, - const CAST_DTYPE* logProbs, - const int* srcLengths, - const int* tgtLengths, - int* alpha_counters, - volatile CAST_DTYPE* alphas, - int* betaCounters, - volatile CAST_DTYPE* betas, - DTYPE* costs, - int warpSize = 0, - int numWarps=0, - int H = 1) { - - assert(threadIdx.y == 0 || threadIdx.y == 1); - - if (threadIdx.y == 0) { - - ComputeAlphas( - /*maxSrcLen=*/maxSrcLen, - /*maxTgtLen=*/maxTgtLen, - /*numTargets=*/numTargets, - /*blank=*/blank, - /*logProbs=*/logProbs, - /*srcLengths=*/srcLengths, - /*tgtLengths=*/tgtLengths, - /*alpha_counters=*/alpha_counters, - /*alphas=*/alphas, - H); - } else { // threadIdx.y == 1 - ComputeBetasCosts( - /*maxSrcLen=*/maxSrcLen, - /*maxTgtLen=*/maxTgtLen, - /*numTargets=*/numTargets, - /*blank=*/blank, - /*logProbs=*/logProbs, - /*srcLengths=*/srcLengths, - /*tgtLengths=*/tgtLengths, - /*betaCounters=*/betaCounters, - /*beta=*/betas, - /*costs=*/costs, - H); - } -} - - -template -__global__ void ComputeGradients( - int maxSrcLen, - int maxTgtLen, - int numTargets, - int blank, - CAST_DTYPE clamp, - const DTYPE* logits, - const int* targets, - const int* srcLengths, - const int* tgtLengths, - const CAST_DTYPE* denominators, - const CAST_DTYPE* alphas, - const CAST_DTYPE* betas, - DTYPE* gradients, - int H = 1, - bool fusedLogSmax = true) { - - const int bTgt = blockIdx.z; // 0 <= b < B - const int t = blockIdx.x * blockDim.x + threadIdx.x; - const int u = blockIdx.y; - - ComputeGradientsElement( - bTgt, - t, - u, - maxSrcLen, - maxTgtLen, - numTargets, - blank, - clamp, - logits, - targets, - srcLengths, - tgtLengths, - denominators, - alphas, - betas, - gradients, - H, - fusedLogSmax); -} - - -// This is a __global__ wrapper around ComputeAlphas -// device kernel to enable unit testing -template -__global__ void ComputeAlphasWrapper( - int maxSrcLen, - int maxTgtLen, - int numTargets, - int blank, - const CAST_DTYPE* logProbs, - const int* srcLengths, - const int* tgtLengths, - int* alpha_counters, - volatile CAST_DTYPE* alphas, - int H=1) { - ComputeAlphas( - maxSrcLen, - maxTgtLen, - numTargets, - blank, - logProbs, - srcLengths, - tgtLengths, - alpha_counters, - alphas, - H); -} - -// This is a __global__ wrapper around ComputeBetas -// device kernel to enable unit testing -template -__global__ void ComputeBetasWrapper( - int maxSrcLen, - int maxTgtLen, - int numTargets, - int blank, - const CAST_DTYPE* logProbs, - const int* srcLengths, - const int* tgtLengths, - int* betaCounters, - volatile CAST_DTYPE* betas, - DTYPE* costs, - int H=1) { - ComputeBetasCosts( - maxSrcLen, - maxTgtLen, - numTargets, - blank, - logProbs, - srcLengths, - tgtLengths, - betaCounters, - betas, - costs, - H); -} - - -// #undef LOG_PROBS_SKIP_IDX -// #undef LOG_PROBS_EMIT_IDX - -} // namespace rnnt -} // namespace torchaudio - -#endif // USE_CUDA diff --git a/torchaudio/csrc/rnnt/gpu/gpu_transducer.h b/torchaudio/csrc/rnnt/gpu/gpu_transducer.h deleted file mode 100644 index 1720b55645..0000000000 --- a/torchaudio/csrc/rnnt/gpu/gpu_transducer.h +++ /dev/null @@ -1,393 +0,0 @@ -#pragma once - -#ifdef USE_CUDA - -#include -#include -#include - -namespace torchaudio { -namespace rnnt { -namespace gpu { - -#define gpuErrchk(ans) \ - { gpuAssert((ans), __FILE__, __LINE__); } - -inline void -gpuAssert(cudaError_t code, const char* file, int line, bool abort = true) { - if (code != cudaSuccess) { - fprintf( - stderr, - "\nGPUassert: %s %s %d\n", - cudaGetErrorString(code), - file, - line); - if (abort) - exit(code); - } -} - -template -status_t LogSumExp2D( - cudaStream_t stream, - int N, - int D, - const DTYPE* logits, // [N, D] - CAST_DTYPE* outputs) { - { // compute max among D. - dim3 block_dims(N); - dim3 thread_dims(REDUCE_THREADS); - - ReduceMax2D - <<>>( - /*dim=*/D, - /*inputs=*/logits, - /*outputs=*/outputs); - - // BUGBUG: These error codes are only accurate when launching with - // blocking. Otherwise they usually reflect earlier errors. - if (cudaGetLastError() != cudaSuccess) { - return COMPUTE_DENOMINATOR_REDUCE_MAX_FAILED; - } - } - - { // compute log(sum(exp(d_i - max))) - dim3 block_dims(N); - dim3 thread_dims(REDUCE_THREADS); - - ReduceLogSumExpGivenMax2D - <<>>( - /*dim=*/D, - /*inputs=*/logits, - /*outputs=*/outputs); - - if (cudaGetLastError() != cudaSuccess) { - return COMPUTE_DENOMINATOR_REDUCE_SUM_FAILED; - } - } - - return SUCCESS; -} - -// Inputs: -// workspace: workspace. -// logits: pointer to (B, max_T, max_U, D) logits. -// targets: pointer to (B, max_U - 1) targets in the batch. -// srcLengths: pointer to (B, ) source lengths in the batch. -// tgtLengths: pointer to (B, ) target lengths in the batch. -// -// Outputs: -// costs: pointer to (B, ) costs in the batch. -// gradients: pointer to (B, max_T, max_U, D) gradients in the batch. -template -status_t Compute( - const Workspace& workspace, - const DTYPE* logits, - const int* targets, - const int* srcLengths, - const int* tgtLengths, - DTYPE* costs, - DTYPE* gradients = nullptr) { - const Options& options = workspace.GetOptions(); - - const cudaStream_t& stream = options.stream_; - const int& B = options.batchSize_; - const int& H = options.nHypos_; - const int& max_T = options.maxSrcLen_; - const int& max_U = options.maxTgtLen_; - const int& D = options.numTargets_; - const int& blank = options.blank_; - const CAST_DTYPE clamp = options.clamp_; - - const bool& fusedLogSmax = options.fusedLogSmax_; - - { // compute denominators. - status_t status = LogSumExp2D( - /*stream=*/stream, - /*N=*/B * H * max_T * max_U, - /*D=*/D, - /*logits=*/logits, - /*denominators=*/workspace.GetPointerToDenominators()); - - if (status != SUCCESS) { - return status; - } - } - - { // compute log probability pairs (blank and target). - int num_segments = - (max_T + MAX_THREADS_PER_BLOCK - 1) / MAX_THREADS_PER_BLOCK; - dim3 block_dims(num_segments, max_U, B * H); - dim3 thread_dims(MAX_THREADS_PER_BLOCK); - - ComputeLogProbs<<>>( - /*max_src_len=*/max_T, - /*max_tgt_len=*/max_U, - /*num_targets=*/D, - /*blank=*/blank, - /*logits=*/logits, - /*targets=*/targets, - /*srcLengths=*/srcLengths, - /*tgtLengths=*/tgtLengths, - /*denominators=*/workspace.GetPointerToDenominators(), - /*log_probs=*/workspace.GetPointerToLogProbs(), - H, - fusedLogSmax); - - if (cudaGetLastError() != cudaSuccess) { - return COMPUTE_LOG_PROBS_FAILED; - } - } - - { // compute alphas, betas and costs. - // warp is usually a group of threads (32) - int num_warps = (max_T + WARP_SIZE - 1) / WARP_SIZE; - - // each block is identified by 3 d tuple. - // we are using num_warp * max_U * B * H blocks - // where num_warp is division among Time axis - dim3 block_dims(num_warps, max_U, B * H); - - // each thread is identified by a 2 d tuple - // 2nd dim is 2. 1 for alpha, 1 for beta - dim3 thread_dims(WARP_SIZE, 2); - - ComputeAlphasBetasCosts - <<>>( - /*max_src_len=*/max_T, - /*max_tgt_len=*/max_U, - /*num_targets=*/D, - /*blank=*/blank, - /*log_probs=*/workspace.GetPointerToLogProbs(), - /*srcLengths=*/srcLengths, - /*tgtLengths=*/tgtLengths, - /*alpha_counters=*/workspace.GetPointerToAlphaCounters(), - /*alphas=*/workspace.GetPointerToAlphas(), - /*beta_counters=*/workspace.GetPointerToBetaCounters(), - /*betas=*/workspace.GetPointerToBetas(), - /*costs=*/costs, - /*warp_size=*/WARP_SIZE, - /*num_warps=*/num_warps, - H); - if (cudaGetLastError() != cudaSuccess) { - return COMPUTE_ALPHAS_BETAS_COSTS_FAILED; - } - } - - if (gradients != nullptr) { // compute gradients. - // don't set gradients to zero to here as gradients might reuse memory from - // logits - - int num_blocks = - (max_T + MAX_THREADS_PER_BLOCK - 1) / MAX_THREADS_PER_BLOCK; - dim3 block_dims(num_blocks, max_U, B * H); - dim3 thread_dims(MAX_THREADS_PER_BLOCK); - - ComputeGradients<<>>( - /*max_src_len=*/max_T, - /*max_tgt_len=*/max_U, - /*num_targets=*/D, - /*blank=*/blank, - /*clamp=*/clamp, - /*logits=*/logits, - /*targets=*/targets, - /*srcLengths=*/srcLengths, - /*tgtLengths=*/tgtLengths, - /*denominators=*/workspace.GetPointerToDenominators(), - /*alphas=*/workspace.GetPointerToAlphas(), - /*betas=*/workspace.GetPointerToBetas(), - /*gradients=*/gradients, - H, - fusedLogSmax); - if (cudaGetLastError() != cudaSuccess) { - return COMPUTE_GRADIENTS_FAILED; - } - } - - return SUCCESS; -} - -template -status_t ComputeAlphas( - const Workspace& workspace, - const DTYPE* logits, - const int* targets, - const int* srcLengths, - const int* tgtLengths, - DTYPE* alphas) { - const Options& options = workspace.GetOptions(); - - const cudaStream_t& stream = options.stream_; - const int& B = options.batchSize_; - const int& H = options.nHypos_; - const int& max_T = options.maxSrcLen_; - const int& max_U = options.maxTgtLen_; - const int& D = options.numTargets_; - const int& blank = options.blank_; - - { // compute denominators. - status_t status = LogSumExp2D( - /*stream=*/stream, - /*N=*/B * H * max_T * max_U, - /*D=*/D, - /*logits=*/logits, - /*denominators=*/workspace.GetPointerToDenominators()); - - if (status != SUCCESS) { - return status; - } - } - - { // compute log probability pairs (blank and target). - int num_segments = - (max_T + MAX_THREADS_PER_BLOCK - 1) / MAX_THREADS_PER_BLOCK; - dim3 block_dims(num_segments, max_U, B * H); - dim3 thread_dims(MAX_THREADS_PER_BLOCK); - - ComputeLogProbs<<>>( - /*max_src_len=*/max_T, - /*max_tgt_len=*/max_U, - /*num_targets=*/D, - /*blank=*/blank, - /*logits=*/logits, - /*targets=*/targets, - /*srcLengths=*/srcLengths, - /*tgtLengths=*/tgtLengths, - /*denominators=*/workspace.GetPointerToDenominators(), - /*log_probs=*/workspace.GetPointerToLogProbs(), - H); - - if (cudaGetLastError() != cudaSuccess) { - return COMPUTE_LOG_PROBS_FAILED; - } - } - { // compute alphas - // warp is usually a group of threads (32) - int num_warps = (max_T + WARP_SIZE - 1) / WARP_SIZE; - - // each block is identified by 3 d tuple. - // we are using num_warp * max_U * B blocks - // where num_warp is division among Time axis - dim3 block_dims(num_warps, max_U, B * H); - - // each thread is identified by a 2 d tuple - // 2nd dim is 1 for alpha only - dim3 thread_dims(WARP_SIZE, 1); - - - ComputeAlphasWrapper - <<>>( - /*max_src_len=*/max_T, - /*max_tgt_len=*/max_U, - /*num_targets=*/D, - /*blank=*/blank, - /*log_probs=*/workspace.GetPointerToLogProbs(), - /*srcLengths=*/srcLengths, - /*tgtLengths=*/tgtLengths, - /*alpha_counters=*/workspace.GetPointerToAlphaCounters(), - /*alphas=*/(volatile DTYPE*)alphas, - H); - - if (cudaGetLastError() != cudaSuccess) { - return COMPUTE_ALPHAS_BETAS_COSTS_FAILED; - } - } - - return SUCCESS; -} - -template -status_t ComputeBetas( - const Workspace& workspace, - const DTYPE* logits, - const int* targets, - const int* srcLengths, - const int* tgtLengths, - DTYPE* costs, - DTYPE* betas) { - const Options& options = workspace.GetOptions(); - - const cudaStream_t& stream = options.stream_; - const int& B = options.batchSize_; - const int& H = options.nHypos_; - const int& max_T = options.maxSrcLen_; - const int& max_U = options.maxTgtLen_; - const int& D = options.numTargets_; - const int& blank = options.blank_; - - { // compute denominators. - status_t status = LogSumExp2D( - /*stream=*/stream, - /*N=*/B * H * max_T * max_U, - /*D=*/D, - /*logits=*/logits, - /*denominators=*/workspace.GetPointerToDenominators()); - - if (status != SUCCESS) { - return status; - } - } - - { // compute log probability pairs (blank and target). - int num_segments = - (max_T + MAX_THREADS_PER_BLOCK - 1) / MAX_THREADS_PER_BLOCK; - dim3 block_dims(num_segments, max_U, B * H); - dim3 thread_dims(MAX_THREADS_PER_BLOCK); - - ComputeLogProbs<<>>( - /*max_src_len=*/max_T, - /*max_tgt_len=*/max_U, - /*num_targets=*/D, - /*blank=*/blank, - /*logits=*/logits, - /*targets=*/targets, - /*srcLengths=*/srcLengths, - /*tgtLengths=*/tgtLengths, - /*denominators=*/workspace.GetPointerToDenominators(), - /*log_probs=*/workspace.GetPointerToLogProbs(), - H); - - if (cudaGetLastError() != cudaSuccess) { - return COMPUTE_LOG_PROBS_FAILED; - } - } - { // compute betas - // warp is usually a group of threads (32) - int num_warps = (max_T + WARP_SIZE - 1) / WARP_SIZE; - - // each block is identified by 3 d tuple. - // we are using num_warp * max_U * B blocks - // where num_warp is division among Time axis - dim3 block_dims(num_warps, max_U, B * H); - - // each thread is identified by a 2 d tuple - // 2nd dim is 1 for betas only - dim3 thread_dims(WARP_SIZE, 1); - - ComputeBetasWrapper - <<>>( - /*max_src_len=*/max_T, - /*max_tgt_len=*/max_U, - /*num_targets=*/D, - /*blank=*/blank, - /*log_probs=*/workspace.GetPointerToLogProbs(), - /*srcLengths=*/srcLengths, - /*tgtLengths=*/tgtLengths, - /*alpha_counters=*/workspace.GetPointerToBetaCounters(), - /*alphas=*/(volatile DTYPE*)betas, - costs, - H); - - if (cudaGetLastError() != cudaSuccess) { - return COMPUTE_ALPHAS_BETAS_COSTS_FAILED; - } - } - - return SUCCESS; -} - -} // namespace gpu -} // namespace rnnt -} // namespace torchaudio - -#endif // USE_CUDA diff --git a/torchaudio/csrc/rnnt/gpu/half.cuh b/torchaudio/csrc/rnnt/gpu/half.cuh deleted file mode 100644 index d49ac3bdcf..0000000000 --- a/torchaudio/csrc/rnnt/gpu/half.cuh +++ /dev/null @@ -1,38 +0,0 @@ -#pragma once - -#ifdef USE_C10_HALF -#include "c10/util/Half.h" -#endif // USE_C10_HALF - -#include - -namespace torchaudio { -namespace rnnt { - -struct alignas(sizeof(__half)) Half { - __half x; - - HOST_AND_DEVICE Half() = default; - - FORCE_INLINE HOST_AND_DEVICE Half(float f) { - x = __float2half_rn(f); - if (isinf(__half2float(x))) { - x = __float2half_rz(f); // round toward 0. - } - } - - FORCE_INLINE HOST_AND_DEVICE operator float() const { - return __half2float(x); - } - - FORCE_INLINE HOST_AND_DEVICE Half(__half f) { - x = f; - } - - FORCE_INLINE HOST_AND_DEVICE operator __half() const { - return x; - } -}; - -} // namespace rnnt -} // namespace torchaudio diff --git a/torchaudio/csrc/rnnt/gpu/kernel_utils.h b/torchaudio/csrc/rnnt/gpu/kernel_utils.h deleted file mode 100644 index 03eb3d33b4..0000000000 --- a/torchaudio/csrc/rnnt/gpu/kernel_utils.h +++ /dev/null @@ -1,59 +0,0 @@ -#pragma once - -#include - -#include - -namespace torchaudio { -namespace rnnt { - -inline HOST_AND_DEVICE bool in_range( - int start, - int end, // inclusive - int val) { - return start <= val && val <= end; -} - -#define LOG_PROBS_SKIP_IDX 0 -#define LOG_PROBS_EMIT_IDX 1 - - -struct Indexer2D { - const int& size2_; - - FORCE_INLINE HOST_AND_DEVICE Indexer2D(const int& size2): size2_(size2) {} - - FORCE_INLINE HOST_AND_DEVICE int operator() (int index1, int index2) { - return index1 * size2_ + index2; - } -}; - - -struct Indexer3D { - const int& size2_; - const int& size3_; - - FORCE_INLINE HOST_AND_DEVICE Indexer3D(const int& size2, const int& size3) - : size2_(size2), size3_(size3) {} - - FORCE_INLINE HOST_AND_DEVICE int operator() (int index1, int index2, int index3) { - return (index1 * size2_ + index2) * size3_ + index3; - } -}; - - -struct Indexer4D { - const int& size2_; - const int& size3_; - const int& size4_; - - HOST_AND_DEVICE Indexer4D(const int& size2, const int& size3, const int& size4) - : size2_(size2), size3_(size3), size4_(size4) {} - - HOST_AND_DEVICE int operator() (int index1, int index2, int index3, int index4) { - return ((index1 * size2_ + index2) * size3_ + index3) * size4_ + index4; - } -}; - -} // namespace rnnt -} // namespace torchaudio diff --git a/torchaudio/csrc/rnnt/gpu/kernels.h b/torchaudio/csrc/rnnt/gpu/kernels.h deleted file mode 100644 index 2cbef51327..0000000000 --- a/torchaudio/csrc/rnnt/gpu/kernels.h +++ /dev/null @@ -1,133 +0,0 @@ -#pragma once - -#include - -#include -#include - -namespace torchaudio { -namespace rnnt { - - -template -HOST_AND_DEVICE void ComputeGradientsElement( - int bTgt, - int t, - int u, - int maxSrcLen, - int maxTgtLen, - int numTargets, - int blank, - CAST_DTYPE clamp, - const DTYPE* logits, - const int* targets, - const int* srcLengths, - const int* tgtLengths, - const CAST_DTYPE* denominators, - const CAST_DTYPE* alphas, - const CAST_DTYPE* betas, - DTYPE* gradients, - int H = 1, - bool fusedLogSmax = true) { - - const int& maxT = maxSrcLen; - const int& maxU = maxTgtLen; - const int& D = numTargets; - - const int bSrc = bTgt / H; - const int T = srcLengths[bSrc]; - const int U = tgtLengths[bTgt] + 1; - - if (t >= T || u >= U) { // out of boundary. - if (gradients == logits && t < maxT && u < maxU) { - // gradients and logits are pointing to the same memory location - Indexer3D idxr3(maxT, maxU); - int idx_b_t_u_zero = idxr3(bTgt, t, u); - if (idx_b_t_u_zero != -1 ) { - int start = idx_b_t_u_zero * D; - for (int b_t_u_d = start; b_t_u_d < start + D; ++b_t_u_d) { - gradients[b_t_u_d] = 0; - } - } - } - return; - } - - int costIdx = bTgt * maxT * maxU; - CAST_DTYPE cost = -(betas[costIdx]); - - - Indexer2D idxr2(maxU - 1); - - int idx_b_t_u, idx_b_t_up1, idx_b_tp1_u, idx_b_tp1_up1; - Indexer3D idxr3(maxT, maxU); - idx_b_t_u = idxr3(bTgt, t, u); - idx_b_t_up1 = idxr3(bTgt, t, u+1); - idx_b_tp1_u = idxr3(bTgt, t+1, u); - idx_b_tp1_up1 = idxr3(bTgt, t+1, u+1); - - if (idx_b_t_u == -1 ) { - return; - } - - if (isinf(cost) || isnan(cost)) { - for (int d = 0; d < D; ++d) { - int b_t_u_d = idx_b_t_u * D + d; - gradients[b_t_u_d] = 0; - } - return; - } - - CAST_DTYPE c = alphas[idx_b_t_u] + cost - denominators[idx_b_t_u]; - for (int d = 0; d < D; ++d) { - int b_t_u_d = idx_b_t_u * D + d; - CAST_DTYPE g = CAST_DTYPE(logits[b_t_u_d]) + c; - - if (fusedLogSmax) { - if (d == blank && t == T - 1 && u == U - 1) { // last blank transition. - gradients[b_t_u_d] = std::exp(g + betas[idx_b_t_u]) - std::exp(g); - } else if (t < T - 1 && d == blank) { - gradients[b_t_u_d] = std::exp(g + betas[idx_b_t_u]); - if (idx_b_tp1_u != -1) { - gradients[b_t_u_d] = gradients[b_t_u_d] - std::exp(g + betas[idx_b_tp1_u]); - } - } else if (u < U - 1 && d == targets[idxr2(bTgt, u)]) { - gradients[b_t_u_d] = std::exp(g + betas[idx_b_t_u]); - if (idx_b_t_up1 != -1) { - gradients[b_t_u_d] = gradients[b_t_u_d] - std::exp(g + betas[idx_b_t_up1]); - } - } else { - gradients[b_t_u_d] = std::exp(g + betas[idx_b_t_u]); - } - } else { // Non fused log softmax case - CAST_DTYPE g = cost + CAST_DTYPE(logits[b_t_u_d]); - if (d == blank && t == T - 1 && u == U - 1) { - gradients[b_t_u_d] = g + alphas[idx_b_t_u]; - } else if (t < T - 1 && d == blank) { - if (idx_b_tp1_u != -1) { - gradients[b_t_u_d] = g + alphas[idx_b_t_u] + betas[idx_b_tp1_u]; - } else { - gradients[b_t_u_d] = g + CAST_DTYPE(-INFINITY); - } - } else if (u < U - 1 && d == targets[idxr2(bTgt, u)]) { - if (idx_b_t_up1 != -1) { - gradients[b_t_u_d] = g + alphas[idx_b_t_u] + betas[idx_b_t_up1]; - } else { - gradients[b_t_u_d] = g + CAST_DTYPE(-INFINITY); - } - } else { - gradients[b_t_u_d] = g + CAST_DTYPE(-INFINITY); - } - gradients[b_t_u_d] = -std::exp(gradients[b_t_u_d]); - } - - if (clamp > 0) { - auto g = CAST_DTYPE(gradients[b_t_u_d]); - gradients[b_t_u_d] = math::min(g, clamp); - gradients[b_t_u_d] = math::max(g, -clamp); - } - } -} - -} // namespace rnnt -} // namespace torchaudio diff --git a/torchaudio/csrc/rnnt/gpu/math.cuh b/torchaudio/csrc/rnnt/gpu/math.cuh deleted file mode 100644 index a2eaabff93..0000000000 --- a/torchaudio/csrc/rnnt/gpu/math.cuh +++ /dev/null @@ -1,41 +0,0 @@ -#pragma once - -#ifdef USE_CUDA - -#include - -#endif // USE_CUDA - -#include - -namespace torchaudio { -namespace rnnt { - -namespace math { - -template -FORCE_INLINE HOST_AND_DEVICE DTYPE max(DTYPE x, DTYPE y) { - if (x > y) return x; - else return y; -} - -template -FORCE_INLINE HOST_AND_DEVICE DTYPE min(DTYPE x, DTYPE y) { - if (x > y) return y; - else return x; -} - -// log_sum_exp -template -FORCE_INLINE HOST_AND_DEVICE DTYPE lse(DTYPE x, DTYPE y); - -template <> -FORCE_INLINE HOST_AND_DEVICE float lse(float x, float y) { - if (y > x) { return y + log1pf(expf(x - y)); } - else { return x + log1pf(expf(y-x)); } -} - -} - -} // namespace rnnt -} // namespace torchaudio From 7f6ac050cc24dc046197d64bf35d7bda784f3809 Mon Sep 17 00:00:00 2001 From: Nicolas Hug Date: Mon, 10 May 2021 09:58:15 -0700 Subject: [PATCH 48/73] Import torchaudio #1479 0c263a935f178490bda78c046e220e84b095447d Summary: This diff syncs torchaudio GH with fbcode Reviewed By: cpuhrsch Differential Revision: D28321222 fbshipit-source-id: 8c5b5ed87c5b7c3aa87495ccb68ccbf9eaaab152 --- .circleci/config.yml | 8 +- .circleci/config.yml.in | 8 +- CMakeLists.txt | 5 + build_tools/setup_helpers/extension.py | 2 + docs/source/index.rst | 8 +- docs/source/{transducer.rst => rnnt_loss.rst} | 6 +- examples/libtorchaudio/CMakeLists.txt | 7 +- examples/libtorchaudio/README.md | 30 +- .../libtorchaudio/augmentation/CMakeLists.txt | 3 + examples/libtorchaudio/augmentation/README.md | 36 ++ .../create_jittable_pipeline.py | 22 +- .../libtorchaudio/{ => augmentation}/main.cpp | 2 +- examples/libtorchaudio/{run.sh => build.sh} | 12 +- .../common_utils/case_utils.py | 8 + .../functional/autograd_impl.py | 3 +- .../functional/functional_cpu_test.py | 14 +- .../functional/functional_cuda_test.py | 16 +- .../functional/functional_impl.py | 36 +- .../torchscript_consistency_cpu_test.py | 14 +- .../torchscript_consistency_cuda_test.py | 16 +- .../torchscript_consistency_impl.py | 47 +- .../rnnt/rnnt_loss_cuda_test.py | 10 + .../transforms/autograd_test_impl.py | 17 + .../torchscript_consistency_cpu_test.py | 14 +- .../torchscript_consistency_cuda_test.py | 16 +- .../torchscript_consistency_impl.py | 40 +- torchaudio/csrc/CMakeLists.txt | 26 +- torchaudio/csrc/lfilter.cpp | 231 +++++----- torchaudio/csrc/rnnt/compute.cpp | 17 +- torchaudio/csrc/rnnt/compute_alphas.cpp | 13 +- torchaudio/csrc/rnnt/compute_betas.cpp | 13 +- torchaudio/csrc/rnnt/cpu/compute.cpp | 133 ++++-- torchaudio/csrc/rnnt/cpu/compute_alphas.cpp | 14 +- torchaudio/csrc/rnnt/cpu/compute_betas.cpp | 18 +- torchaudio/csrc/rnnt/cpu/cpu_kernels.h | 3 +- torchaudio/csrc/rnnt/cpu/cpu_transducer.h | 14 +- torchaudio/csrc/rnnt/cpu/kernel_utils.h | 33 +- torchaudio/csrc/rnnt/cpu/math.h | 25 +- torchaudio/csrc/rnnt/gpu/compute.cu | 161 +++++++ torchaudio/csrc/rnnt/gpu/compute_alphas.cu | 73 +++ torchaudio/csrc/rnnt/gpu/compute_betas.cu | 78 ++++ torchaudio/csrc/rnnt/gpu/gpu_kernel_utils.cuh | 98 ++++ torchaudio/csrc/rnnt/gpu/gpu_kernels.cuh | 422 ++++++++++++++++++ torchaudio/csrc/rnnt/gpu/gpu_transducer.h | 395 ++++++++++++++++ torchaudio/csrc/rnnt/gpu/half.cuh | 38 ++ torchaudio/csrc/rnnt/gpu/kernel_utils.h | 66 +++ torchaudio/csrc/rnnt/gpu/kernels.h | 131 ++++++ torchaudio/csrc/rnnt/gpu/math.cuh | 48 ++ torchaudio/csrc/rnnt/macros.cpp | 5 - torchaudio/csrc/rnnt/macros.h | 26 -- torchaudio/csrc/rnnt/transducer.h | 6 - torchaudio/csrc/rnnt/workspace.cpp | 20 - torchaudio/csrc/rnnt/workspace.h | 17 +- torchaudio/functional/functional.py | 23 +- torchaudio/prototype/rnnt_loss.py | 108 +---- torchaudio/transforms.py | 9 + 56 files changed, 2077 insertions(+), 587 deletions(-) rename docs/source/{transducer.rst => rnnt_loss.rst} (69%) create mode 100644 examples/libtorchaudio/augmentation/CMakeLists.txt create mode 100644 examples/libtorchaudio/augmentation/README.md rename examples/libtorchaudio/{ => augmentation}/create_jittable_pipeline.py (80%) rename examples/libtorchaudio/{ => augmentation}/main.cpp (90%) rename examples/libtorchaudio/{run.sh => build.sh} (56%) create mode 100644 test/torchaudio_unittest/rnnt/rnnt_loss_cuda_test.py create mode 100644 torchaudio/csrc/rnnt/gpu/compute.cu create mode 100644 torchaudio/csrc/rnnt/gpu/compute_alphas.cu create mode 100644 torchaudio/csrc/rnnt/gpu/compute_betas.cu create mode 100644 torchaudio/csrc/rnnt/gpu/gpu_kernel_utils.cuh create mode 100644 torchaudio/csrc/rnnt/gpu/gpu_kernels.cuh create mode 100644 torchaudio/csrc/rnnt/gpu/gpu_transducer.h create mode 100644 torchaudio/csrc/rnnt/gpu/half.cuh create mode 100644 torchaudio/csrc/rnnt/gpu/kernel_utils.h create mode 100644 torchaudio/csrc/rnnt/gpu/kernels.h create mode 100644 torchaudio/csrc/rnnt/gpu/math.cuh delete mode 100644 torchaudio/csrc/rnnt/workspace.cpp diff --git a/.circleci/config.yml b/.circleci/config.yml index 7bba9977fd..64a6ae9f9f 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -42,7 +42,7 @@ commands: description: "installs tools required to build torchaudio" steps: - run: - name: Install pkg-config + name: Install build tools command: HOMEBREW_NO_AUTO_UPDATE=1 brew install pkg-config wget # Disable brew auto update which is very slow load_conda_channel_flags: @@ -162,7 +162,7 @@ jobs: binary_macos_wheel: <<: *binary_common macos: - xcode: "9.4.1" + xcode: "12.0" steps: - checkout - install_build_tools_macos @@ -188,7 +188,7 @@ jobs: binary_macos_conda: <<: *binary_common macos: - xcode: "9.4.1" + xcode: "12.0" steps: - checkout - install_build_tools_macos @@ -509,7 +509,7 @@ jobs: unittest_macos_cpu: <<: *binary_common macos: - xcode: "9.4.1" + xcode: "12.0" resource_class: large steps: - checkout diff --git a/.circleci/config.yml.in b/.circleci/config.yml.in index cc4c391ea1..16b47bde79 100644 --- a/.circleci/config.yml.in +++ b/.circleci/config.yml.in @@ -42,7 +42,7 @@ commands: description: "installs tools required to build torchaudio" steps: - run: - name: Install pkg-config + name: Install build tools command: HOMEBREW_NO_AUTO_UPDATE=1 brew install pkg-config wget # Disable brew auto update which is very slow load_conda_channel_flags: @@ -162,7 +162,7 @@ jobs: binary_macos_wheel: <<: *binary_common macos: - xcode: "9.4.1" + xcode: "12.0" steps: - checkout - install_build_tools_macos @@ -188,7 +188,7 @@ jobs: binary_macos_conda: <<: *binary_common macos: - xcode: "9.4.1" + xcode: "12.0" steps: - checkout - install_build_tools_macos @@ -509,7 +509,7 @@ jobs: unittest_macos_cpu: <<: *binary_common macos: - xcode: "9.4.1" + xcode: "12.0" resource_class: large steps: - checkout diff --git a/CMakeLists.txt b/CMakeLists.txt index 96360532f2..35b148c058 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -59,6 +59,11 @@ option(BUILD_KALDI "Build kaldi statically" ON) option(BUILD_TRANSDUCER "Enable transducer" OFF) option(BUILD_LIBTORCHAUDIO "Build C++ Library" ON) option(BUILD_TORCHAUDIO_PYTHON_EXTENSION "Build Python extension" OFF) +option(USE_CUDA "Enable CUDA support" OFF) + +if(USE_CUDA) + enable_language(CUDA) +endif() find_package(Torch REQUIRED) diff --git a/build_tools/setup_helpers/extension.py b/build_tools/setup_helpers/extension.py index 430ff168c3..91002fa0e9 100644 --- a/build_tools/setup_helpers/extension.py +++ b/build_tools/setup_helpers/extension.py @@ -38,6 +38,7 @@ def _get_build(var, default=False): _BUILD_KALDI = False if platform.system() == 'Windows' else _get_build("BUILD_KALDI", True) _BUILD_TRANSDUCER = _get_build("BUILD_TRANSDUCER") _USE_ROCM = _get_build("USE_ROCM") +_USE_CUDA = torch.cuda.is_available() def get_ext_modules(): @@ -76,6 +77,7 @@ def build_extension(self, ext): "-DBUILD_TORCHAUDIO_PYTHON_EXTENSION:BOOL=ON", "-DBUILD_LIBTORCHAUDIO:BOOL=OFF", f"-DUSE_ROCM:BOOL={'ON' if _USE_ROCM else 'OFF'}", + f"-DUSE_CUDA:BOOL={'ON' if _USE_CUDA else 'OFF'}", ] build_args = [ '--target', 'install' diff --git a/docs/source/index.rst b/docs/source/index.rst index 49ffb9af22..5aacb87f54 100644 --- a/docs/source/index.rst +++ b/docs/source/index.rst @@ -21,7 +21,7 @@ Features described in this documentation are classified by release status: *Prototype:* These features are typically not available as part of binary distributions like PyPI or Conda, except sometimes behind run-time flags, and are at an early stage for feedback and testing. - + The :mod:`torchaudio` package consists of I/O, popular datasets and common audio transformations. @@ -39,9 +39,9 @@ The :mod:`torchaudio` package consists of I/O, popular datasets and common audio compliance.kaldi kaldi_io utils - transducer - - + rnnt_loss + + .. toctree:: :maxdepth: 1 :caption: PyTorch Libraries diff --git a/docs/source/transducer.rst b/docs/source/rnnt_loss.rst similarity index 69% rename from docs/source/transducer.rst rename to docs/source/rnnt_loss.rst index 505ab0187c..0c3b075d65 100644 --- a/docs/source/transducer.rst +++ b/docs/source/rnnt_loss.rst @@ -1,14 +1,14 @@ .. role:: hidden :class: hidden-section -torchaudio.prototype.transducer +torchaudio.prototype.rnnt_loss =============================== -.. currentmodule:: torchaudio.prototype.transducer +.. currentmodule:: torchaudio.prototype.rnnt_loss .. note:: - The RNN transducer loss is a prototype feature, see `here `_ to learn more about the nomenclature. It is only available within the nightlies, and also needs to be imported explicitly using: :code:`from torchaudio.prototype.transducer import rnnt_loss, RNNTLoss`. + The RNN transducer loss is a prototype feature, see `here `_ to learn more about the nomenclature. It is only available within the nightlies, and also needs to be imported explicitly using: :code:`from torchaudio.prototype.rnnt_loss import rnnt_loss, RNNTLoss`. rnnt_loss --------- diff --git a/examples/libtorchaudio/CMakeLists.txt b/examples/libtorchaudio/CMakeLists.txt index 264949bc12..6a359bd47e 100644 --- a/examples/libtorchaudio/CMakeLists.txt +++ b/examples/libtorchaudio/CMakeLists.txt @@ -6,7 +6,7 @@ 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_TRANSDUCER OFF CACHE BOOL "Build transducer into libtorchaudio") SET(BUILD_TORCHAUDIO_PYTHON_EXTENSION OFF CACHE BOOL "Build Python binding") find_package(Torch REQUIRED) @@ -14,7 +14,4 @@ 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) +add_subdirectory(augmentation) diff --git a/examples/libtorchaudio/README.md b/examples/libtorchaudio/README.md index 10f1228894..be6611ea85 100644 --- a/examples/libtorchaudio/README.md +++ b/examples/libtorchaudio/README.md @@ -1,11 +1,27 @@ -# Example usage: libtorchaudio +# Libtorchaudio Examples -This example demonstrates how you can use torchaudio's I/O features in C++ application, in addition to PyTorch's operations. +* [Augmentation](./augmentation) -To try this example, simply run `./run.sh`. This script will +## Build -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 example applications in this directory depend on `libtorch` and `libtorchaudio`. +If you have a working `PyTorch`, you already have `libtorch`. +Please refer to [this tutorial](https://pytorch.org/tutorials/advanced/torch_script_custom_classes.html) for the use of `libtorch` and TorchScript. -The detail of the preprocessing pipeline can be found in [`create_jittable_pipeline.py`](./create_jittable_pipeline.py). +`libtorchaudio` is the library of torchaudio's C++ components without Python component. +It is currently not distributed, and it will be built alongside with the applications. + +The following commands will build `libtorchaudio` and applications. + +```bash +mkdir build +cd build +cmake -GNinja \ + -DCMAKE_PREFIX_PATH="$(python -c 'import torch;print(torch.utils.cmake_prefix_path)')" \ + -DBUILD_SOX=ON \ + -DBUILD_KALDI=OFF \ + .. +cmake --build . +``` + +For the usages of each application, refer to the corresponding application directory. diff --git a/examples/libtorchaudio/augmentation/CMakeLists.txt b/examples/libtorchaudio/augmentation/CMakeLists.txt new file mode 100644 index 0000000000..e9bfece93a --- /dev/null +++ b/examples/libtorchaudio/augmentation/CMakeLists.txt @@ -0,0 +1,3 @@ +add_executable(augment main.cpp) +target_link_libraries(augment "${TORCH_LIBRARIES}" "${TORCHAUDIO_LIBRARY}") +set_property(TARGET augment PROPERTY CXX_STANDARD 14) diff --git a/examples/libtorchaudio/augmentation/README.md b/examples/libtorchaudio/augmentation/README.md new file mode 100644 index 0000000000..b78248af6b --- /dev/null +++ b/examples/libtorchaudio/augmentation/README.md @@ -0,0 +1,36 @@ +# Augmentation + +This example demonstrates how you can use torchaudio's I/O features and augmentations in C++ application. + +**NOTE** +This example uses `"sox_io"` backend, thus does not work on Windows. + +## Steps +### 1. Create augmentation pipeline TorchScript file. + +First, we implement our data process pipeline as a regular Python, and save it as a TorchScript object. +We will load and execute it in our C++ application. The C++ code is found in [`main.cpp`](./main.cpp). + +```python +python create_jittable_pipeline.py \ + --rir-path "../data/rir.wav" \ + --output-path "./pipeline.zip" +``` + +### 2. Build the application + +Please refer to [the top level README.md](../README.md) + +### 3. Run the application + +Now we run the C++ application `augment`, with the TorchScript object we created in Step.1 and an input audio file. + +In [the top level directory](../) + +```bash +input_audio_file="./data/input.wav" +./build/augmentation/augment ./augmentation/pipeline.zip "${input_audio_file}" "output.wav" +``` + +When you give a clean speech file, the output audio sounds like it's a phone conversation. + diff --git a/examples/libtorchaudio/create_jittable_pipeline.py b/examples/libtorchaudio/augmentation/create_jittable_pipeline.py similarity index 80% rename from examples/libtorchaudio/create_jittable_pipeline.py rename to examples/libtorchaudio/augmentation/create_jittable_pipeline.py index 14a7eefd50..ac33a837da 100755 --- a/examples/libtorchaudio/create_jittable_pipeline.py +++ b/examples/libtorchaudio/augmentation/create_jittable_pipeline.py @@ -14,9 +14,9 @@ class Pipeline(torch.nn.Module): This example load waveform from a file then apply effects and save it to a file. """ - def __init__(self): + def __init__(self, rir_path: str): super().__init__() - rir, sample_rate = _load_rir() + rir, sample_rate = torchaudio.load(rir_path) self.register_buffer('rir', rir) self.rir_sample_rate: int = sample_rate @@ -44,8 +44,8 @@ def forward(self, input_path: str, output_path: str): torchaudio.save(output_path, waveform, sample_rate) -def _create_jit_pipeline(output_path): - module = torch.jit.script(Pipeline()) +def _create_jit_pipeline(rir_path, output_path): + module = torch.jit.script(Pipeline(rir_path)) print("*" * 40) print("* Pipeline code") print("*" * 40) @@ -59,16 +59,16 @@ 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( + "--rir-path", + default=_get_path("..", "data", "rir.wav"), + help="Audio dara for room impulse response." + ) parser.add_argument( "--output-path", - default=_get_path("data", "pipeline.zip"), + default=_get_path("pipeline.zip"), help="Output JIT file." ) return parser.parse_args() @@ -76,7 +76,7 @@ def _parse_args(): def _main(): args = _parse_args() - _create_jit_pipeline(args.output_path) + _create_jit_pipeline(args.rir_path, args.output_path) if __name__ == '__main__': diff --git a/examples/libtorchaudio/main.cpp b/examples/libtorchaudio/augmentation/main.cpp similarity index 90% rename from examples/libtorchaudio/main.cpp rename to examples/libtorchaudio/augmentation/main.cpp index 9f9a7b0d00..fe45d28aa9 100644 --- a/examples/libtorchaudio/main.cpp +++ b/examples/libtorchaudio/augmentation/main.cpp @@ -7,7 +7,7 @@ int main(int argc, char* argv[]) { } torch::jit::script::Module module; - std::cout << "Loading module from: " << argv[0] << std::endl; + std::cout << "Loading module from: " << argv[1] << std::endl; try { module = torch::jit::load(argv[1]); } catch (const c10::Error &error) { diff --git a/examples/libtorchaudio/run.sh b/examples/libtorchaudio/build.sh similarity index 56% rename from examples/libtorchaudio/run.sh rename to examples/libtorchaudio/build.sh index a55614e909..11ca65f751 100755 --- a/examples/libtorchaudio/run.sh +++ b/examples/libtorchaudio/build.sh @@ -3,22 +3,14 @@ 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}" +cmake --build . diff --git a/test/torchaudio_unittest/common_utils/case_utils.py b/test/torchaudio_unittest/common_utils/case_utils.py index 7357cec4c4..773f1915b9 100644 --- a/test/torchaudio_unittest/common_utils/case_utils.py +++ b/test/torchaudio_unittest/common_utils/case_utils.py @@ -81,6 +81,14 @@ def setUp(self): super().setUp() set_audio_backend(self.backend) + @property + def complex_dtype(self): + if self.dtype in ['float32', 'float', torch.float, torch.float32]: + return torch.cfloat + if self.dtype in ['float64', 'double', torch.double, torch.float64]: + return torch.cdouble + raise ValueError(f'No corresponding complex dtype for {self.dtype}') + class TorchaudioTestCase(TestBaseMixin, PytorchTestCase): pass diff --git a/test/torchaudio_unittest/functional/autograd_impl.py b/test/torchaudio_unittest/functional/autograd_impl.py index e273369ea6..049ae25c90 100644 --- a/test/torchaudio_unittest/functional/autograd_impl.py +++ b/test/torchaudio_unittest/functional/autograd_impl.py @@ -3,7 +3,7 @@ from parameterized import parameterized from torch import Tensor import torchaudio.functional as F -from torch.autograd import gradcheck +from torch.autograd import gradcheck, gradgradcheck from torchaudio_unittest.common_utils import ( TestBaseMixin, get_whitenoise, @@ -26,6 +26,7 @@ def assert_grad( i.requires_grad = True inputs_.append(i) assert gradcheck(transform, inputs_) + assert gradgradcheck(transform, inputs_) def test_lfilter_x(self): torch.random.manual_seed(2434) diff --git a/test/torchaudio_unittest/functional/functional_cpu_test.py b/test/torchaudio_unittest/functional/functional_cpu_test.py index 73cc8662fa..520ff86b20 100644 --- a/test/torchaudio_unittest/functional/functional_cpu_test.py +++ b/test/torchaudio_unittest/functional/functional_cpu_test.py @@ -4,7 +4,7 @@ from parameterized import parameterized from torchaudio_unittest.common_utils import PytorchTestCase, TorchaudioTestCase, skipIfNoSox -from .functional_impl import Functional, FunctionalComplex, FunctionalCPUOnly +from .functional_impl import Functional, FunctionalCPUOnly class TestFunctionalFloat32(Functional, FunctionalCPUOnly, PytorchTestCase): @@ -21,18 +21,6 @@ class TestFunctionalFloat64(Functional, PytorchTestCase): device = torch.device('cpu') -class TestFunctionalComplex64(FunctionalComplex, PytorchTestCase): - complex_dtype = torch.complex64 - real_dtype = torch.float32 - device = torch.device('cpu') - - -class TestFunctionalComplex128(FunctionalComplex, PytorchTestCase): - complex_dtype = torch.complex128 - real_dtype = torch.float64 - device = torch.device('cpu') - - @skipIfNoSox class TestApplyCodec(TorchaudioTestCase): backend = "sox_io" diff --git a/test/torchaudio_unittest/functional/functional_cuda_test.py b/test/torchaudio_unittest/functional/functional_cuda_test.py index 054e2c3e4f..fd35547270 100644 --- a/test/torchaudio_unittest/functional/functional_cuda_test.py +++ b/test/torchaudio_unittest/functional/functional_cuda_test.py @@ -2,7 +2,7 @@ import unittest from torchaudio_unittest.common_utils import PytorchTestCase, skipIfNoCuda -from .functional_impl import Functional, FunctionalComplex +from .functional_impl import Functional @skipIfNoCuda @@ -19,17 +19,3 @@ def test_lfilter_9th_order_filter_stability(self): class TestLFilterFloat64(Functional, PytorchTestCase): dtype = torch.float64 device = torch.device('cuda') - - -@skipIfNoCuda -class TestFunctionalComplex64(FunctionalComplex, PytorchTestCase): - complex_dtype = torch.complex64 - real_dtype = torch.float32 - device = torch.device('cuda') - - -@skipIfNoCuda -class TestFunctionalComplex128(FunctionalComplex, PytorchTestCase): - complex_dtype = torch.complex64 - real_dtype = torch.float32 - device = torch.device('cuda') diff --git a/test/torchaudio_unittest/functional/functional_impl.py b/test/torchaudio_unittest/functional/functional_impl.py index f4cc94f806..424ead2ca9 100644 --- a/test/torchaudio_unittest/functional/functional_impl.py +++ b/test/torchaudio_unittest/functional/functional_impl.py @@ -227,11 +227,37 @@ def test_mask_along_axis_iid(self, mask_param, mask_value, axis): assert mask_specgrams.size() == specgrams.size() assert (num_masked_columns < mask_param).sum() == num_masked_columns.numel() + @parameterized.expand( + list(itertools.product([(2, 1025, 400), (1, 201, 100)], [100], [0., 30.], [1, 2])) + ) + def test_mask_along_axis_preserve(self, shape, mask_param, mask_value, axis): + """mask_along_axis should not alter original input Tensor + + Test is run 5 times to bound the probability of no masking occurring to 1e-10 + See https://github.com/pytorch/audio/issues/1478 + """ + torch.random.manual_seed(42) + for _ in range(5): + specgram = torch.randn(*shape, dtype=self.dtype, device=self.device) + specgram_copy = specgram.clone() + F.mask_along_axis(specgram, mask_param, mask_value, axis) + + self.assertEqual(specgram, specgram_copy) + + @parameterized.expand(list(itertools.product([100], [0., 30.], [2, 3]))) + def test_mask_along_axis_iid_preserve(self, mask_param, mask_value, axis): + """mask_along_axis_iid should not alter original input Tensor + + Test is run 5 times to bound the probability of no masking occurring to 1e-10 + See https://github.com/pytorch/audio/issues/1478 + """ + torch.random.manual_seed(42) + for _ in range(5): + specgrams = torch.randn(4, 2, 1025, 400, dtype=self.dtype, device=self.device) + specgrams_copy = specgrams.clone() + F.mask_along_axis_iid(specgrams, mask_param, mask_value, axis) -class FunctionalComplex(TestBaseMixin): - complex_dtype = None - real_dtype = None - device = None + self.assertEqual(specgrams, specgrams_copy) @nested_params( [0.5, 1.01, 1.3], @@ -254,7 +280,7 @@ def test_phase_vocoder_shape(self, rate, test_pseudo_complex): 0, np.pi * hop_length, num_freq, - dtype=self.real_dtype, device=self.device)[..., None] + dtype=self.dtype, device=self.device)[..., None] spec_stretch = F.phase_vocoder(spec, rate=rate, phase_advance=phase_advance) diff --git a/test/torchaudio_unittest/functional/torchscript_consistency_cpu_test.py b/test/torchaudio_unittest/functional/torchscript_consistency_cpu_test.py index d9d34eff76..06871f9bde 100644 --- a/test/torchaudio_unittest/functional/torchscript_consistency_cpu_test.py +++ b/test/torchaudio_unittest/functional/torchscript_consistency_cpu_test.py @@ -1,7 +1,7 @@ import torch from torchaudio_unittest.common_utils import PytorchTestCase -from .torchscript_consistency_impl import Functional, FunctionalComplex +from .torchscript_consistency_impl import Functional class TestFunctionalFloat32(Functional, PytorchTestCase): @@ -12,15 +12,3 @@ class TestFunctionalFloat32(Functional, PytorchTestCase): class TestFunctionalFloat64(Functional, PytorchTestCase): dtype = torch.float64 device = torch.device('cpu') - - -class TestFunctionalComplex64(FunctionalComplex, PytorchTestCase): - complex_dtype = torch.complex64 - real_dtype = torch.float32 - device = torch.device('cpu') - - -class TestFunctionalComplex128(FunctionalComplex, PytorchTestCase): - complex_dtype = torch.complex128 - real_dtype = torch.float64 - device = torch.device('cpu') diff --git a/test/torchaudio_unittest/functional/torchscript_consistency_cuda_test.py b/test/torchaudio_unittest/functional/torchscript_consistency_cuda_test.py index 026e09abfa..53ccbad3c9 100644 --- a/test/torchaudio_unittest/functional/torchscript_consistency_cuda_test.py +++ b/test/torchaudio_unittest/functional/torchscript_consistency_cuda_test.py @@ -1,7 +1,7 @@ import torch from torchaudio_unittest.common_utils import skipIfNoCuda, PytorchTestCase -from .torchscript_consistency_impl import Functional, FunctionalComplex +from .torchscript_consistency_impl import Functional @skipIfNoCuda @@ -14,17 +14,3 @@ class TestFunctionalFloat32(Functional, PytorchTestCase): class TestFunctionalFloat64(Functional, PytorchTestCase): dtype = torch.float64 device = torch.device('cuda') - - -@skipIfNoCuda -class TestFunctionalComplex64(FunctionalComplex, PytorchTestCase): - complex_dtype = torch.complex64 - real_dtype = torch.float32 - device = torch.device('cuda') - - -@skipIfNoCuda -class TestFunctionalComplex128(FunctionalComplex, PytorchTestCase): - complex_dtype = torch.complex128 - real_dtype = torch.float64 - device = torch.device('cuda') diff --git a/test/torchaudio_unittest/functional/torchscript_consistency_impl.py b/test/torchaudio_unittest/functional/torchscript_consistency_impl.py index 9c34846b9e..a39973f867 100644 --- a/test/torchaudio_unittest/functional/torchscript_consistency_impl.py +++ b/test/torchaudio_unittest/functional/torchscript_consistency_impl.py @@ -13,7 +13,7 @@ class Functional(TempDirMixin, TestBaseMixin): - """Implements test for `functinoal` modul that are performed for different devices""" + """Implements test for `functional` module that are performed for different devices""" def _assert_consistency(self, func, tensor, shape_only=False): tensor = tensor.to(device=self.device, dtype=self.dtype) @@ -21,13 +21,36 @@ def _assert_consistency(self, func, tensor, shape_only=False): torch.jit.script(func).save(path) ts_func = torch.jit.load(path) + torch.random.manual_seed(40) output = func(tensor) + + torch.random.manual_seed(40) ts_output = ts_func(tensor) + if shape_only: ts_output = ts_output.shape output = output.shape self.assertEqual(ts_output, output) + def _assert_consistency_complex(self, func, tensor, test_pseudo_complex=False): + assert tensor.is_complex() + tensor = tensor.to(device=self.device, dtype=self.complex_dtype) + + path = self.get_temp_path('func.zip') + torch.jit.script(func).save(path) + ts_func = torch.jit.load(path) + + if test_pseudo_complex: + tensor = torch.view_as_real(tensor) + + torch.random.manual_seed(40) + output = func(tensor) + + torch.random.manual_seed(40) + ts_output = ts_func(tensor) + + self.assertEqual(ts_output, output) + def test_spectrogram(self): def func(tensor): n_fft = 400 @@ -568,26 +591,6 @@ def func(tensor): tensor = common_utils.get_whitenoise(sample_rate=44100) self._assert_consistency(func, tensor) - -class FunctionalComplex(TempDirMixin, TestBaseMixin): - complex_dtype = None - real_dtype = None - device = None - - def _assert_consistency(self, func, tensor, test_pseudo_complex=False): - assert tensor.is_complex() - tensor = tensor.to(device=self.device, dtype=self.complex_dtype) - - path = self.get_temp_path('func.zip') - torch.jit.script(func).save(path) - ts_func = torch.jit.load(path) - - if test_pseudo_complex: - tensor = torch.view_as_real(tensor) - output = func(tensor) - ts_output = ts_func(tensor) - self.assertEqual(ts_output, output) - @parameterized.expand([(True, ), (False, )]) def test_phase_vocoder(self, test_paseudo_complex): def func(tensor): @@ -606,4 +609,4 @@ def func(tensor): return F.phase_vocoder(tensor, rate, phase_advance) tensor = torch.view_as_complex(torch.randn(2, 1025, 400, 2)) - self._assert_consistency(func, tensor, test_paseudo_complex) + self._assert_consistency_complex(func, tensor, test_paseudo_complex) diff --git a/test/torchaudio_unittest/rnnt/rnnt_loss_cuda_test.py b/test/torchaudio_unittest/rnnt/rnnt_loss_cuda_test.py new file mode 100644 index 0000000000..c64fd687fe --- /dev/null +++ b/test/torchaudio_unittest/rnnt/rnnt_loss_cuda_test.py @@ -0,0 +1,10 @@ +import torch +from .rnnt_loss_impl import RNNTLossTest +from torchaudio_unittest import common_utils +from .utils import skipIfNoTransducer + + +@skipIfNoTransducer +@common_utils.skipIfNoCuda +class TestRNNTLoss(RNNTLossTest, common_utils.PytorchTestCase): + device = torch.device('cuda') diff --git a/test/torchaudio_unittest/transforms/autograd_test_impl.py b/test/torchaudio_unittest/transforms/autograd_test_impl.py index b8fe6c1863..717a7bc87b 100644 --- a/test/torchaudio_unittest/transforms/autograd_test_impl.py +++ b/test/torchaudio_unittest/transforms/autograd_test_impl.py @@ -154,6 +154,23 @@ def test_vol(self, gain, gain_type): waveform = get_whitenoise(sample_rate=sample_rate, duration=0.05, n_channels=2) self.assert_grad(transform, [waveform]) + @parameterized.expand([ + ({'cmn_window': 100, 'min_cmn_window': 50, 'center': False, 'norm_vars': False}, ), + ({'cmn_window': 100, 'min_cmn_window': 50, 'center': True, 'norm_vars': False}, ), + ({'cmn_window': 100, 'min_cmn_window': 50, 'center': False, 'norm_vars': True}, ), + ({'cmn_window': 100, 'min_cmn_window': 50, 'center': True, 'norm_vars': True}, ), + ]) + def test_sliding_window_cmn(self, kwargs): + n_fft = 10 + power = 1 + spec = get_spectrogram( + get_whitenoise(sample_rate=200, duration=0.05, n_channels=2), + n_fft=n_fft, power=power) + spec_reshaped = spec.transpose(-1, -2) + + transform = T.SlidingWindowCmn(**kwargs) + self.assert_grad(transform, [spec_reshaped]) + @unittest.expectedFailure def test_timestretch_zeros_fail(self): """Test that ``T.TimeStretch`` fails gradcheck at 0 diff --git a/test/torchaudio_unittest/transforms/torchscript_consistency_cpu_test.py b/test/torchaudio_unittest/transforms/torchscript_consistency_cpu_test.py index 4de32a57bb..9092f3a64b 100644 --- a/test/torchaudio_unittest/transforms/torchscript_consistency_cpu_test.py +++ b/test/torchaudio_unittest/transforms/torchscript_consistency_cpu_test.py @@ -1,7 +1,7 @@ import torch from torchaudio_unittest.common_utils import PytorchTestCase -from .torchscript_consistency_impl import Transforms, TransformsComplex +from .torchscript_consistency_impl import Transforms class TestTransformsFloat32(Transforms, PytorchTestCase): @@ -12,15 +12,3 @@ class TestTransformsFloat32(Transforms, PytorchTestCase): class TestTransformsFloat64(Transforms, PytorchTestCase): dtype = torch.float64 device = torch.device('cpu') - - -class TestTransformsComplex64(TransformsComplex, PytorchTestCase): - complex_dtype = torch.complex64 - real_dtype = torch.float32 - device = torch.device('cpu') - - -class TestTransformsComplex128(TransformsComplex, PytorchTestCase): - complex_dtype = torch.complex128 - real_dtype = torch.float64 - device = torch.device('cpu') diff --git a/test/torchaudio_unittest/transforms/torchscript_consistency_cuda_test.py b/test/torchaudio_unittest/transforms/torchscript_consistency_cuda_test.py index 2435b82589..7425647bab 100644 --- a/test/torchaudio_unittest/transforms/torchscript_consistency_cuda_test.py +++ b/test/torchaudio_unittest/transforms/torchscript_consistency_cuda_test.py @@ -1,7 +1,7 @@ import torch from torchaudio_unittest.common_utils import skipIfNoCuda, PytorchTestCase -from .torchscript_consistency_impl import Transforms, TransformsComplex +from .torchscript_consistency_impl import Transforms @skipIfNoCuda @@ -14,17 +14,3 @@ class TestTransformsFloat32(Transforms, PytorchTestCase): class TestTransformsFloat64(Transforms, PytorchTestCase): dtype = torch.float64 device = torch.device('cuda') - - -@skipIfNoCuda -class TestTransformsComplex64(TransformsComplex, PytorchTestCase): - complex_dtype = torch.complex64 - real_dtype = torch.float32 - device = torch.device('cuda') - - -@skipIfNoCuda -class TestTransformsComplex128(TransformsComplex, PytorchTestCase): - complex_dtype = torch.complex128 - real_dtype = torch.float64 - device = torch.device('cuda') diff --git a/test/torchaudio_unittest/transforms/torchscript_consistency_impl.py b/test/torchaudio_unittest/transforms/torchscript_consistency_impl.py index 64ecbe53f7..506ca9af6c 100644 --- a/test/torchaudio_unittest/transforms/torchscript_consistency_impl.py +++ b/test/torchaudio_unittest/transforms/torchscript_consistency_impl.py @@ -26,6 +26,22 @@ def _assert_consistency(self, transform, tensor): ts_output = ts_transform(tensor) self.assertEqual(ts_output, output) + def _assert_consistency_complex(self, transform, tensor, test_pseudo_complex=False): + assert tensor.is_complex() + tensor = tensor.to(device=self.device, dtype=self.complex_dtype) + transform = transform.to(device=self.device, dtype=self.dtype) + + path = self.get_temp_path('transform.zip') + torch.jit.script(transform).save(path) + ts_transform = torch.jit.load(path) + + if test_pseudo_complex: + tensor = torch.view_as_real(tensor) + + output = transform(tensor) + ts_output = ts_transform(tensor) + self.assertEqual(ts_output, output) + def test_Spectrogram(self): tensor = torch.rand((1, 1000)) self._assert_consistency(T.Spectrogram(), tensor) @@ -104,35 +120,13 @@ def test_SpectralCentroid(self): waveform = common_utils.get_whitenoise(sample_rate=sample_rate) self._assert_consistency(T.SpectralCentroid(sample_rate=sample_rate), waveform) - -class TransformsComplex(TempDirMixin, TestBaseMixin): - complex_dtype = None - real_dtype = None - device = None - - def _assert_consistency(self, transform, tensor, test_pseudo_complex=False): - assert tensor.is_complex() - tensor = tensor.to(device=self.device, dtype=self.complex_dtype) - transform = transform.to(device=self.device, dtype=self.real_dtype) - - path = self.get_temp_path('transform.zip') - torch.jit.script(transform).save(path) - ts_transform = torch.jit.load(path) - - if test_pseudo_complex: - tensor = torch.view_as_real(tensor) - - output = transform(tensor) - ts_output = ts_transform(tensor) - self.assertEqual(ts_output, output) - @parameterized.expand([(True, ), (False, )]) def test_TimeStretch(self, test_pseudo_complex): n_freq = 400 hop_length = 512 fixed_rate = 1.3 tensor = torch.view_as_complex(torch.rand((10, 2, n_freq, 10, 2))) - self._assert_consistency( + self._assert_consistency_complex( T.TimeStretch(n_freq=n_freq, hop_length=hop_length, fixed_rate=fixed_rate), tensor, test_pseudo_complex diff --git a/torchaudio/csrc/CMakeLists.txt b/torchaudio/csrc/CMakeLists.txt index fc033699b2..ebf577eb64 100644 --- a/torchaudio/csrc/CMakeLists.txt +++ b/torchaudio/csrc/CMakeLists.txt @@ -11,7 +11,27 @@ set( ) if(BUILD_TRANSDUCER) - list(APPEND LIBTORCHAUDIO_SOURCES transducer.cpp) + set( + TRANSDUCER_SOURCES + rnnt/cpu/compute_alphas.cpp + rnnt/cpu/compute_betas.cpp + rnnt/cpu/compute.cpp + rnnt/compute_alphas.cpp + rnnt/compute_betas.cpp + rnnt/compute.cpp + ) + + if (USE_CUDA) + set( + CUDA_TRANSDUCER_SOURCES + rnnt/gpu/compute_alphas.cu + rnnt/gpu/compute_betas.cu + rnnt/gpu/compute.cu + ) + list(APPEND TRANSDUCER_SOURCES ${CUDA_TRANSDUCER_SOURCES}) + endif() + + list(APPEND LIBTORCHAUDIO_SOURCES ${TRANSDUCER_SOURCES}) endif() if(BUILD_KALDI) @@ -96,6 +116,10 @@ if (BUILD_TORCHAUDIO_PYTHON_EXTENSION) target_compile_definitions(_torchaudio PRIVATE INCLUDE_KALDI) endif() + if (USE_CUDA) + target_compile_definitions(_torchaudio PRIVATE USE_CUDA) + endif() + target_include_directories( _torchaudio PRIVATE diff --git a/torchaudio/csrc/lfilter.cpp b/torchaudio/csrc/lfilter.cpp index 56540c33f6..dcc5dbe442 100644 --- a/torchaudio/csrc/lfilter.cpp +++ b/torchaudio/csrc/lfilter.cpp @@ -80,170 +80,159 @@ void lfilter_core_generic_loop( } } -std::tuple lfilter_core( - const torch::Tensor& waveform, - const torch::Tensor& a_coeffs, - const torch::Tensor& b_coeffs) { - TORCH_CHECK(waveform.device() == a_coeffs.device()); - TORCH_CHECK(b_coeffs.device() == a_coeffs.device()); - TORCH_CHECK(a_coeffs.size(0) == b_coeffs.size(0)); +class DifferentiableIIR : public torch::autograd::Function { + public: + static torch::Tensor forward( + torch::autograd::AutogradContext* ctx, + const torch::Tensor& waveform, + const torch::Tensor& a_coeffs_normalized) { + auto device = waveform.device(); + auto dtype = waveform.dtype(); + int64_t n_channel = waveform.size(0); + int64_t n_sample = waveform.size(1); + int64_t n_order = a_coeffs_normalized.size(0); + int64_t n_sample_padded = n_sample + n_order - 1; - TORCH_INTERNAL_ASSERT(waveform.sizes().size() == 2); + auto a_coeff_flipped = a_coeffs_normalized.flip(0).contiguous(); - auto device = waveform.device(); - int64_t n_order = a_coeffs.size(0); + auto options = torch::TensorOptions().dtype(dtype).device(device); + auto padded_output_waveform = + torch::zeros({n_channel, n_sample_padded}, options); + + if (device.is_cpu()) { + cpu_lfilter_core_loop(waveform, a_coeff_flipped, padded_output_waveform); + } else { + lfilter_core_generic_loop( + waveform, a_coeff_flipped, padded_output_waveform); + } - TORCH_INTERNAL_ASSERT(n_order > 0); + auto output = padded_output_waveform.index( + {torch::indexing::Slice(), + torch::indexing::Slice(n_order - 1, torch::indexing::None)}); - namespace F = torch::nn::functional; + ctx->save_for_backward({waveform, a_coeffs_normalized, output}); + return output; + } - auto padded_waveform = F::pad(waveform, F::PadFuncOptions({n_order - 1, 0})); - auto padded_output_waveform = torch::zeros_like(padded_waveform); + static torch::autograd::tensor_list backward( + torch::autograd::AutogradContext* ctx, + torch::autograd::tensor_list grad_outputs) { + auto saved = ctx->get_saved_variables(); + auto x = saved[0]; + auto a_coeffs_normalized = saved[1]; + auto y = saved[2]; - auto a_coeff_flipped = a_coeffs.flip(0).contiguous(); - auto b_coeff_flipped = b_coeffs.flip(0).contiguous(); + int64_t n_channel = x.size(0); + int64_t n_order = a_coeffs_normalized.size(0); - auto input_signal_windows = - F::conv1d( - padded_waveform.unsqueeze(1), b_coeff_flipped.view({1, 1, n_order})) - .squeeze(1); + auto dx = torch::Tensor(); + auto da = torch::Tensor(); + auto dy = grad_outputs[0]; - input_signal_windows.div_(a_coeffs[0]); - a_coeff_flipped.div_(a_coeffs[0]); + namespace F = torch::nn::functional; - if (device.is_cpu()) { - cpu_lfilter_core_loop( - input_signal_windows, a_coeff_flipped, padded_output_waveform); - } else { - lfilter_core_generic_loop( - input_signal_windows, a_coeff_flipped, padded_output_waveform); - } + if (a_coeffs_normalized.requires_grad()) { + auto dyda = F::pad( + DifferentiableIIR::apply(-y, a_coeffs_normalized), + F::PadFuncOptions({n_order - 1, 0})); - auto output = padded_output_waveform.index( - {torch::indexing::Slice(), - torch::indexing::Slice(n_order - 1, torch::indexing::None)}); + da = F::conv1d( + dyda.unsqueeze(0), + dy.unsqueeze(1), + F::Conv1dFuncOptions().groups(n_channel)) + .sum(1) + .squeeze(0) + .flip(0); + } - return {output, input_signal_windows}; -} + if (x.requires_grad()) { + dx = DifferentiableIIR::apply(dy.flip(1), a_coeffs_normalized).flip(1); + } -torch::Tensor lfilter_simple( - const torch::Tensor& waveform, - const torch::Tensor& a_coeffs, - const torch::Tensor& b_coeffs) { - return std::get<0>(lfilter_core(waveform, a_coeffs, b_coeffs)); -} + return {dx, da}; + } +}; -class DifferentiableLfilter - : public torch::autograd::Function { +class DifferentiableFIR : public torch::autograd::Function { public: static torch::Tensor forward( torch::autograd::AutogradContext* ctx, const torch::Tensor& waveform, - const torch::Tensor& a_coeffs, const torch::Tensor& b_coeffs) { - at::AutoNonVariableTypeMode g; - auto result = lfilter_core(waveform, a_coeffs, b_coeffs); - ctx->save_for_backward( - {waveform, - a_coeffs, - b_coeffs, - std::get<0>(result), - std::get<1>(result)}); - return std::get<0>(result); + int64_t n_order = b_coeffs.size(0); + + namespace F = torch::nn::functional; + auto b_coeff_flipped = b_coeffs.flip(0).contiguous(); + auto padded_waveform = + F::pad(waveform, F::PadFuncOptions({n_order - 1, 0})); + + auto output = + F::conv1d( + padded_waveform.unsqueeze(1), b_coeff_flipped.view({1, 1, n_order})) + .squeeze(1); + + ctx->save_for_backward({waveform, b_coeffs, output}); + return output; } static torch::autograd::tensor_list backward( torch::autograd::AutogradContext* ctx, torch::autograd::tensor_list grad_outputs) { auto saved = ctx->get_saved_variables(); - auto waveform = saved[0]; - auto a_coeffs = saved[1]; - auto b_coeffs = saved[2]; - auto y = saved[3]; - auto xh = saved[4]; - - auto device = waveform.device(); - auto dtype = waveform.dtype(); - int64_t n_channel = waveform.size(0); - int64_t n_sample = waveform.size(1); - int64_t n_order = a_coeffs.size(0); - int64_t n_sample_padded = n_sample + n_order - 1; + auto x = saved[0]; + auto b_coeffs = saved[1]; + auto y = saved[2]; - auto a_coeff_flipped = a_coeffs.flip(0).contiguous(); - auto b_coeff_flipped = b_coeffs.flip(0).contiguous(); - b_coeff_flipped.div_(a_coeffs[0]); - a_coeff_flipped.div_(a_coeffs[0]); + int64_t n_channel = x.size(0); + int64_t n_order = b_coeffs.size(0); auto dx = torch::Tensor(); - auto da = torch::Tensor(); auto db = torch::Tensor(); auto dy = grad_outputs[0]; - at::AutoNonVariableTypeMode g; namespace F = torch::nn::functional; - auto options = torch::TensorOptions().dtype(dtype).device(device); - if (a_coeffs.requires_grad()) { - auto dyda = torch::zeros({n_channel, n_sample_padded}, options); - if (device.is_cpu()) { - cpu_lfilter_core_loop(-y, a_coeff_flipped, dyda); - } else { - lfilter_core_generic_loop(-y, a_coeff_flipped, dyda); - } - - da = F::conv1d( - dyda.unsqueeze(0), + if (b_coeffs.requires_grad()) { + db = F::conv1d( + F::pad(x.unsqueeze(0), F::PadFuncOptions({n_order - 1, 0})), dy.unsqueeze(1), F::Conv1dFuncOptions().groups(n_channel)) .sum(1) .squeeze(0) .flip(0); - da.div_(a_coeffs[0]); } - if (b_coeffs.requires_grad() || waveform.requires_grad()) { - auto dxh = torch::zeros({n_channel, n_sample_padded}, options); - if (device.is_cpu()) { - cpu_lfilter_core_loop(dy.flip(1), a_coeff_flipped, dxh); - } else { - lfilter_core_generic_loop(dy.flip(1), a_coeff_flipped, dxh); - } - - dxh = dxh.index( - {torch::indexing::Slice(), - torch::indexing::Slice(n_order - 1, torch::indexing::None)}) - .flip(1); - - if (waveform.requires_grad()) { - dx = F::conv1d( - F::pad(dxh.unsqueeze(1), F::PadFuncOptions({0, n_order - 1})), - b_coeffs.view({1, 1, n_order})) - .squeeze(1); - dx.div_(a_coeffs[0]); - } - if (b_coeffs.requires_grad()) { - db = - F::conv1d( - F::pad( - waveform.unsqueeze(0), F::PadFuncOptions({n_order - 1, 0})), - dxh.unsqueeze(1), - F::Conv1dFuncOptions().groups(n_channel)) - .sum(1) - .squeeze(0) - .flip(0); - db.div_(a_coeffs[0]); - } + if (x.requires_grad()) { + dx = F::conv1d( + F::pad(dy.unsqueeze(1), F::PadFuncOptions({0, n_order - 1})), + b_coeffs.view({1, 1, n_order})) + .squeeze(1); } - return {dx, da, db}; + return {dx, db}; } }; -torch::Tensor lfilter_autograd( +torch::Tensor lfilter_core( const torch::Tensor& waveform, const torch::Tensor& a_coeffs, const torch::Tensor& b_coeffs) { - return DifferentiableLfilter::apply(waveform, a_coeffs, b_coeffs); + TORCH_CHECK(waveform.device() == a_coeffs.device()); + TORCH_CHECK(b_coeffs.device() == a_coeffs.device()); + TORCH_CHECK(a_coeffs.size(0) == b_coeffs.size(0)); + + TORCH_INTERNAL_ASSERT(waveform.sizes().size() == 2); + + int64_t n_order = b_coeffs.size(0); + + TORCH_INTERNAL_ASSERT(n_order > 0); + + auto filtered_waveform = + DifferentiableFIR::apply(waveform, b_coeffs / a_coeffs[0]); + + auto output = + DifferentiableIIR::apply(filtered_waveform, a_coeffs / a_coeffs[0]); + return output; } } // namespace @@ -259,10 +248,6 @@ TORCH_LIBRARY(torchaudio, m) { "torchaudio::_lfilter(Tensor waveform, Tensor a_coeffs, Tensor b_coeffs) -> Tensor"); } -TORCH_LIBRARY_IMPL(torchaudio, DefaultBackend, m) { - m.impl("torchaudio::_lfilter", lfilter_simple); -} - -TORCH_LIBRARY_IMPL(torchaudio, Autograd, m) { - m.impl("torchaudio::_lfilter", lfilter_autograd); +TORCH_LIBRARY_IMPL(torchaudio, CompositeImplicitAutograd, m) { + m.impl("torchaudio::_lfilter", lfilter_core); } diff --git a/torchaudio/csrc/rnnt/compute.cpp b/torchaudio/csrc/rnnt/compute.cpp index 91ce8cceb6..bce803fffa 100644 --- a/torchaudio/csrc/rnnt/compute.cpp +++ b/torchaudio/csrc/rnnt/compute.cpp @@ -1,12 +1,13 @@ #include TORCH_LIBRARY_FRAGMENT(torchaudio, m) { - m.def("rnnt_loss(Tensor logits," - "Tensor targets," - "Tensor src_lengths," - "Tensor tgt_lengths," - "int blank," - "float clamp," - "bool fused_log_smax=True," - "bool reuse_logits_for_grads=True) -> (Tensor, Tensor?)"); + m.def( + "rnnt_loss(Tensor logits," + "Tensor targets," + "Tensor src_lengths," + "Tensor tgt_lengths," + "int blank," + "float clamp," + "bool fused_log_smax=True," + "bool reuse_logits_for_grads=True) -> (Tensor, Tensor?)"); } diff --git a/torchaudio/csrc/rnnt/compute_alphas.cpp b/torchaudio/csrc/rnnt/compute_alphas.cpp index a52d49b8a1..6460fa1ad5 100644 --- a/torchaudio/csrc/rnnt/compute_alphas.cpp +++ b/torchaudio/csrc/rnnt/compute_alphas.cpp @@ -1,10 +1,11 @@ #include TORCH_LIBRARY_FRAGMENT(torchaudio, m) { - m.def("rnnt_loss_alphas(Tensor logits," - "Tensor targets," - "Tensor src_lengths," - "Tensor tgt_lengths," - "int blank," - "float clamp) -> Tensor"); + m.def( + "rnnt_loss_alphas(Tensor logits," + "Tensor targets," + "Tensor src_lengths," + "Tensor tgt_lengths," + "int blank," + "float clamp) -> Tensor"); } diff --git a/torchaudio/csrc/rnnt/compute_betas.cpp b/torchaudio/csrc/rnnt/compute_betas.cpp index 234dd909b5..209f786d4e 100644 --- a/torchaudio/csrc/rnnt/compute_betas.cpp +++ b/torchaudio/csrc/rnnt/compute_betas.cpp @@ -1,10 +1,11 @@ #include TORCH_LIBRARY_FRAGMENT(torchaudio, m) { - m.def("rnnt_loss_betas(Tensor logits," - "Tensor targets," - "Tensor src_lengths," - "Tensor tgt_lengths," - "int blank," - "float clamp) -> Tensor"); + m.def( + "rnnt_loss_betas(Tensor logits," + "Tensor targets," + "Tensor src_lengths," + "Tensor tgt_lengths," + "int blank," + "float clamp) -> Tensor"); } diff --git a/torchaudio/csrc/rnnt/cpu/compute.cpp b/torchaudio/csrc/rnnt/cpu/compute.cpp index 1cd9801d18..bc8f8034db 100644 --- a/torchaudio/csrc/rnnt/cpu/compute.cpp +++ b/torchaudio/csrc/rnnt/cpu/compute.cpp @@ -15,6 +15,61 @@ std::tuple> compute( double clamp, bool fused_log_smax = true, bool reuse_logits_for_grads = true) { + TORCH_CHECK( + logits.device().type() == targets.device().type(), + "logits and targets must be on the same device"); + TORCH_CHECK( + logits.device().type() == src_lengths.device().type(), + "logits and logit_lengths must be on the same device"); + TORCH_CHECK( + logits.device().type() == tgt_lengths.device().type(), + "logits and target_lengths must be on the same device"); + + TORCH_CHECK( + logits.dtype() == torch::kFloat32 || logits.dtype() == torch::kFloat16, + "logits must be float32 or float16 (half) type"); + TORCH_CHECK(targets.dtype() == torch::kInt32, "targets must be int32 type"); + TORCH_CHECK( + src_lengths.dtype() == torch::kInt32, "logit_lengths must be int32 type"); + TORCH_CHECK( + tgt_lengths.dtype() == torch::kInt32, + "target_lengths must be int32 type"); + + TORCH_CHECK(logits.is_contiguous(), "logits must be contiguous"); + TORCH_CHECK(targets.is_contiguous(), "targets must be contiguous"); + TORCH_CHECK(src_lengths.is_contiguous(), "logit_lengths must be contiguous"); + TORCH_CHECK(tgt_lengths.is_contiguous(), "target_lengths must be contiguous"); + + TORCH_CHECK( + logits.dim() == 4, "logits must be 4-D (batch, time, target, class)"); + TORCH_CHECK( + targets.dim() == 2, "targets must be 2-D (batch, max target length)"); + TORCH_CHECK(src_lengths.dim() == 1, "logit_lengths must be 1-D"); + TORCH_CHECK(tgt_lengths.dim() == 1, "target_lengths must be 1-D"); + + TORCH_CHECK( + src_lengths.size(0) == logits.size(0), + "batch dimension mismatch between logits and logit_lengths"); + TORCH_CHECK( + tgt_lengths.size(0) == logits.size(0), + "batch dimension mismatch between logits and target_lengths"); + TORCH_CHECK( + targets.size(0) == logits.size(0), + "batch dimension mismatch between logits and targets"); + + TORCH_CHECK( + blank >= 0 && blank < logits.size(-1), + "blank must be within [0, logits.shape[-1])"); + + TORCH_CHECK( + logits.size(1) == at::max(src_lengths).item().toInt(), + "input length mismatch"); + TORCH_CHECK( + logits.size(2) == at::max(tgt_lengths).item().toInt() + 1, + "output length mismatch"); + TORCH_CHECK( + targets.size(1) == at::max(tgt_lengths).item().toInt(), + "target length mismatch"); Options options; options.batchSize_ = src_lengths.size(0); @@ -43,50 +98,52 @@ std::tuple> compute( torch::Tensor int_workspace = torch::empty( IntWorkspace::ComputeSizeFromOptions(options), - torch::TensorOptions().device(logits.device()).dtype(torch::ScalarType::Int)); + torch::TensorOptions() + .device(logits.device()) + .dtype(torch::ScalarType::Int)); torch::Tensor float_workspace = torch::empty( DtypeWorkspace::ComputeSizeFromOptions(options), - torch::TensorOptions().device(logits.device()).dtype(torch::ScalarType::Float)); + torch::TensorOptions() + .device(logits.device()) + .dtype(torch::ScalarType::Float)); Workspace workspace( /*options=*/options, - /*dtype_data=*/float_workspace.data(), + /*dtype_data=*/float_workspace.data_ptr(), /*dtype_size=*/float_workspace.numel(), - /*int_data=*/int_workspace.data(), + /*int_data=*/int_workspace.data_ptr(), /*int_size=*/int_workspace.numel()); - switch (logits.type().scalarType()) { - case torch::ScalarType::Float: - { - Compute( - /*workspace=*/workspace, - /*logits=*/logits.data(), - /*targets=*/targets.data(), - /*src_lengths=*/src_lengths.data(), - /*tgt_lengths=*/tgt_lengths.data(), - /*costs=*/costs.data(), - /*gradients=*/(gradients == c10::nullopt)? nullptr : gradients->data()); - break; - } - case torch::ScalarType::Half: - { - Compute( - /*workspace=*/workspace, - /*logits=*/logits.data(), - /*targets=*/targets.data(), - /*src_lengths=*/src_lengths.data(), - /*tgt_lengths=*/tgt_lengths.data(), - /*costs=*/costs.data(), - /*gradients=*/(gradients == c10::nullopt)? nullptr : gradients->data()); - break; - } - default: - { - LOG(ERROR) << "unsupported logits.type().scalarType() = " - << logits.type().scalarType(); - break; - } + switch (logits.scalar_type()) { + case torch::ScalarType::Float: { + Compute( + /*workspace=*/workspace, + /*logits=*/logits.data_ptr(), + /*targets=*/targets.data_ptr(), + /*src_lengths=*/src_lengths.data_ptr(), + /*tgt_lengths=*/tgt_lengths.data_ptr(), + /*costs=*/costs.data_ptr(), + /*gradients=*/ + (gradients == c10::nullopt) ? nullptr : gradients->data_ptr()); + break; + } + case torch::ScalarType::Half: { + Compute( + /*workspace=*/workspace, + /*logits=*/logits.data_ptr(), + /*targets=*/targets.data_ptr(), + /*src_lengths=*/src_lengths.data_ptr(), + /*tgt_lengths=*/tgt_lengths.data_ptr(), + /*costs=*/costs.data_ptr(), + /*gradients=*/ + (gradients == c10::nullopt) ? nullptr + : gradients->data_ptr()); + break; + } + default: { + break; + } }; return std::make_tuple(costs, gradients); @@ -96,6 +153,6 @@ TORCH_LIBRARY_IMPL(torchaudio, CPU, m) { m.impl("rnnt_loss", &compute); } -} // namespace cpu -} // namespace rnnt -} // namespace torchaudio +} // namespace cpu +} // namespace rnnt +} // namespace torchaudio diff --git a/torchaudio/csrc/rnnt/cpu/compute_alphas.cpp b/torchaudio/csrc/rnnt/cpu/compute_alphas.cpp index fed1dec5cd..5eb8528b15 100644 --- a/torchaudio/csrc/rnnt/cpu/compute_alphas.cpp +++ b/torchaudio/csrc/rnnt/cpu/compute_alphas.cpp @@ -44,20 +44,20 @@ torch::Tensor compute_alphas( Workspace workspace( /*options=*/options, - /*dtype_data=*/float_workspace.data(), + /*dtype_data=*/float_workspace.data_ptr(), /*dtype_size=*/float_workspace.numel(), - /*int_data=*/int_workspace.data(), + /*int_data=*/int_workspace.data_ptr(), /*int_size=*/int_workspace.numel()); // Only support float, this is mainly to enable easy // unit-testing ComputeAlphas( /*workspace=*/workspace, - /*logits=*/logits.data(), - /*targets=*/targets.data(), - /*src_lengths=*/src_lengths.data(), - /*tgt_lengths=*/tgt_lengths.data(), - /*alphas=*/alphas.data()); + /*logits=*/logits.data_ptr(), + /*targets=*/targets.data_ptr(), + /*src_lengths=*/src_lengths.data_ptr(), + /*tgt_lengths=*/tgt_lengths.data_ptr(), + /*alphas=*/alphas.data_ptr()); return alphas; } diff --git a/torchaudio/csrc/rnnt/cpu/compute_betas.cpp b/torchaudio/csrc/rnnt/cpu/compute_betas.cpp index 3789dec895..228cd66c1b 100644 --- a/torchaudio/csrc/rnnt/cpu/compute_betas.cpp +++ b/torchaudio/csrc/rnnt/cpu/compute_betas.cpp @@ -48,21 +48,21 @@ torch::Tensor compute_betas( Workspace workspace( /*options=*/options, - /*dtype_data=*/float_workspace.data(), + /*dtype_data=*/float_workspace.data_ptr(), /*dtype_size=*/float_workspace.numel(), - /*int_data=*/int_workspace.data(), + /*int_data=*/int_workspace.data_ptr(), /*int_size=*/int_workspace.numel()); // Only support float, this is mainly to enable easy // unit-testing ComputeBetas( /*workspace=*/workspace, - /*logits=*/logits.data(), - /*targets=*/targets.data(), - /*src_lengths=*/src_lengths.data(), - /*tgt_lengths=*/tgt_lengths.data(), - /*costs=*/costs.data(), - /*betas=*/betas.data()); + /*logits=*/logits.data_ptr(), + /*targets=*/targets.data_ptr(), + /*src_lengths=*/src_lengths.data_ptr(), + /*tgt_lengths=*/tgt_lengths.data_ptr(), + /*costs=*/costs.data_ptr(), + /*betas=*/betas.data_ptr()); return betas; } @@ -70,6 +70,6 @@ TORCH_LIBRARY_IMPL(torchaudio, CPU, m) { m.impl("rnnt_loss_betas", &compute_betas); } -} // namespace cpu +} // namespace cpu } // namespace rnnt } // namespace torchaudio diff --git a/torchaudio/csrc/rnnt/cpu/cpu_kernels.h b/torchaudio/csrc/rnnt/cpu/cpu_kernels.h index bb63b97ce2..468cb41887 100644 --- a/torchaudio/csrc/rnnt/cpu/cpu_kernels.h +++ b/torchaudio/csrc/rnnt/cpu/cpu_kernels.h @@ -325,8 +325,7 @@ void ComputeGradientsOneSequence( CAST_DTYPE c = alpha({t, u}) + cost - denom({t, u}); for (int d = 0; d < D; ++d) { CAST_DTYPE g = CAST_DTYPE(logits({t, u, d})) + c; - if (d == blank && t == T - 1 && - u == U - 1) { // last blank transition. + if (d == blank && t == T - 1 && u == U - 1) { // last blank transition. gradients({t, u, d}) = std::exp(g + beta({t, u})) - std::exp(g); } else if (d == blank && t < T - 1) { gradients({t, u, d}) = diff --git a/torchaudio/csrc/rnnt/cpu/cpu_transducer.h b/torchaudio/csrc/rnnt/cpu/cpu_transducer.h index 47a058dc31..9d1fc86789 100644 --- a/torchaudio/csrc/rnnt/cpu/cpu_transducer.h +++ b/torchaudio/csrc/rnnt/cpu/cpu_transducer.h @@ -36,7 +36,7 @@ status_t Compute( const int& D = options.numTargets_; { // compute denominators. - status_t status = LogSumExp2D( + LogSumExp2D( /*N=*/B * maxT * maxU, /*D=*/D, /*logits=*/logits, @@ -44,7 +44,7 @@ status_t Compute( } { // compute log prob pairs. - status_t status = ComputeLogProbs( + ComputeLogProbs( /*options=*/options, /*logits=*/logits, /*targets=*/targets, @@ -99,7 +99,7 @@ status_t ComputeAlphas( const int& D = options.numTargets_; { // compute denominators. - status_t status = LogSumExp2D( + LogSumExp2D( /*N=*/B * maxT * maxU, /*D=*/D, /*logits=*/logits, @@ -107,7 +107,7 @@ status_t ComputeAlphas( } { // compute log prob pairs. - status_t status = ComputeLogProbs( + ComputeLogProbs( /*options=*/options, /*logits=*/logits, /*targets=*/targets, @@ -129,8 +129,6 @@ status_t ComputeAlphas( return SUCCESS; } - - template status_t ComputeBetas( const Workspace& workspace, @@ -150,7 +148,7 @@ status_t ComputeBetas( const int& D = options.numTargets_; { // compute denominators. - status_t status = LogSumExp2D( + LogSumExp2D( /*N=*/B * maxT * maxU, /*D=*/D, /*logits=*/logits, @@ -158,7 +156,7 @@ status_t ComputeBetas( } { // compute log prob pairs. - status_t status = ComputeLogProbs( + ComputeLogProbs( /*options=*/options, /*logits=*/logits, /*targets=*/targets, diff --git a/torchaudio/csrc/rnnt/cpu/kernel_utils.h b/torchaudio/csrc/rnnt/cpu/kernel_utils.h index 08fc97b2e1..5a4b0fb887 100644 --- a/torchaudio/csrc/rnnt/cpu/kernel_utils.h +++ b/torchaudio/csrc/rnnt/cpu/kernel_utils.h @@ -17,43 +17,50 @@ inline HOST_AND_DEVICE bool in_range( #define LOG_PROBS_SKIP_IDX 0 #define LOG_PROBS_EMIT_IDX 1 - struct Indexer2D { const int& size2_; - FORCE_INLINE HOST_AND_DEVICE Indexer2D(const int& size2): size2_(size2) {} + FORCE_INLINE HOST_AND_DEVICE Indexer2D(const int& size2) : size2_(size2) {} - FORCE_INLINE HOST_AND_DEVICE int operator() (int index1, int index2) { + FORCE_INLINE HOST_AND_DEVICE int operator()(int index1, int index2) { return index1 * size2_ + index2; } }; - struct Indexer3D { const int& size2_; const int& size3_; FORCE_INLINE HOST_AND_DEVICE Indexer3D(const int& size2, const int& size3) - : size2_(size2), size3_(size3) {} + : size2_(size2), size3_(size3) {} - FORCE_INLINE HOST_AND_DEVICE int operator() (int index1, int index2, int index3) { + FORCE_INLINE HOST_AND_DEVICE int operator()( + int index1, + int index2, + int index3) { return (index1 * size2_ + index2) * size3_ + index3; } }; - struct Indexer4D { const int& size2_; const int& size3_; const int& size4_; - HOST_AND_DEVICE Indexer4D(const int& size2, const int& size3, const int& size4) - : size2_(size2), size3_(size3), size4_(size4) {} - - HOST_AND_DEVICE int operator() (int index1, int index2, int index3, int index4) { + HOST_AND_DEVICE Indexer4D( + const int& size2, + const int& size3, + const int& size4) + : size2_(size2), size3_(size3), size4_(size4) {} + + HOST_AND_DEVICE int operator()( + int index1, + int index2, + int index3, + int index4) { return ((index1 * size2_ + index2) * size3_ + index3) * size4_ + index4; } }; -} // namespace rnnt -} // namespace torchaudio +} // namespace rnnt +} // namespace torchaudio diff --git a/torchaudio/csrc/rnnt/cpu/math.h b/torchaudio/csrc/rnnt/cpu/math.h index 4f1d7bc4dd..e630a65cd2 100644 --- a/torchaudio/csrc/rnnt/cpu/math.h +++ b/torchaudio/csrc/rnnt/cpu/math.h @@ -9,14 +9,18 @@ namespace math { template FORCE_INLINE HOST_AND_DEVICE DTYPE max(DTYPE x, DTYPE y) { - if (x > y) return x; - else return y; + if (x > y) + return x; + else + return y; } template FORCE_INLINE HOST_AND_DEVICE DTYPE min(DTYPE x, DTYPE y) { - if (x > y) return y; - else return x; + if (x > y) + return y; + else + return x; } // log_sum_exp @@ -25,11 +29,14 @@ FORCE_INLINE HOST_AND_DEVICE DTYPE lse(DTYPE x, DTYPE y); template <> FORCE_INLINE HOST_AND_DEVICE float lse(float x, float y) { - if (y > x) { return y + log1pf(expf(x - y)); } - else { return x + log1pf(expf(y-x)); } + if (y > x) { + return y + log1pf(expf(x - y)); + } else { + return x + log1pf(expf(y - x)); + } } -} +} // namespace math -} // namespace rnnt -} // namespace torchaudio +} // namespace rnnt +} // namespace torchaudio diff --git a/torchaudio/csrc/rnnt/gpu/compute.cu b/torchaudio/csrc/rnnt/gpu/compute.cu new file mode 100644 index 0000000000..d04efaec7e --- /dev/null +++ b/torchaudio/csrc/rnnt/gpu/compute.cu @@ -0,0 +1,161 @@ +#include +#include +#include + +namespace torchaudio { +namespace rnnt { +namespace gpu { + +// Entry point into RNNT Loss +std::tuple> compute( + torch::Tensor& logits, + const torch::Tensor& targets, + const torch::Tensor& src_lengths, + const torch::Tensor& tgt_lengths, + int64_t blank, + double clamp, + bool fused_log_smax = true, + bool reuse_logits_for_grads = true) { + TORCH_CHECK( + logits.device().type() == targets.device().type(), + "logits and targets must be on the same device"); + TORCH_CHECK( + logits.device().type() == src_lengths.device().type(), + "logits and logit_lengths must be on the same device"); + TORCH_CHECK( + logits.device().type() == tgt_lengths.device().type(), + "logits and target_lengths must be on the same device"); + + TORCH_CHECK( + logits.dtype() == torch::kFloat32 || logits.dtype() == torch::kFloat16, + "logits must be float32 or float16 (half) type"); + TORCH_CHECK(targets.dtype() == torch::kInt32, "targets must be int32 type"); + TORCH_CHECK( + src_lengths.dtype() == torch::kInt32, "logit_lengths must be int32 type"); + TORCH_CHECK( + tgt_lengths.dtype() == torch::kInt32, + "target_lengths must be int32 type"); + + TORCH_CHECK(logits.is_contiguous(), "logits must be contiguous"); + TORCH_CHECK(targets.is_contiguous(), "targets must be contiguous"); + TORCH_CHECK(src_lengths.is_contiguous(), "logit_lengths must be contiguous"); + TORCH_CHECK(tgt_lengths.is_contiguous(), "target_lengths must be contiguous"); + + TORCH_CHECK( + logits.dim() == 4, "logits must be 4-D (batch, time, target, class)"); + TORCH_CHECK( + targets.dim() == 2, "targets must be 2-D (batch, max target length)"); + TORCH_CHECK(src_lengths.dim() == 1, "logit_lengths must be 1-D"); + TORCH_CHECK(tgt_lengths.dim() == 1, "target_lengths must be 1-D"); + + TORCH_CHECK( + src_lengths.size(0) == logits.size(0), + "batch dimension mismatch between logits and logit_lengths"); + TORCH_CHECK( + tgt_lengths.size(0) == logits.size(0), + "batch dimension mismatch between logits and target_lengths"); + TORCH_CHECK( + targets.size(0) == logits.size(0), + "batch dimension mismatch between logits and targets"); + + TORCH_CHECK( + blank >= 0 && blank < logits.size(-1), + "blank must be within [0, logits.shape[-1])"); + + TORCH_CHECK( + logits.size(1) == at::max(src_lengths).item().toInt(), + "input length mismatch"); + TORCH_CHECK( + logits.size(2) == at::max(tgt_lengths).item().toInt() + 1, + "output length mismatch"); + TORCH_CHECK( + targets.size(1) == at::max(tgt_lengths).item().toInt(), + "target length mismatch"); + + Options options; + options.batchSize_ = src_lengths.size(0); + options.nHypos_ = tgt_lengths.size(0) / src_lengths.size(0); + options.maxSrcLen_ = logits.size(1); + options.maxTgtLen_ = logits.size(2); + options.numTargets_ = logits.size(3); + options.blank_ = blank; + options.clamp_ = clamp; + options.fusedLogSmax_ = fused_log_smax; + + CHECK_EQ(logits.device().type(), torch::DeviceType::CUDA); + options.stream_ = at::cuda::getCurrentCUDAStream(); + cudaSetDevice(logits.get_device()); + options.device_ = GPU; + + torch::Tensor costs = torch::empty( + options.batchSize_ * options.nHypos_, + torch::TensorOptions().device(logits.device()).dtype(logits.dtype())); + c10::optional gradients = c10::nullopt; + if (logits.requires_grad()) { + if (reuse_logits_for_grads) { + gradients = logits; + } else { + gradients = torch::zeros_like(logits); + } + } + + torch::Tensor int_workspace = torch::empty( + IntWorkspace::ComputeSizeFromOptions(options), + torch::TensorOptions() + .device(logits.device()) + .dtype(torch::ScalarType::Int)); + + torch::Tensor float_workspace = torch::empty( + DtypeWorkspace::ComputeSizeFromOptions(options), + torch::TensorOptions() + .device(logits.device()) + .dtype(torch::ScalarType::Float)); + + Workspace workspace( + /*options=*/options, + /*dtype_data=*/float_workspace.data_ptr(), + /*dtype_size=*/float_workspace.numel(), + /*int_data=*/int_workspace.data_ptr(), + /*int_size=*/int_workspace.numel()); + + switch (logits.scalar_type()) { + case torch::ScalarType::Float: { + Compute( + /*workspace=*/workspace, + /*logits=*/logits.data_ptr(), + /*targets=*/targets.data_ptr(), + /*src_lengths=*/src_lengths.data_ptr(), + /*tgt_lengths=*/tgt_lengths.data_ptr(), + /*costs=*/costs.data_ptr(), + /*gradients=*/ + (gradients == c10::nullopt) ? nullptr : gradients->data_ptr()); + break; + } + case torch::ScalarType::Half: { + Compute( + /*workspace=*/workspace, + /*logits=*/logits.data_ptr(), + /*targets=*/targets.data_ptr(), + /*src_lengths=*/src_lengths.data_ptr(), + /*tgt_lengths=*/tgt_lengths.data_ptr(), + /*costs=*/costs.data_ptr(), + /*gradients=*/ + (gradients == c10::nullopt) ? nullptr + : gradients->data_ptr()); + break; + } + default: { + break; + } + }; + + return std::make_tuple(costs, gradients); +} + +TORCH_LIBRARY_IMPL(torchaudio, CUDA, m) { + m.impl("rnnt_loss", &compute); +} + +} // namespace gpu +} // namespace rnnt +} // namespace torchaudio diff --git a/torchaudio/csrc/rnnt/gpu/compute_alphas.cu b/torchaudio/csrc/rnnt/gpu/compute_alphas.cu new file mode 100644 index 0000000000..f24c6a5b0f --- /dev/null +++ b/torchaudio/csrc/rnnt/gpu/compute_alphas.cu @@ -0,0 +1,73 @@ +#include +#include +#include + +namespace torchaudio { +namespace rnnt { +namespace gpu { + +torch::Tensor compute_alphas( + const torch::Tensor& logits, + const torch::Tensor& targets, + const torch::Tensor& src_lengths, + const torch::Tensor& tgt_lengths, + int64_t blank, + double clamp) { + Options options; + options.batchSize_ = src_lengths.size(0); + options.nHypos_ = tgt_lengths.size(0) / src_lengths.size(0); + options.maxSrcLen_ = logits.size(1); + options.maxTgtLen_ = logits.size(2); + options.numTargets_ = logits.size(3); + options.blank_ = blank; + options.clamp_ = clamp; + + CHECK_EQ(logits.device().type(), torch::DeviceType::CUDA); + options.stream_ = at::cuda::getCurrentCUDAStream(); + cudaSetDevice(logits.get_device()); + options.device_ = GPU; + + torch::Tensor alphas = torch::zeros( + {options.batchSize_ * options.nHypos_, + options.maxSrcLen_, + options.maxTgtLen_}, + torch::TensorOptions().device(logits.device()).dtype(logits.dtype())); + + torch::Tensor int_workspace = torch::empty( + IntWorkspace::ComputeSizeFromOptions(options), + torch::TensorOptions() + .device(logits.device()) + .dtype(torch::ScalarType::Int)); + + torch::Tensor float_workspace = torch::empty( + DtypeWorkspace::ComputeSizeFromOptions(options), + torch::TensorOptions() + .device(logits.device()) + .dtype(torch::ScalarType::Float)); + + Workspace workspace( + /*options=*/options, + /*dtype_data=*/float_workspace.data_ptr(), + /*dtype_size=*/float_workspace.numel(), + /*int_data=*/int_workspace.data_ptr(), + /*int_size=*/int_workspace.numel()); + + // Only support float, this is mainly to enable easy + // unit-testing + ComputeAlphas( + /*workspace=*/workspace, + /*logits=*/logits.data_ptr(), + /*targets=*/targets.data_ptr(), + /*src_lengths=*/src_lengths.data_ptr(), + /*tgt_lengths=*/tgt_lengths.data_ptr(), + /*alphas=*/alphas.data_ptr()); + return alphas; +} + +TORCH_LIBRARY_IMPL(torchaudio, CUDA, m) { + m.impl("rnnt_loss_alphas", &compute_alphas); +} + +} // namespace gpu +} // namespace rnnt +} // namespace torchaudio diff --git a/torchaudio/csrc/rnnt/gpu/compute_betas.cu b/torchaudio/csrc/rnnt/gpu/compute_betas.cu new file mode 100644 index 0000000000..a225c9cf42 --- /dev/null +++ b/torchaudio/csrc/rnnt/gpu/compute_betas.cu @@ -0,0 +1,78 @@ +#include +#include +#include + +namespace torchaudio { +namespace rnnt { +namespace gpu { + +torch::Tensor compute_betas( + const torch::Tensor& logits, + const torch::Tensor& targets, + const torch::Tensor& src_lengths, + const torch::Tensor& tgt_lengths, + int64_t blank, + double clamp) { + Options options; + options.batchSize_ = src_lengths.size(0); + options.nHypos_ = tgt_lengths.size(0) / src_lengths.size(0); + options.maxSrcLen_ = logits.size(1); + options.maxTgtLen_ = logits.size(2); + options.numTargets_ = logits.size(3); + options.blank_ = blank; + options.clamp_ = clamp; + + CHECK_EQ(logits.device().type(), torch::DeviceType::CUDA); + options.stream_ = at::cuda::getCurrentCUDAStream(); + cudaSetDevice(logits.get_device()); + options.device_ = GPU; + + torch::Tensor costs = torch::empty( + tgt_lengths.size(0), + torch::TensorOptions().device(logits.device()).dtype(logits.dtype())); + + torch::Tensor betas = torch::zeros( + {options.batchSize_ * options.nHypos_, + options.maxSrcLen_, + options.maxTgtLen_}, + torch::TensorOptions().device(logits.device()).dtype(logits.dtype())); + + torch::Tensor int_workspace = torch::empty( + IntWorkspace::ComputeSizeFromOptions(options), + torch::TensorOptions() + .device(logits.device()) + .dtype(torch::ScalarType::Int)); + + torch::Tensor float_workspace = torch::empty( + DtypeWorkspace::ComputeSizeFromOptions(options), + torch::TensorOptions() + .device(logits.device()) + .dtype(torch::ScalarType::Float)); + + Workspace workspace( + /*options=*/options, + /*dtype_data=*/float_workspace.data_ptr(), + /*dtype_size=*/float_workspace.numel(), + /*int_data=*/int_workspace.data_ptr(), + /*int_size=*/int_workspace.numel()); + + // Only support float, this is mainly to enable easy + // unit-testing + ComputeBetas( + /*workspace=*/workspace, + /*logits=*/logits.data_ptr(), + /*targets=*/targets.data_ptr(), + /*src_lengths=*/src_lengths.data_ptr(), + /*tgt_lengths=*/tgt_lengths.data_ptr(), + /*costs=*/costs.data_ptr(), + /*betas=*/betas.data_ptr()); + return betas; +} + +TORCH_LIBRARY_IMPL(torchaudio, CUDA, m) { + m.impl("rnnt_loss_betas", &compute_betas); +} + +} // namespace gpu +} // namespace rnnt +} // namespace torchaudio diff --git a/torchaudio/csrc/rnnt/gpu/gpu_kernel_utils.cuh b/torchaudio/csrc/rnnt/gpu/gpu_kernel_utils.cuh new file mode 100644 index 0000000000..e5f1cfc2df --- /dev/null +++ b/torchaudio/csrc/rnnt/gpu/gpu_kernel_utils.cuh @@ -0,0 +1,98 @@ +#pragma once + +#ifdef USE_CUDA + +#include + +namespace torchaudio { +namespace rnnt { + +template +__global__ void ReduceMax2D( + int dim, + const DTYPE* inputs, // [N, dim] + CAST_DTYPE* outputs) { + __shared__ CAST_DTYPE shared[NUM_THREADS]; + + // each thread reduces one matrix row + int offset = blockIdx.x * dim; // [n, 0] + CAST_DTYPE val = inputs[offset]; // default = inputs(n, 0) + for (int d = threadIdx.x; d < dim; d += NUM_THREADS) { + CAST_DTYPE next = inputs[offset + d]; + if (next > val) { + val = next; + } + } + + shared[threadIdx.x] = val; + __syncthreads(); + + for (int stride = (NUM_THREADS >> 1); stride >= WARP_SIZE; stride >>= 1) { + if (threadIdx.x < stride && threadIdx.x + stride < dim) { + if (shared[threadIdx.x + stride] > shared[threadIdx.x]) { + shared[threadIdx.x] = shared[threadIdx.x + stride]; + val = shared[threadIdx.x]; + } + } + __syncthreads(); + } + + CAST_DTYPE shf; + for (int stride = (WARP_SIZE >> 1); stride > 0; stride >>= 1) { + shf = __shfl_down_sync(0xFFFFFFFF, val, stride); + if (threadIdx.x < stride && threadIdx.x + stride < dim) { + if (shf > val) { + val = shf; + } + } + } + + if (threadIdx.x == 0) { + outputs[blockIdx.x] = val; + } +} + +template +__global__ void ReduceLogSumExpGivenMax2D( + int dim, + const DTYPE* inputs, // [N, dim] + CAST_DTYPE* outputs) { // in: max -> out: logsum + + __shared__ CAST_DTYPE shared[NUM_THREADS]; + + CAST_DTYPE max = outputs[blockIdx.x]; + CAST_DTYPE val = 0; + + int offset = blockIdx.x * dim; + for (int d = threadIdx.x; d < dim; d += NUM_THREADS) { + val = val + std::exp(CAST_DTYPE(inputs[offset + d]) - max); + } + + shared[threadIdx.x] = val; + __syncthreads(); + + for (int stride = (NUM_THREADS >> 1); stride >= WARP_SIZE; stride >>= 1) { + if (threadIdx.x < stride && threadIdx.x + stride < dim) { + val = shared[threadIdx.x] + shared[threadIdx.x + stride]; + shared[threadIdx.x] = val; + } + __syncthreads(); + } + + CAST_DTYPE shf; + for (int stride = (WARP_SIZE >> 1); stride > 0; stride >>= 1) { + shf = __shfl_down_sync(0xFFFFFFFF, val, stride); + if (threadIdx.x < stride && threadIdx.x + stride < dim) { + val = val + shf; + } + } + + if (threadIdx.x == 0) { + outputs[blockIdx.x] = max + std::log(val); + } +} + +} // namespace rnnt +} // namespace torchaudio + +#endif // USE_CUDA diff --git a/torchaudio/csrc/rnnt/gpu/gpu_kernels.cuh b/torchaudio/csrc/rnnt/gpu/gpu_kernels.cuh new file mode 100644 index 0000000000..4ba04b68fc --- /dev/null +++ b/torchaudio/csrc/rnnt/gpu/gpu_kernels.cuh @@ -0,0 +1,422 @@ +#pragma once + +#ifdef USE_CUDA + +#include + +#include +#include +#include + +namespace torchaudio { +namespace rnnt { + +template +__global__ void ComputeLogProbs( + int maxSrcLen, + int maxTgtLen, + int numTargets, + int blank, + const DTYPE* logits, + const int* targets, + const int* srcLengths, + const int* tgtLengths, + const CAST_DTYPE* denominators, + CAST_DTYPE* logProbs, + int H = 1, + bool fusedLogSmax = true) { + const int& maxT = maxSrcLen; + const int& maxU = maxTgtLen; + const int& D = numTargets; + + const int bTgt = blockIdx.z; // 0 <= b < B + const int bSrc = bTgt / H; + const int T = srcLengths[bSrc]; + const int U = tgtLengths[bTgt] + 1; + + const int t = blockIdx.x * blockDim.x + threadIdx.x; + const int u = blockIdx.y; + + if (t >= T || u >= U) { // out of boundary. + return; + } + + Indexer3D indexer(maxT, maxU); + + int idx = indexer(bTgt, t, u); + + // skip: log_prob(b, t, u).skip() = logits(b, t, u, blank) - denom(b, t, u). + logProbs[(idx << 1) + LOG_PROBS_SKIP_IDX] = + CAST_DTYPE(logits[idx * D + blank]) - denominators[idx]; + + if (!fusedLogSmax) { + logProbs[(idx << 1) + LOG_PROBS_SKIP_IDX] = + CAST_DTYPE(logits[idx * D + blank]); + } + + if (u < U - 1) { + // emit: log_prob(b, t, u).emit() = logits(b, t, u, tgt[u]) - denom(b, t, + // u). + int target = targets[Indexer2D(maxU - 1)(bTgt, u)]; + logProbs[(idx << 1) + LOG_PROBS_EMIT_IDX] = + CAST_DTYPE(logits[idx * D + target]) - denominators[idx]; + + if (!fusedLogSmax) { + logProbs[(idx << 1) + LOG_PROBS_EMIT_IDX] = + CAST_DTYPE(logits[idx * D + target]); + } + } +} + +template +__device__ void ComputeAlphas( + int maxSrcLen, + int maxTgtLen, + int numTargets, + int blank, + const CAST_DTYPE* logProbs, + const int* srcLengths, + const int* tgtLengths, + int* alpha_counters, + volatile CAST_DTYPE* alphas, + int H = 1) { + const int& maxT = maxSrcLen; + const int& maxU = maxTgtLen; + + const int bTgt = blockIdx.z; // 0 <= b < B + const int bSrc = bTgt / H; + const int T = srcLengths[bSrc]; + const int U = tgtLengths[bTgt] + 1; + + const int t = blockIdx.x * blockDim.x + threadIdx.x + 1; + const int u = blockIdx.y + 1; + + if (t >= T || u >= U) { // out of boundary. + return; + } + + int* counter = alpha_counters + Indexer2D(maxU)(bTgt, blockIdx.y); + + Indexer3D idxr(maxT, maxU); + + if (t == 1 && u == 1) { + alphas[idxr(bTgt, 0, 0)] = 0; + } + + if (blockIdx.x > 0) { // wait for previous warp (in t-axis) is ready. + while (atomicAdd(counter, 0) < blockIdx.x) { + } + } + + if (blockIdx.y > 0) { // wait for previous warp (in u-axis) is ready. + while (atomicAdd(counter - 1, 0) <= blockIdx.x) { + } + } + + if (t == 1 && u < U) { + // alpha(0, u) = alpha(0, u - 1) + logProbs(0, u - 1).emit(). + alphas[idxr(bTgt, 0, u)] = alphas[idxr(bTgt, 0, u - 1)] + + logProbs[(idxr(bTgt, 0, u - 1) << 1) + LOG_PROBS_EMIT_IDX]; + } + + if (blockIdx.y == 0 && t < T) { + CAST_DTYPE skip_prob = + logProbs[(idxr(bTgt, t - 1, 0) << 1) + LOG_PROBS_SKIP_IDX]; + CAST_DTYPE val; + +#pragma unroll + for (int i = 1; i < warpSize; i <<= 1) { + val = __shfl_up_sync(0xffffffff, skip_prob, i); + if (i <= threadIdx.x) { + skip_prob = skip_prob + val; + } + } + + val = alphas[idxr(bTgt, blockIdx.x * blockDim.x, 0)]; + alphas[idxr(bTgt, t, 0)] = skip_prob + val; + } + + if (t < T && u < U) { + CAST_DTYPE skip_prob = + logProbs[(idxr(bTgt, t - 1, u) << 1) + LOG_PROBS_SKIP_IDX]; + CAST_DTYPE emit_prob = + logProbs[(idxr(bTgt, t, u - 1) << 1) + LOG_PROBS_EMIT_IDX]; + + CAST_DTYPE skip = + alphas[idxr(bTgt, blockIdx.x * blockDim.x, u)] + skip_prob; + CAST_DTYPE emit = alphas[idxr(bTgt, t, u - 1)] + emit_prob; + + CAST_DTYPE val = math::lse(skip, emit); + CAST_DTYPE out = val; + + for (int i = 1; i < warpSize; ++i) { + val = __shfl_up_sync(0xffffffff, val, 1); + if (i == threadIdx.x) { + val = math::lse(val + skip_prob, emit); + out = val; + } + } + + alphas[idxr(bTgt, t, u)] = out; + } + + if (threadIdx.x == 0) { + __threadfence(); + atomicAdd(counter, 1); + } +} + +template +__device__ void ComputeBetasCosts( + int maxSrcLen, + int maxTgtLen, + int numTargets, + int blank, + const CAST_DTYPE* logProbs, + const int* srcLengths, + const int* tgtLengths, + int* betaCounters, + volatile CAST_DTYPE* betas, + DTYPE* costs, + int H = 1) { + const int& maxT = maxSrcLen; + const int& maxU = maxTgtLen; + + const int bTgt = blockIdx.z; // 0 <= b < B + const int bSrc = bTgt / H; + const int T = srcLengths[bSrc]; + const int U = tgtLengths[bTgt] + 1; + + const int t = T - 2 - blockIdx.x * blockDim.x - threadIdx.x; + const int u = U - 2 - blockIdx.y; + + if (t < 0 || u < 0) { // out of boundary. + return; + } + + int* counter = betaCounters + Indexer2D(maxU)(bTgt, blockIdx.y); + + Indexer3D idxr(maxT, maxU); + + if (t == T - 2 && u == U - 2) { + betas[idxr(bTgt, T - 1, U - 1)] = + logProbs[(idxr(bTgt, T - 1, U - 1) << 1) + LOG_PROBS_SKIP_IDX]; + } + + if (blockIdx.x > 0) { // wait for previous warp (in t-axis) is ready. + while (atomicAdd(counter, 0) < blockIdx.x) { + } + } + + if (blockIdx.y > 0) { // wait for previous warp (in u-axis) is ready. + while (atomicAdd(counter - 1, 0) <= blockIdx.x) { + } + } + + if (t == T - 2 && u >= 0) { + betas[idxr(bTgt, T - 1, u)] = betas[idxr(bTgt, T - 1, u + 1)] + + logProbs[(idxr(bTgt, T - 1, u) << 1) + LOG_PROBS_EMIT_IDX]; + } + + if (blockIdx.y == 0 && t >= 0) { + CAST_DTYPE skip_prob = + logProbs[(idxr(bTgt, t, U - 1) << 1) + LOG_PROBS_SKIP_IDX]; + CAST_DTYPE val; + +#pragma unroll + for (int i = 1; i < warpSize; i <<= 1) { + val = __shfl_up_sync(0xffffffff, skip_prob, i); + if (i <= threadIdx.x) { + skip_prob = skip_prob + val; + } + } + + betas[idxr(bTgt, t, U - 1)] = + betas[idxr(bTgt, T - 1 - blockIdx.x * blockDim.x, U - 1)] + skip_prob; + } + + if (t >= 0 && u >= 0) { + CAST_DTYPE skip_prob = + logProbs[(idxr(bTgt, t, u) << 1) + LOG_PROBS_SKIP_IDX]; + CAST_DTYPE emit_prob = + logProbs[(idxr(bTgt, t, u) << 1) + LOG_PROBS_EMIT_IDX]; + + CAST_DTYPE skip = betas[idxr(bTgt, t + threadIdx.x + 1, u)] + skip_prob; + CAST_DTYPE emit = betas[idxr(bTgt, t, u + 1)] + emit_prob; + + CAST_DTYPE val = math::lse(skip, emit); + CAST_DTYPE out = val; + + for (int i = 1; i < warpSize; ++i) { + val = __shfl_up_sync(0xffffffff, val, 1); + if (i == threadIdx.x) { + val = math::lse(val + skip_prob, emit); + out = val; + } + } + + betas[idxr(bTgt, t, u)] = out; + + if (t == 0 && u == 0) { // use -beta(0, 0) as cost. + costs[bTgt] = DTYPE(-out); + } + } + + if (threadIdx.x == 0) { + __threadfence(); + atomicAdd(counter, 1); + } +} + +template +__global__ void ComputeAlphasBetasCosts( + int maxSrcLen, + int maxTgtLen, + int numTargets, + int blank, + const CAST_DTYPE* logProbs, + const int* srcLengths, + const int* tgtLengths, + int* alpha_counters, + volatile CAST_DTYPE* alphas, + int* betaCounters, + volatile CAST_DTYPE* betas, + DTYPE* costs, + int warpSize = 0, + int numWarps = 0, + int H = 1) { + assert(threadIdx.y == 0 || threadIdx.y == 1); + + if (threadIdx.y == 0) { + ComputeAlphas( + /*maxSrcLen=*/maxSrcLen, + /*maxTgtLen=*/maxTgtLen, + /*numTargets=*/numTargets, + /*blank=*/blank, + /*logProbs=*/logProbs, + /*srcLengths=*/srcLengths, + /*tgtLengths=*/tgtLengths, + /*alpha_counters=*/alpha_counters, + /*alphas=*/alphas, + H); + } else { // threadIdx.y == 1 + ComputeBetasCosts( + /*maxSrcLen=*/maxSrcLen, + /*maxTgtLen=*/maxTgtLen, + /*numTargets=*/numTargets, + /*blank=*/blank, + /*logProbs=*/logProbs, + /*srcLengths=*/srcLengths, + /*tgtLengths=*/tgtLengths, + /*betaCounters=*/betaCounters, + /*beta=*/betas, + /*costs=*/costs, + H); + } +} + +template +__global__ void ComputeGradients( + int maxSrcLen, + int maxTgtLen, + int numTargets, + int blank, + CAST_DTYPE clamp, + const DTYPE* logits, + const int* targets, + const int* srcLengths, + const int* tgtLengths, + const CAST_DTYPE* denominators, + const CAST_DTYPE* alphas, + const CAST_DTYPE* betas, + DTYPE* gradients, + int H = 1, + bool fusedLogSmax = true) { + const int bTgt = blockIdx.z; // 0 <= b < B + const int t = blockIdx.x * blockDim.x + threadIdx.x; + const int u = blockIdx.y; + + ComputeGradientsElement( + bTgt, + t, + u, + maxSrcLen, + maxTgtLen, + numTargets, + blank, + clamp, + logits, + targets, + srcLengths, + tgtLengths, + denominators, + alphas, + betas, + gradients, + H, + fusedLogSmax); +} + +// This is a __global__ wrapper around ComputeAlphas +// device kernel to enable unit testing +template +__global__ void ComputeAlphasWrapper( + int maxSrcLen, + int maxTgtLen, + int numTargets, + int blank, + const CAST_DTYPE* logProbs, + const int* srcLengths, + const int* tgtLengths, + int* alpha_counters, + volatile CAST_DTYPE* alphas, + int H = 1) { + ComputeAlphas( + maxSrcLen, + maxTgtLen, + numTargets, + blank, + logProbs, + srcLengths, + tgtLengths, + alpha_counters, + alphas, + H); +} + +// This is a __global__ wrapper around ComputeBetas +// device kernel to enable unit testing +template +__global__ void ComputeBetasWrapper( + int maxSrcLen, + int maxTgtLen, + int numTargets, + int blank, + const CAST_DTYPE* logProbs, + const int* srcLengths, + const int* tgtLengths, + int* betaCounters, + volatile CAST_DTYPE* betas, + DTYPE* costs, + int H = 1) { + ComputeBetasCosts( + maxSrcLen, + maxTgtLen, + numTargets, + blank, + logProbs, + srcLengths, + tgtLengths, + betaCounters, + betas, + costs, + H); +} + +// #undef LOG_PROBS_SKIP_IDX +// #undef LOG_PROBS_EMIT_IDX + +} // namespace rnnt +} // namespace torchaudio + +#endif // USE_CUDA diff --git a/torchaudio/csrc/rnnt/gpu/gpu_transducer.h b/torchaudio/csrc/rnnt/gpu/gpu_transducer.h new file mode 100644 index 0000000000..72759b39f4 --- /dev/null +++ b/torchaudio/csrc/rnnt/gpu/gpu_transducer.h @@ -0,0 +1,395 @@ +#pragma once + +#ifdef USE_CUDA + +#include +#include +#include + +namespace torchaudio { +namespace rnnt { +namespace gpu { + +#define gpuErrchk(ans) \ + { gpuAssert((ans), __FILE__, __LINE__); } + +inline void gpuAssert( + cudaError_t code, + const char* file, + int line, + bool abort = true) { + if (code != cudaSuccess) { + fprintf( + stderr, + "\nGPUassert: %s %s %d\n", + cudaGetErrorString(code), + file, + line); + if (abort) + exit(code); + } +} + +template +status_t LogSumExp2D( + cudaStream_t stream, + int N, + int D, + const DTYPE* logits, // [N, D] + CAST_DTYPE* outputs) { + { // compute max among D. + dim3 block_dims(N); + dim3 thread_dims(REDUCE_THREADS); + + ReduceMax2D + <<>>( + /*dim=*/D, + /*inputs=*/logits, + /*outputs=*/outputs); + + // BUGBUG: These error codes are only accurate when launching with + // blocking. Otherwise they usually reflect earlier errors. + if (cudaGetLastError() != cudaSuccess) { + return COMPUTE_DENOMINATOR_REDUCE_MAX_FAILED; + } + } + + { // compute log(sum(exp(d_i - max))) + dim3 block_dims(N); + dim3 thread_dims(REDUCE_THREADS); + + ReduceLogSumExpGivenMax2D + <<>>( + /*dim=*/D, + /*inputs=*/logits, + /*outputs=*/outputs); + + if (cudaGetLastError() != cudaSuccess) { + return COMPUTE_DENOMINATOR_REDUCE_SUM_FAILED; + } + } + + return SUCCESS; +} + +// Inputs: +// workspace: workspace. +// logits: pointer to (B, max_T, max_U, D) logits. +// targets: pointer to (B, max_U - 1) targets in the batch. +// srcLengths: pointer to (B, ) source lengths in the batch. +// tgtLengths: pointer to (B, ) target lengths in the batch. +// +// Outputs: +// costs: pointer to (B, ) costs in the batch. +// gradients: pointer to (B, max_T, max_U, D) gradients in the batch. +template +status_t Compute( + const Workspace& workspace, + const DTYPE* logits, + const int* targets, + const int* srcLengths, + const int* tgtLengths, + DTYPE* costs, + DTYPE* gradients = nullptr) { + const Options& options = workspace.GetOptions(); + + const cudaStream_t& stream = options.stream_; + const int& B = options.batchSize_; + const int& H = options.nHypos_; + const int& max_T = options.maxSrcLen_; + const int& max_U = options.maxTgtLen_; + const int& D = options.numTargets_; + const int& blank = options.blank_; + const CAST_DTYPE clamp = options.clamp_; + + const bool& fusedLogSmax = options.fusedLogSmax_; + + { // compute denominators. + status_t status = LogSumExp2D( + /*stream=*/stream, + /*N=*/B * H * max_T * max_U, + /*D=*/D, + /*logits=*/logits, + /*denominators=*/workspace.GetPointerToDenominators()); + + if (status != SUCCESS) { + return status; + } + } + + { // compute log probability pairs (blank and target). + int num_segments = + (max_T + MAX_THREADS_PER_BLOCK - 1) / MAX_THREADS_PER_BLOCK; + dim3 block_dims(num_segments, max_U, B * H); + dim3 thread_dims(MAX_THREADS_PER_BLOCK); + + ComputeLogProbs<<>>( + /*max_src_len=*/max_T, + /*max_tgt_len=*/max_U, + /*num_targets=*/D, + /*blank=*/blank, + /*logits=*/logits, + /*targets=*/targets, + /*srcLengths=*/srcLengths, + /*tgtLengths=*/tgtLengths, + /*denominators=*/workspace.GetPointerToDenominators(), + /*log_probs=*/workspace.GetPointerToLogProbs(), + H, + fusedLogSmax); + + if (cudaGetLastError() != cudaSuccess) { + return COMPUTE_LOG_PROBS_FAILED; + } + } + + { // compute alphas, betas and costs. + // warp is usually a group of threads (32) + int num_warps = (max_T + WARP_SIZE - 1) / WARP_SIZE; + + // each block is identified by 3 d tuple. + // we are using num_warp * max_U * B * H blocks + // where num_warp is division among Time axis + dim3 block_dims(num_warps, max_U, B * H); + + // each thread is identified by a 2 d tuple + // 2nd dim is 2. 1 for alpha, 1 for beta + dim3 thread_dims(WARP_SIZE, 2); + + ComputeAlphasBetasCosts + <<>>( + /*max_src_len=*/max_T, + /*max_tgt_len=*/max_U, + /*num_targets=*/D, + /*blank=*/blank, + /*log_probs=*/workspace.GetPointerToLogProbs(), + /*srcLengths=*/srcLengths, + /*tgtLengths=*/tgtLengths, + /*alpha_counters=*/workspace.GetPointerToAlphaCounters(), + /*alphas=*/workspace.GetPointerToAlphas(), + /*beta_counters=*/workspace.GetPointerToBetaCounters(), + /*betas=*/workspace.GetPointerToBetas(), + /*costs=*/costs, + /*warp_size=*/WARP_SIZE, + /*num_warps=*/num_warps, + H); + if (cudaGetLastError() != cudaSuccess) { + return COMPUTE_ALPHAS_BETAS_COSTS_FAILED; + } + } + + if (gradients != nullptr) { // compute gradients. + // don't set gradients to zero to here as gradients might reuse memory from + // logits + + int num_blocks = + (max_T + MAX_THREADS_PER_BLOCK - 1) / MAX_THREADS_PER_BLOCK; + dim3 block_dims(num_blocks, max_U, B * H); + dim3 thread_dims(MAX_THREADS_PER_BLOCK); + + ComputeGradients<<>>( + /*max_src_len=*/max_T, + /*max_tgt_len=*/max_U, + /*num_targets=*/D, + /*blank=*/blank, + /*clamp=*/clamp, + /*logits=*/logits, + /*targets=*/targets, + /*srcLengths=*/srcLengths, + /*tgtLengths=*/tgtLengths, + /*denominators=*/workspace.GetPointerToDenominators(), + /*alphas=*/workspace.GetPointerToAlphas(), + /*betas=*/workspace.GetPointerToBetas(), + /*gradients=*/gradients, + H, + fusedLogSmax); + if (cudaGetLastError() != cudaSuccess) { + return COMPUTE_GRADIENTS_FAILED; + } + } + + return SUCCESS; +} + +template +status_t ComputeAlphas( + const Workspace& workspace, + const DTYPE* logits, + const int* targets, + const int* srcLengths, + const int* tgtLengths, + DTYPE* alphas) { + const Options& options = workspace.GetOptions(); + + const cudaStream_t& stream = options.stream_; + const int& B = options.batchSize_; + const int& H = options.nHypos_; + const int& max_T = options.maxSrcLen_; + const int& max_U = options.maxTgtLen_; + const int& D = options.numTargets_; + const int& blank = options.blank_; + + { // compute denominators. + status_t status = LogSumExp2D( + /*stream=*/stream, + /*N=*/B * H * max_T * max_U, + /*D=*/D, + /*logits=*/logits, + /*denominators=*/workspace.GetPointerToDenominators()); + + if (status != SUCCESS) { + return status; + } + } + + { // compute log probability pairs (blank and target). + int num_segments = + (max_T + MAX_THREADS_PER_BLOCK - 1) / MAX_THREADS_PER_BLOCK; + dim3 block_dims(num_segments, max_U, B * H); + dim3 thread_dims(MAX_THREADS_PER_BLOCK); + + ComputeLogProbs<<>>( + /*max_src_len=*/max_T, + /*max_tgt_len=*/max_U, + /*num_targets=*/D, + /*blank=*/blank, + /*logits=*/logits, + /*targets=*/targets, + /*srcLengths=*/srcLengths, + /*tgtLengths=*/tgtLengths, + /*denominators=*/workspace.GetPointerToDenominators(), + /*log_probs=*/workspace.GetPointerToLogProbs(), + H); + + if (cudaGetLastError() != cudaSuccess) { + return COMPUTE_LOG_PROBS_FAILED; + } + } + { // compute alphas + // warp is usually a group of threads (32) + int num_warps = (max_T + WARP_SIZE - 1) / WARP_SIZE; + + // each block is identified by 3 d tuple. + // we are using num_warp * max_U * B blocks + // where num_warp is division among Time axis + dim3 block_dims(num_warps, max_U, B * H); + + // each thread is identified by a 2 d tuple + // 2nd dim is 1 for alpha only + dim3 thread_dims(WARP_SIZE, 1); + + ComputeAlphasWrapper + <<>>( + /*max_src_len=*/max_T, + /*max_tgt_len=*/max_U, + /*num_targets=*/D, + /*blank=*/blank, + /*log_probs=*/workspace.GetPointerToLogProbs(), + /*srcLengths=*/srcLengths, + /*tgtLengths=*/tgtLengths, + /*alpha_counters=*/workspace.GetPointerToAlphaCounters(), + /*alphas=*/(volatile DTYPE*)alphas, + H); + + if (cudaGetLastError() != cudaSuccess) { + return COMPUTE_ALPHAS_BETAS_COSTS_FAILED; + } + } + + return SUCCESS; +} + +template +status_t ComputeBetas( + const Workspace& workspace, + const DTYPE* logits, + const int* targets, + const int* srcLengths, + const int* tgtLengths, + DTYPE* costs, + DTYPE* betas) { + const Options& options = workspace.GetOptions(); + + const cudaStream_t& stream = options.stream_; + const int& B = options.batchSize_; + const int& H = options.nHypos_; + const int& max_T = options.maxSrcLen_; + const int& max_U = options.maxTgtLen_; + const int& D = options.numTargets_; + const int& blank = options.blank_; + + { // compute denominators. + status_t status = LogSumExp2D( + /*stream=*/stream, + /*N=*/B * H * max_T * max_U, + /*D=*/D, + /*logits=*/logits, + /*denominators=*/workspace.GetPointerToDenominators()); + + if (status != SUCCESS) { + return status; + } + } + + { // compute log probability pairs (blank and target). + int num_segments = + (max_T + MAX_THREADS_PER_BLOCK - 1) / MAX_THREADS_PER_BLOCK; + dim3 block_dims(num_segments, max_U, B * H); + dim3 thread_dims(MAX_THREADS_PER_BLOCK); + + ComputeLogProbs<<>>( + /*max_src_len=*/max_T, + /*max_tgt_len=*/max_U, + /*num_targets=*/D, + /*blank=*/blank, + /*logits=*/logits, + /*targets=*/targets, + /*srcLengths=*/srcLengths, + /*tgtLengths=*/tgtLengths, + /*denominators=*/workspace.GetPointerToDenominators(), + /*log_probs=*/workspace.GetPointerToLogProbs(), + H); + + if (cudaGetLastError() != cudaSuccess) { + return COMPUTE_LOG_PROBS_FAILED; + } + } + { // compute betas + // warp is usually a group of threads (32) + int num_warps = (max_T + WARP_SIZE - 1) / WARP_SIZE; + + // each block is identified by 3 d tuple. + // we are using num_warp * max_U * B blocks + // where num_warp is division among Time axis + dim3 block_dims(num_warps, max_U, B * H); + + // each thread is identified by a 2 d tuple + // 2nd dim is 1 for betas only + dim3 thread_dims(WARP_SIZE, 1); + + ComputeBetasWrapper + <<>>( + /*max_src_len=*/max_T, + /*max_tgt_len=*/max_U, + /*num_targets=*/D, + /*blank=*/blank, + /*log_probs=*/workspace.GetPointerToLogProbs(), + /*srcLengths=*/srcLengths, + /*tgtLengths=*/tgtLengths, + /*alpha_counters=*/workspace.GetPointerToBetaCounters(), + /*alphas=*/(volatile DTYPE*)betas, + costs, + H); + + if (cudaGetLastError() != cudaSuccess) { + return COMPUTE_ALPHAS_BETAS_COSTS_FAILED; + } + } + + return SUCCESS; +} + +} // namespace gpu +} // namespace rnnt +} // namespace torchaudio + +#endif // USE_CUDA diff --git a/torchaudio/csrc/rnnt/gpu/half.cuh b/torchaudio/csrc/rnnt/gpu/half.cuh new file mode 100644 index 0000000000..72a2f37e04 --- /dev/null +++ b/torchaudio/csrc/rnnt/gpu/half.cuh @@ -0,0 +1,38 @@ +#pragma once + +#ifdef USE_C10_HALF +#include "c10/util/Half.h" +#endif // USE_C10_HALF + +#include + +namespace torchaudio { +namespace rnnt { + +struct alignas(sizeof(__half)) Half { + __half x; + + HOST_AND_DEVICE Half() = default; + + FORCE_INLINE HOST_AND_DEVICE Half(float f) { + x = __float2half_rn(f); + if (isinf(__half2float(x))) { + x = __float2half_rz(f); // round toward 0. + } + } + + FORCE_INLINE HOST_AND_DEVICE operator float() const { + return __half2float(x); + } + + FORCE_INLINE HOST_AND_DEVICE Half(__half f) { + x = f; + } + + FORCE_INLINE HOST_AND_DEVICE operator __half() const { + return x; + } +}; + +} // namespace rnnt +} // namespace torchaudio diff --git a/torchaudio/csrc/rnnt/gpu/kernel_utils.h b/torchaudio/csrc/rnnt/gpu/kernel_utils.h new file mode 100644 index 0000000000..3b2989b073 --- /dev/null +++ b/torchaudio/csrc/rnnt/gpu/kernel_utils.h @@ -0,0 +1,66 @@ +#pragma once + +#include + +#include + +namespace torchaudio { +namespace rnnt { + +inline HOST_AND_DEVICE bool in_range( + int start, + int end, // inclusive + int val) { + return start <= val && val <= end; +} + +#define LOG_PROBS_SKIP_IDX 0 +#define LOG_PROBS_EMIT_IDX 1 + +struct Indexer2D { + const int& size2_; + + FORCE_INLINE HOST_AND_DEVICE Indexer2D(const int& size2) : size2_(size2) {} + + FORCE_INLINE HOST_AND_DEVICE int operator()(int index1, int index2) { + return index1 * size2_ + index2; + } +}; + +struct Indexer3D { + const int& size2_; + const int& size3_; + + FORCE_INLINE HOST_AND_DEVICE Indexer3D(const int& size2, const int& size3) + : size2_(size2), size3_(size3) {} + + FORCE_INLINE HOST_AND_DEVICE int operator()( + int index1, + int index2, + int index3) { + return (index1 * size2_ + index2) * size3_ + index3; + } +}; + +struct Indexer4D { + const int& size2_; + const int& size3_; + const int& size4_; + + HOST_AND_DEVICE Indexer4D( + const int& size2, + const int& size3, + const int& size4) + : size2_(size2), size3_(size3), size4_(size4) {} + + HOST_AND_DEVICE int operator()( + int index1, + int index2, + int index3, + int index4) { + return ((index1 * size2_ + index2) * size3_ + index3) * size4_ + index4; + } +}; + +} // namespace rnnt +} // namespace torchaudio diff --git a/torchaudio/csrc/rnnt/gpu/kernels.h b/torchaudio/csrc/rnnt/gpu/kernels.h new file mode 100644 index 0000000000..db8bb5092b --- /dev/null +++ b/torchaudio/csrc/rnnt/gpu/kernels.h @@ -0,0 +1,131 @@ +#pragma once + +#include + +#include +#include + +namespace torchaudio { +namespace rnnt { + +template +HOST_AND_DEVICE void ComputeGradientsElement( + int bTgt, + int t, + int u, + int maxSrcLen, + int maxTgtLen, + int numTargets, + int blank, + CAST_DTYPE clamp, + const DTYPE* logits, + const int* targets, + const int* srcLengths, + const int* tgtLengths, + const CAST_DTYPE* denominators, + const CAST_DTYPE* alphas, + const CAST_DTYPE* betas, + DTYPE* gradients, + int H = 1, + bool fusedLogSmax = true) { + const int& maxT = maxSrcLen; + const int& maxU = maxTgtLen; + const int& D = numTargets; + + const int bSrc = bTgt / H; + const int T = srcLengths[bSrc]; + const int U = tgtLengths[bTgt] + 1; + + if (t >= T || u >= U) { // out of boundary. + if (gradients == logits && t < maxT && u < maxU) { + // gradients and logits are pointing to the same memory location + Indexer3D idxr3(maxT, maxU); + int idx_b_t_u_zero = idxr3(bTgt, t, u); + if (idx_b_t_u_zero != -1) { + int start = idx_b_t_u_zero * D; + for (int b_t_u_d = start; b_t_u_d < start + D; ++b_t_u_d) { + gradients[b_t_u_d] = 0; + } + } + } + return; + } + + int costIdx = bTgt * maxT * maxU; + CAST_DTYPE cost = -(betas[costIdx]); + + Indexer2D idxr2(maxU - 1); + + int idx_b_t_u, idx_b_t_up1, idx_b_tp1_u; + Indexer3D idxr3(maxT, maxU); + idx_b_t_u = idxr3(bTgt, t, u); + idx_b_t_up1 = idxr3(bTgt, t, u + 1); + idx_b_tp1_u = idxr3(bTgt, t + 1, u); + + if (idx_b_t_u == -1) { + return; + } + + if (isinf(cost) || isnan(cost)) { + for (int d = 0; d < D; ++d) { + int b_t_u_d = idx_b_t_u * D + d; + gradients[b_t_u_d] = 0; + } + return; + } + + CAST_DTYPE c = alphas[idx_b_t_u] + cost - denominators[idx_b_t_u]; + for (int d = 0; d < D; ++d) { + int b_t_u_d = idx_b_t_u * D + d; + CAST_DTYPE g = CAST_DTYPE(logits[b_t_u_d]) + c; + + if (fusedLogSmax) { + if (d == blank && t == T - 1 && u == U - 1) { // last blank transition. + gradients[b_t_u_d] = std::exp(g + betas[idx_b_t_u]) - std::exp(g); + } else if (t < T - 1 && d == blank) { + gradients[b_t_u_d] = std::exp(g + betas[idx_b_t_u]); + if (idx_b_tp1_u != -1) { + gradients[b_t_u_d] = + gradients[b_t_u_d] - std::exp(g + betas[idx_b_tp1_u]); + } + } else if (u < U - 1 && d == targets[idxr2(bTgt, u)]) { + gradients[b_t_u_d] = std::exp(g + betas[idx_b_t_u]); + if (idx_b_t_up1 != -1) { + gradients[b_t_u_d] = + gradients[b_t_u_d] - std::exp(g + betas[idx_b_t_up1]); + } + } else { + gradients[b_t_u_d] = std::exp(g + betas[idx_b_t_u]); + } + } else { // Non fused log softmax case + CAST_DTYPE g = cost + CAST_DTYPE(logits[b_t_u_d]); + if (d == blank && t == T - 1 && u == U - 1) { + gradients[b_t_u_d] = g + alphas[idx_b_t_u]; + } else if (t < T - 1 && d == blank) { + if (idx_b_tp1_u != -1) { + gradients[b_t_u_d] = g + alphas[idx_b_t_u] + betas[idx_b_tp1_u]; + } else { + gradients[b_t_u_d] = g + CAST_DTYPE(-INFINITY); + } + } else if (u < U - 1 && d == targets[idxr2(bTgt, u)]) { + if (idx_b_t_up1 != -1) { + gradients[b_t_u_d] = g + alphas[idx_b_t_u] + betas[idx_b_t_up1]; + } else { + gradients[b_t_u_d] = g + CAST_DTYPE(-INFINITY); + } + } else { + gradients[b_t_u_d] = g + CAST_DTYPE(-INFINITY); + } + gradients[b_t_u_d] = -std::exp(gradients[b_t_u_d]); + } + + if (clamp > 0) { + auto g = CAST_DTYPE(gradients[b_t_u_d]); + gradients[b_t_u_d] = math::min(g, clamp); + gradients[b_t_u_d] = math::max(g, -clamp); + } + } +} + +} // namespace rnnt +} // namespace torchaudio diff --git a/torchaudio/csrc/rnnt/gpu/math.cuh b/torchaudio/csrc/rnnt/gpu/math.cuh new file mode 100644 index 0000000000..643fa98300 --- /dev/null +++ b/torchaudio/csrc/rnnt/gpu/math.cuh @@ -0,0 +1,48 @@ +#pragma once + +#ifdef USE_CUDA + +#include + +#endif // USE_CUDA + +#include + +namespace torchaudio { +namespace rnnt { + +namespace math { + +template +FORCE_INLINE HOST_AND_DEVICE DTYPE max(DTYPE x, DTYPE y) { + if (x > y) + return x; + else + return y; +} + +template +FORCE_INLINE HOST_AND_DEVICE DTYPE min(DTYPE x, DTYPE y) { + if (x > y) + return y; + else + return x; +} + +// log_sum_exp +template +FORCE_INLINE HOST_AND_DEVICE DTYPE lse(DTYPE x, DTYPE y); + +template <> +FORCE_INLINE HOST_AND_DEVICE float lse(float x, float y) { + if (y > x) { + return y + log1pf(expf(x - y)); + } else { + return x + log1pf(expf(y - x)); + } +} + +} // namespace math + +} // namespace rnnt +} // namespace torchaudio diff --git a/torchaudio/csrc/rnnt/macros.cpp b/torchaudio/csrc/rnnt/macros.cpp index da6e5045bc..d2ea30a69b 100644 --- a/torchaudio/csrc/rnnt/macros.cpp +++ b/torchaudio/csrc/rnnt/macros.cpp @@ -1,8 +1,5 @@ #include -#ifdef USE_GLOG -#else - const char* ToString(level_t level) { switch (level) { case INFO: @@ -17,5 +14,3 @@ const char* ToString(level_t level) { return "UNKNOWN"; } } - -#endif // USE_GLOG diff --git a/torchaudio/csrc/rnnt/macros.h b/torchaudio/csrc/rnnt/macros.h index 84a8db24f0..abcbc39966 100644 --- a/torchaudio/csrc/rnnt/macros.h +++ b/torchaudio/csrc/rnnt/macros.h @@ -13,35 +13,9 @@ #define FORCE_INLINE inline #endif // USE_CUDA -#ifdef USE_GLOG -#include -#else #include #include typedef enum { INFO = 0, WARNING = 1, ERROR = 2, FATAL = 3 } level_t; const char* ToString(level_t level); - -struct LOG { - LOG(const level_t& level) { - ::std::cerr << "LOG(" << ToString(level) << "): "; - } - ~LOG() { - ::std::cerr << ::std::endl; - } -}; - -template -LOG&& operator<<(LOG&& log, const T& object) { - ::std::cerr << object; - return ::std::move(log); -} - -#define DCHECK(x) -#define DCHECK_EQ(x, y) -#define DCHECK_NE(x, y) -#define CHECK(x) -#define CHECK_EQ(x, y) -#define CHECK_NE(x, y) -#endif // USE_GLOG diff --git a/torchaudio/csrc/rnnt/transducer.h b/torchaudio/csrc/rnnt/transducer.h index 82b84ce0ea..0553616114 100644 --- a/torchaudio/csrc/rnnt/transducer.h +++ b/torchaudio/csrc/rnnt/transducer.h @@ -39,8 +39,6 @@ status_t Compute( return status; } default: { - LOG(ERROR) << "unsupported workspace.GetOptions().device = " - << workspace.GetOptions().device_; return FAILURE; } }; @@ -76,8 +74,6 @@ status_t ComputeAlphas( return status; } default: { - LOG(ERROR) << "unsupported workspace.GetOptions().device = " - << workspace.GetOptions().device_; return FAILURE; } }; @@ -116,8 +112,6 @@ status_t ComputeBetas( return status; } default: { - LOG(ERROR) << "unsupported workspace.GetOptions().device = " - << workspace.GetOptions().device_; return FAILURE; } }; diff --git a/torchaudio/csrc/rnnt/workspace.cpp b/torchaudio/csrc/rnnt/workspace.cpp deleted file mode 100644 index 2c8d0f6ab1..0000000000 --- a/torchaudio/csrc/rnnt/workspace.cpp +++ /dev/null @@ -1,20 +0,0 @@ -#include - -namespace torchaudio { -namespace rnnt { - -void IntWorkspace::ResetAlphaBetaCounters() { - if (data_ != nullptr && options_.device_ == GPU) { - cudaMemset( - GetPointerToAlphaCounters(), - 0, - ComputeSizeForAlphaCounters(options_) * sizeof(int)); - cudaMemset( - GetPointerToBetaCounters(), - 0, - ComputeSizeForBetaCounters(options_) * sizeof(int)); - } -} - -} // namespace rnnt -} // namespace torchaudio diff --git a/torchaudio/csrc/rnnt/workspace.h b/torchaudio/csrc/rnnt/workspace.h index 95a1fcf0c4..31b57647af 100644 --- a/torchaudio/csrc/rnnt/workspace.h +++ b/torchaudio/csrc/rnnt/workspace.h @@ -98,7 +98,7 @@ class IntWorkspace { void Reset(const Options& options, int* data, int size) { int needed_size = ComputeSizeFromOptions(options); - //CHECK_LE(needed_size, size); + CHECK_LE(needed_size, size); options_ = options; data_ = data; size_ = size; @@ -118,7 +118,20 @@ class IntWorkspace { } private: - void ResetAlphaBetaCounters(); + inline void ResetAlphaBetaCounters() { +#ifdef USE_CUDA + if (data_ != nullptr && options_.device_ == GPU) { + cudaMemset( + GetPointerToAlphaCounters(), + 0, + ComputeSizeForAlphaCounters(options_) * sizeof(int)); + cudaMemset( + GetPointerToBetaCounters(), + 0, + ComputeSizeForBetaCounters(options_) * sizeof(int)); + } +#endif // USE_CUDA + } static int ComputeSizeForAlphaCounters(const Options& options) { // B * U #ifdef USE_CUDA diff --git a/torchaudio/functional/functional.py b/torchaudio/functional/functional.py index cef2553d82..b7d9b112b8 100644 --- a/torchaudio/functional/functional.py +++ b/torchaudio/functional/functional.py @@ -578,6 +578,12 @@ def angle( return torch.atan2(complex_tensor[..., 1], complex_tensor[..., 0]) +@_mod_utils.deprecated( + "Please convert the input Tensor to complex type with `torch.view_as_complex` then " + "use `torch.abs` and `torch.angle`. " + "Please refer to https://github.com/pytorch/audio/issues/1337 " + "for more details about torchaudio's plan to migrate to native complex type." +) def magphase( complex_tensor: Tensor, power: float = 1.0 @@ -746,7 +752,7 @@ def mask_along_axis_iid( # Per batch example masking specgrams = specgrams.transpose(axis, -1) - specgrams.masked_fill_((mask >= mask_start) & (mask < mask_end), mask_value) + specgrams = specgrams.masked_fill((mask >= mask_start) & (mask < mask_end), mask_value) specgrams = specgrams.transpose(axis, -1) return specgrams @@ -772,24 +778,25 @@ def mask_along_axis( Returns: Tensor: Masked spectrogram of dimensions (channel, freq, time) """ + if axis != 1 and axis != 2: + raise ValueError('Only Frequency and Time masking are supported') # pack batch shape = specgram.size() specgram = specgram.reshape([-1] + list(shape[-2:])) - value = torch.rand(1) * mask_param min_value = torch.rand(1) * (specgram.size(axis) - value) mask_start = (min_value.long()).squeeze() mask_end = (min_value.long() + value.long()).squeeze() + mask = torch.arange(0, specgram.shape[axis], device=specgram.device, dtype=specgram.dtype) + mask = (mask >= mask_start) & (mask < mask_end) + if axis == 1: + mask = mask.unsqueeze(-1) assert mask_end - mask_start < mask_param - if axis == 1: - specgram[:, mask_start:mask_end] = mask_value - elif axis == 2: - specgram[:, :, mask_start:mask_end] = mask_value - else: - raise ValueError('Only Frequency and Time masking are supported') + + specgram = specgram.masked_fill(mask, mask_value) # unpack batch specgram = specgram.reshape(shape[:-2] + specgram.shape[-2:]) diff --git a/torchaudio/prototype/rnnt_loss.py b/torchaudio/prototype/rnnt_loss.py index 1da03bfb2a..08c96ab0f2 100644 --- a/torchaudio/prototype/rnnt_loss.py +++ b/torchaudio/prototype/rnnt_loss.py @@ -80,7 +80,6 @@ def forward( target_lengths, blank=-1, clamp=-1, - runtime_check=False, fused_log_softmax=True, reuse_logits_for_grads=True, ): @@ -101,15 +100,6 @@ def forward( if blank < 0: # reinterpret blank index if blank < 0. blank = logits.shape[-1] + blank - if runtime_check: - check_inputs( - logits=logits, - targets=targets, - logit_lengths=logit_lengths, - target_lengths=target_lengths, - blank=blank, - ) - costs, gradients = torch.ops.torchaudio.rnnt_loss( logits=logits, targets=targets, @@ -137,7 +127,6 @@ def backward(ctx, output_gradients): None, # target_lengths None, # blank None, # clamp - None, # runtime_check None, # fused_log_softmax None, # reuse_logits_for_grads ) @@ -150,7 +139,6 @@ def rnnt_loss( target_lengths, blank=-1, clamp=-1, - runtime_check=False, fused_log_softmax=True, reuse_logits_for_grads=True, ): @@ -169,7 +157,7 @@ def rnnt_loss( blank (int, opt): blank label (Default: ``-1``) clamp (float): clamp for gradients (Default: ``-1``) runtime_check (bool): whether to do sanity check during runtime. (Default: ``False``) - fused_log_smax (bool): set to False if calling log_softmax outside loss (Default: ``True``) + fused_log_softmax (bool): set to False if calling log_softmax outside loss (Default: ``True``) reuse_logits_for_grads (bool): whether to save memory by reusing logits memory for grads (Default: ``True``) """ if not fused_log_softmax: @@ -185,7 +173,6 @@ def rnnt_loss( target_lengths, blank, clamp, - runtime_check, fused_log_softmax, reuse_logits_for_grads, ) @@ -203,8 +190,7 @@ class RNNTLoss(torch.nn.Module): Args: blank (int, opt): blank label (Default: ``-1``) clamp (float): clamp for gradients (Default: ``-1``) - runtime_check (bool): whether to do sanity check during runtime. (Default: ``False``) - fused_log_smax (bool): set to False if calling log_softmax outside loss (Default: ``True``) + fused_log_softmax (bool): set to False if calling log_softmax outside loss (Default: ``True``) reuse_logits_for_grads (bool): whether to save memory by reusing logits memory for grads (Default: ``True``) """ @@ -212,14 +198,12 @@ def __init__( self, blank=-1, clamp=-1, - runtime_check=False, fused_log_softmax=True, reuse_logits_for_grads=True, ): super().__init__() self.blank = blank self.clamp = clamp - self.runtime_check = runtime_check self.fused_log_softmax = fused_log_softmax self.reuse_logits_for_grads = reuse_logits_for_grads @@ -244,94 +228,6 @@ def forward( target_lengths, self.blank, self.clamp, - self.runtime_check, self.fused_log_softmax, self.reuse_logits_for_grads, ) - - -def check_type(var, t, name): - if var.dtype is not t: - raise TypeError("{} must be {}".format(name, t)) - - -def check_contiguous(var, name): - if not var.is_contiguous(): - raise ValueError("{} must be contiguous".format(name)) - - -def check_dim(var, dim, name): - if len(var.shape) != dim: - raise ValueError("{} must be {}D".format(name, dim)) - - -def check_equal(var1, name1, var2, name2): - if var1 != var2: - raise ValueError( - "`{}` ({}) must equal to ".format(name1, var1) - + "`{}` ({})".format(name2, var2) - ) - - -def check_device(var1, name1, var2, name2): - if var1.device != var2.device: - raise ValueError( - "`{}` ({}) must be on the same ".format(name1, var1.device.type) - + "device as `{}` ({})".format(name2, var2.device.type) - ) - - -def check_inputs(logits, targets, logit_lengths, target_lengths, blank): - check_device(logits, "logits", targets, "targets") - check_device(logits, "logits", targets, "logit_lengths") - check_device(logits, "logits", targets, "target_lengths") - - check_type(logits, torch.float32, "logits") - check_type(targets, torch.int32, "targets") - check_type(logit_lengths, torch.int32, "logit_lengths") - check_type(target_lengths, torch.int32, "target_lengths") - - check_contiguous(logits, "logits") - check_contiguous(targets, "targets") - check_contiguous(target_lengths, "target_lengths") - check_contiguous(logit_lengths, "logit_lengths") - - check_dim(logits, 4, "logits") - check_dim(targets, 2, "targets") - check_dim(logit_lengths, 1, "logit_lengths") - check_dim(target_lengths, 1, "target_lengths") - - check_equal( - logit_lengths.shape[0], "logit_lengths.shape[0]", logits.shape[0], "logits.shape[0]" - ) - check_equal( - target_lengths.shape[0], "target_lengths.shape[0]", logits.shape[0], "logits.shape[0]" - ) - check_equal( - targets.shape[0], "targets.shape[0]", logits.shape[0], "logits.shape[0]" - ) - check_equal( - targets.shape[1], - "targets.shape[1]", - torch.max(target_lengths), - "torch.max(target_lengths)", - ) - check_equal( - logits.shape[1], - "logits.shape[1]", - torch.max(logit_lengths), - "torch.max(logit_lengths)", - ) - check_equal( - logits.shape[2], - "logits.shape[2]", - torch.max(target_lengths) + 1, - "torch.max(target_lengths) + 1", - ) - - if blank < 0 or blank >= logits.shape[-1]: - raise ValueError( - "blank ({}) must be within [0, logits.shape[-1]={})".format( - blank, logits.shape[-1] - ) - ) diff --git a/torchaudio/transforms.py b/torchaudio/transforms.py index a04592f2c4..fa38118043 100644 --- a/torchaudio/transforms.py +++ b/torchaudio/transforms.py @@ -1,6 +1,7 @@ # -*- coding: utf-8 -*- import math +import warnings from typing import Callable, Optional import torch @@ -673,6 +674,14 @@ class ComplexNorm(torch.nn.Module): __constants__ = ['power'] def __init__(self, power: float = 1.0) -> None: + warnings.warn( + 'torchaudio.transforms.ComplexNorm has been deprecated ' + 'and will be removed from future release.' + 'Please convert the input Tensor to complex type with `torch.view_as_complex` then ' + 'use `torch.abs` and `torch.angle`. ' + 'Please refer to https://github.com/pytorch/audio/issues/1337 ' + "for more details about torchaudio's plan to migrate to native complex type." + ) super(ComplexNorm, self).__init__() self.power = power From 81db19be529233ab7a91daa4c664089fbb654973 Mon Sep 17 00:00:00 2001 From: Parmeet Singh Bhatia Date: Fri, 21 May 2021 16:54:14 -0700 Subject: [PATCH 49/73] Import torchaudio #1513 08f2bde Summary: Import from github Reviewed By: mthrok Differential Revision: D28606124 fbshipit-source-id: 05dcb07efc5537d928bec682a68e6ccee7cc325e --- .github/workflows/codeql.yml | 10 +- docs/source/models.rst | 8 + .../common_utils/case_utils.py | 5 +- .../compliance_kaldi_test.py | 43 +++-- .../functional/functional_impl.py | 21 ++- .../torchscript_consistency_impl.py | 22 +++ test/torchaudio_unittest/models_test.py | 19 +- .../rnnt/torchscript_consistency_cpu_test.py | 10 + .../rnnt/torchscript_consistency_cuda_test.py | 11 ++ .../rnnt/torchscript_consistency_impl.py | 70 +++++++ test/torchaudio_unittest/rnnt/utils.py | 8 +- .../transforms/autograd_test_impl.py | 25 +++ .../transforms/sox_compatibility_test.py | 25 +++ .../torchscript_consistency_impl.py | 4 + .../transforms/transforms_test.py | 6 +- .../transforms/transforms_test_impl.py | 20 +- torchaudio/compliance/kaldi.py | 11 +- torchaudio/csrc/CMakeLists.txt | 1 + torchaudio/csrc/rnnt/autograd.cpp | 74 ++++++++ torchaudio/csrc/rnnt/compute.cpp | 24 +++ torchaudio/csrc/rnnt/compute.h | 13 ++ torchaudio/csrc/rnnt/transducer.h | 121 ------------ torchaudio/functional/filtering.py | 15 +- torchaudio/functional/functional.py | 129 +++++++++---- torchaudio/models/__init__.py | 2 + torchaudio/models/deepspeech.py | 92 +++++++++ torchaudio/prototype/rnnt_loss.py | 176 +++--------------- torchaudio/transforms.py | 69 ++++++- 28 files changed, 682 insertions(+), 352 deletions(-) create mode 100644 test/torchaudio_unittest/rnnt/torchscript_consistency_cpu_test.py create mode 100644 test/torchaudio_unittest/rnnt/torchscript_consistency_cuda_test.py create mode 100644 test/torchaudio_unittest/rnnt/torchscript_consistency_impl.py create mode 100644 torchaudio/csrc/rnnt/autograd.cpp create mode 100644 torchaudio/csrc/rnnt/compute.h delete mode 100644 torchaudio/csrc/rnnt/transducer.h create mode 100644 torchaudio/models/deepspeech.py diff --git a/.github/workflows/codeql.yml b/.github/workflows/codeql.yml index f0ea58f309..7d38c2c0e2 100644 --- a/.github/workflows/codeql.yml +++ b/.github/workflows/codeql.yml @@ -20,19 +20,13 @@ jobs: with: languages: python, cpp - - name: Install Ninja - run: | - sudo apt-get update -y - sudo apt-get install -y ninja-build - - name: Update submodules run: git submodule update --init --recursive - name: Install Torch run: | - python -m pip install cmake - python -m pip install torch==1.8.1+cpu -f https://download.pytorch.org/whl/torch_stable.html - sudo ln -s /usr/bin/ninja /usr/bin/ninja-build + python -m pip install cmake ninja + python -m pip install --pre torch -f https://download.pytorch.org/whl/nightly/cpu/torch_nightly.html - name: Build TorchAudio run: BUILD_SOX=1 USE_CUDA=0 python setup.py develop --user diff --git a/docs/source/models.rst b/docs/source/models.rst index ea86d8b73b..2030eefd28 100644 --- a/docs/source/models.rst +++ b/docs/source/models.rst @@ -17,6 +17,14 @@ The models subpackage contains definitions of models for addressing common audio .. automethod:: forward +:hidden:`DeepSpeech` +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +.. autoclass:: DeepSpeech + + .. automethod:: forward + + :hidden:`Wav2Letter` ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ diff --git a/test/torchaudio_unittest/common_utils/case_utils.py b/test/torchaudio_unittest/common_utils/case_utils.py index 773f1915b9..fa3d5077bb 100644 --- a/test/torchaudio_unittest/common_utils/case_utils.py +++ b/test/torchaudio_unittest/common_utils/case_utils.py @@ -59,8 +59,9 @@ def setUpClass(cls): super().setUpClass() cls._proc = subprocess.Popen( ['python', '-m', 'http.server', f'{cls._port}'], - cwd=cls.get_base_temp_dir()) - time.sleep(1.0) + cwd=cls.get_base_temp_dir(), + stderr=subprocess.DEVNULL) # Disable server-side error log because it is confusing + time.sleep(2.0) @classmethod def tearDownClass(cls): diff --git a/test/torchaudio_unittest/compliance_kaldi_test.py b/test/torchaudio_unittest/compliance_kaldi_test.py index 17d73fbf2f..af093cea55 100644 --- a/test/torchaudio_unittest/compliance_kaldi_test.py +++ b/test/torchaudio_unittest/compliance_kaldi_test.py @@ -7,6 +7,7 @@ from torchaudio_unittest import common_utils from .compliance import utils as compliance_utils +from parameterized import parameterized def extract_window(window, wave, f, frame_length, frame_shift, snip_edges): @@ -182,20 +183,26 @@ def get_output_fn(sound, args): self._compliance_test_helper(self.test2_filepath, 'resample', 32, 3, get_output_fn, atol=1e-2, rtol=1e-5) - def test_resample_waveform_upsample_size(self): - upsample_sound = kaldi.resample_waveform(self.test1_signal, self.test1_signal_sr, self.test1_signal_sr * 2) + @parameterized.expand([("sinc_interpolation"), ("kaiser_window")]) + def test_resample_waveform_upsample_size(self, resampling_method): + upsample_sound = kaldi.resample_waveform(self.test1_signal, self.test1_signal_sr, self.test1_signal_sr * 2, + resampling_method=resampling_method) self.assertTrue(upsample_sound.size(-1) == self.test1_signal.size(-1) * 2) - def test_resample_waveform_downsample_size(self): - downsample_sound = kaldi.resample_waveform(self.test1_signal, self.test1_signal_sr, self.test1_signal_sr // 2) + @parameterized.expand([("sinc_interpolation"), ("kaiser_window")]) + def test_resample_waveform_downsample_size(self, resampling_method): + downsample_sound = kaldi.resample_waveform(self.test1_signal, self.test1_signal_sr, self.test1_signal_sr // 2, + resampling_method=resampling_method) self.assertTrue(downsample_sound.size(-1) == self.test1_signal.size(-1) // 2) - def test_resample_waveform_identity_size(self): - downsample_sound = kaldi.resample_waveform(self.test1_signal, self.test1_signal_sr, self.test1_signal_sr) + @parameterized.expand([("sinc_interpolation"), ("kaiser_window")]) + def test_resample_waveform_identity_size(self, resampling_method): + downsample_sound = kaldi.resample_waveform(self.test1_signal, self.test1_signal_sr, self.test1_signal_sr, + resampling_method=resampling_method) self.assertTrue(downsample_sound.size(-1) == self.test1_signal.size(-1)) def _test_resample_waveform_accuracy(self, up_scale_factor=None, down_scale_factor=None, - atol=1e-1, rtol=1e-4): + resampling_method="sinc_interpolation", atol=1e-1, rtol=1e-4): # resample the signal and compare it to the ground truth n_to_trim = 20 sample_rate = 1000 @@ -211,7 +218,8 @@ def _test_resample_waveform_accuracy(self, up_scale_factor=None, down_scale_fact original_timestamps = torch.arange(0, duration, 1.0 / sample_rate) sound = 123 * torch.cos(2 * math.pi * 3 * original_timestamps).unsqueeze(0) - estimate = kaldi.resample_waveform(sound, sample_rate, new_sample_rate).squeeze() + estimate = kaldi.resample_waveform(sound, sample_rate, new_sample_rate, + resampling_method=resampling_method).squeeze() new_timestamps = torch.arange(0, duration, 1.0 / new_sample_rate)[:estimate.size(0)] ground_truth = 123 * torch.cos(2 * math.pi * 3 * new_timestamps) @@ -222,15 +230,18 @@ def _test_resample_waveform_accuracy(self, up_scale_factor=None, down_scale_fact self.assertEqual(estimate, ground_truth, atol=atol, rtol=rtol) - def test_resample_waveform_downsample_accuracy(self): + @parameterized.expand([("sinc_interpolation"), ("kaiser_window")]) + def test_resample_waveform_downsample_accuracy(self, resampling_method): for i in range(1, 20): - self._test_resample_waveform_accuracy(down_scale_factor=i * 2) + self._test_resample_waveform_accuracy(down_scale_factor=i * 2, resampling_method=resampling_method) - def test_resample_waveform_upsample_accuracy(self): + @parameterized.expand([("sinc_interpolation"), ("kaiser_window")]) + def test_resample_waveform_upsample_accuracy(self, resampling_method): for i in range(1, 20): - self._test_resample_waveform_accuracy(up_scale_factor=1.0 + i / 20.0) + self._test_resample_waveform_accuracy(up_scale_factor=1.0 + i / 20.0, resampling_method=resampling_method) - def test_resample_waveform_multi_channel(self): + @parameterized.expand([("sinc_interpolation"), ("kaiser_window")]) + def test_resample_waveform_multi_channel(self, resampling_method): num_channels = 3 multi_sound = self.test1_signal.repeat(num_channels, 1) # (num_channels, 8000 smp) @@ -238,11 +249,13 @@ def test_resample_waveform_multi_channel(self): for i in range(num_channels): multi_sound[i, :] *= (i + 1) * 1.5 - multi_sound_sampled = kaldi.resample_waveform(multi_sound, self.test1_signal_sr, self.test1_signal_sr // 2) + multi_sound_sampled = kaldi.resample_waveform(multi_sound, self.test1_signal_sr, self.test1_signal_sr // 2, + resampling_method=resampling_method) # check that sampling is same whether using separately or in a tensor of size (c, n) for i in range(num_channels): single_channel = self.test1_signal * (i + 1) * 1.5 single_channel_sampled = kaldi.resample_waveform(single_channel, self.test1_signal_sr, - self.test1_signal_sr // 2) + self.test1_signal_sr // 2, + resampling_method=resampling_method) self.assertEqual(multi_sound_sampled[i, :], single_channel_sampled[0], rtol=1e-4, atol=1e-7) diff --git a/test/torchaudio_unittest/functional/functional_impl.py b/test/torchaudio_unittest/functional/functional_impl.py index 424ead2ca9..1a2026233d 100644 --- a/test/torchaudio_unittest/functional/functional_impl.py +++ b/test/torchaudio_unittest/functional/functional_impl.py @@ -9,7 +9,7 @@ from parameterized import parameterized from scipy import signal -from torchaudio_unittest.common_utils import TestBaseMixin, get_sinusoid, nested_params +from torchaudio_unittest.common_utils import TestBaseMixin, get_sinusoid, nested_params, get_whitenoise class Functional(TestBaseMixin): @@ -259,6 +259,25 @@ def test_mask_along_axis_iid_preserve(self, mask_param, mask_value, axis): self.assertEqual(specgrams, specgrams_copy) + def test_resample_no_warning(self): + sample_rate = 44100 + waveform = get_whitenoise(sample_rate=sample_rate, duration=0.1) + + with warnings.catch_warnings(record=True) as w: + warnings.simplefilter("always") + F.resample(waveform, float(sample_rate), sample_rate / 2.) + assert len(w) == 0 + + def test_resample_warning(self): + """resample should throw a warning if an input frequency is not of an integer value""" + sample_rate = 44100 + waveform = get_whitenoise(sample_rate=sample_rate, duration=0.1) + + with warnings.catch_warnings(record=True) as w: + warnings.simplefilter("always") + F.resample(waveform, sample_rate, 5512.5) + assert len(w) == 1 + @nested_params( [0.5, 1.01, 1.3], [True, False], diff --git a/test/torchaudio_unittest/functional/torchscript_consistency_impl.py b/test/torchaudio_unittest/functional/torchscript_consistency_impl.py index a39973f867..3eb869c876 100644 --- a/test/torchaudio_unittest/functional/torchscript_consistency_impl.py +++ b/test/torchaudio_unittest/functional/torchscript_consistency_impl.py @@ -591,6 +591,28 @@ def func(tensor): tensor = common_utils.get_whitenoise(sample_rate=44100) self._assert_consistency(func, tensor) + def test_resample_sinc(self): + def func(tensor): + sr1, sr2 = 16000., 8000. + return F.resample(tensor, sr1, sr2, resampling_method="sinc_interpolation") + + tensor = common_utils.get_whitenoise(sample_rate=16000) + self._assert_consistency(func, tensor) + + def test_resample_kaiser(self): + def func(tensor): + sr1, sr2 = 16000., 8000. + return F.resample(tensor, sr1, sr2, resampling_method="kaiser_window") + + def func_beta(tensor): + sr1, sr2 = 16000., 8000. + beta = 6. + return F.resample(tensor, sr1, sr2, resampling_method="kaiser_window", beta=beta) + + tensor = common_utils.get_whitenoise(sample_rate=16000) + self._assert_consistency(func, tensor) + self._assert_consistency(func_beta, tensor) + @parameterized.expand([(True, ), (False, )]) def test_phase_vocoder(self, test_paseudo_complex): def func(tensor): diff --git a/test/torchaudio_unittest/models_test.py b/test/torchaudio_unittest/models_test.py index 484ec6c10c..4db4895b8f 100644 --- a/test/torchaudio_unittest/models_test.py +++ b/test/torchaudio_unittest/models_test.py @@ -3,7 +3,7 @@ import torch from parameterized import parameterized -from torchaudio.models import ConvTasNet, Wav2Letter, WaveRNN +from torchaudio.models import ConvTasNet, DeepSpeech, Wav2Letter, WaveRNN from torchaudio.models.wavernn import MelResNet, UpsampleNetwork from torchaudio_unittest import common_utils @@ -174,3 +174,20 @@ def test_paper_configuration(self, num_sources, model_params): output = model(tensor) assert output.shape == (batch_size, num_sources, num_frames) + + +class TestDeepSpeech(common_utils.TorchaudioTestCase): + + def test_deepspeech(self): + n_batch = 2 + n_feature = 1 + n_channel = 1 + n_class = 40 + n_time = 320 + + model = DeepSpeech(n_feature=n_feature, n_class=n_class) + + x = torch.rand(n_batch, n_channel, n_time, n_feature) + out = model(x) + + assert out.size() == (n_batch, n_time, n_class) diff --git a/test/torchaudio_unittest/rnnt/torchscript_consistency_cpu_test.py b/test/torchaudio_unittest/rnnt/torchscript_consistency_cpu_test.py new file mode 100644 index 0000000000..06b6baf5a1 --- /dev/null +++ b/test/torchaudio_unittest/rnnt/torchscript_consistency_cpu_test.py @@ -0,0 +1,10 @@ +import torch + +from torchaudio_unittest.common_utils import PytorchTestCase +from .utils import skipIfNoTransducer +from .torchscript_consistency_impl import RNNTLossTorchscript + + +@skipIfNoTransducer +class TestRNNTLoss(RNNTLossTorchscript, PytorchTestCase): + device = torch.device('cpu') diff --git a/test/torchaudio_unittest/rnnt/torchscript_consistency_cuda_test.py b/test/torchaudio_unittest/rnnt/torchscript_consistency_cuda_test.py new file mode 100644 index 0000000000..22b1713582 --- /dev/null +++ b/test/torchaudio_unittest/rnnt/torchscript_consistency_cuda_test.py @@ -0,0 +1,11 @@ +import torch + +from torchaudio_unittest.common_utils import PytorchTestCase, skipIfNoCuda +from .utils import skipIfNoTransducer +from .torchscript_consistency_impl import RNNTLossTorchscript + + +@skipIfNoTransducer +@skipIfNoCuda +class TestRNNTLoss(RNNTLossTorchscript, PytorchTestCase): + device = torch.device('cuda') diff --git a/test/torchaudio_unittest/rnnt/torchscript_consistency_impl.py b/test/torchaudio_unittest/rnnt/torchscript_consistency_impl.py new file mode 100644 index 0000000000..aeba7e3ae4 --- /dev/null +++ b/test/torchaudio_unittest/rnnt/torchscript_consistency_impl.py @@ -0,0 +1,70 @@ +import torch +from torchaudio_unittest.common_utils import TempDirMixin, TestBaseMixin +from torchaudio.prototype.rnnt_loss import RNNTLoss, rnnt_loss + + +class RNNTLossTorchscript(TempDirMixin, TestBaseMixin): + """Implements test for RNNT Loss that are performed for different devices""" + def _assert_consistency(self, func, tensor, shape_only=False): + tensor = tensor.to(device=self.device, dtype=self.dtype) + + path = self.get_temp_path('func.zip') + torch.jit.script(func).save(path) + ts_func = torch.jit.load(path) + + torch.random.manual_seed(40) + input_tensor = tensor.clone().detach().requires_grad_(True) + output = func(input_tensor) + + torch.random.manual_seed(40) + input_tensor = tensor.clone().detach().requires_grad_(True) + ts_output = ts_func(input_tensor) + + self.assertEqual(ts_output, output) + + def test_rnnt_loss(self): + def func( + logits, + ): + targets = torch.tensor([[1, 2]], device=logits.device, dtype=torch.int32) + logit_lengths = torch.tensor([2], device=logits.device, dtype=torch.int32) + target_lengths = torch.tensor([2], device=logits.device, dtype=torch.int32) + return rnnt_loss(logits, targets, logit_lengths, target_lengths) + + logits = torch.tensor([[[[0.1, 0.6, 0.1, 0.1, 0.1], + [0.1, 0.1, 0.6, 0.1, 0.1], + [0.1, 0.1, 0.2, 0.8, 0.1]], + [[0.1, 0.6, 0.1, 0.1, 0.1], + [0.1, 0.1, 0.2, 0.1, 0.1], + [0.7, 0.1, 0.2, 0.1, 0.1]]]]) + + self._assert_consistency(func, logits) + + def test_RNNTLoss(self): + func = RNNTLoss() + + logits = torch.tensor([[[[0.1, 0.6, 0.1, 0.1, 0.1], + [0.1, 0.1, 0.6, 0.1, 0.1], + [0.1, 0.1, 0.2, 0.8, 0.1]], + [[0.1, 0.6, 0.1, 0.1, 0.1], + [0.1, 0.1, 0.2, 0.1, 0.1], + [0.7, 0.1, 0.2, 0.1, 0.1]]]]) + targets = torch.tensor([[1, 2]], device=self.device, dtype=torch.int32) + logit_lengths = torch.tensor([2], device=self.device, dtype=torch.int32) + target_lengths = torch.tensor([2], device=self.device, dtype=torch.int32) + + tensor = logits.to(device=self.device, dtype=self.dtype) + + path = self.get_temp_path('func.zip') + torch.jit.script(func).save(path) + ts_func = torch.jit.load(path) + + torch.random.manual_seed(40) + input_tensor = tensor.clone().detach().requires_grad_(True) + output = func(input_tensor, targets, logit_lengths, target_lengths) + + torch.random.manual_seed(40) + input_tensor = tensor.clone().detach().requires_grad_(True) + ts_output = ts_func(input_tensor, targets, logit_lengths, target_lengths) + + self.assertEqual(ts_output, output) diff --git a/test/torchaudio_unittest/rnnt/utils.py b/test/torchaudio_unittest/rnnt/utils.py index 8e93d28032..5f4c40379e 100644 --- a/test/torchaudio_unittest/rnnt/utils.py +++ b/test/torchaudio_unittest/rnnt/utils.py @@ -405,10 +405,10 @@ def get_numpy_random_data( def numpy_to_torch(data, device, requires_grad=True): - logits = torch.from_numpy(data["logits"]) - targets = torch.from_numpy(data["targets"]) - logit_lengths = torch.from_numpy(data["logit_lengths"]) - target_lengths = torch.from_numpy(data["target_lengths"]) + logits = torch.from_numpy(data["logits"]).to(device=device) + targets = torch.from_numpy(data["targets"]).to(device=device) + logit_lengths = torch.from_numpy(data["logit_lengths"]).to(device=device) + target_lengths = torch.from_numpy(data["target_lengths"]).to(device=device) if "nbest_wers" in data: data["nbest_wers"] = torch.from_numpy(data["nbest_wers"]).to(device=device) diff --git a/test/torchaudio_unittest/transforms/autograd_test_impl.py b/test/torchaudio_unittest/transforms/autograd_test_impl.py index 717a7bc87b..0f7b612482 100644 --- a/test/torchaudio_unittest/transforms/autograd_test_impl.py +++ b/test/torchaudio_unittest/transforms/autograd_test_impl.py @@ -125,6 +125,31 @@ def test_fade(self, fade_shape): waveform = get_whitenoise(sample_rate=8000, duration=0.05, n_channels=2) self.assert_grad(transform, [waveform], nondet_tol=1e-10) + @parameterized.expand([(T.TimeMasking,), (T.FrequencyMasking,)]) + def test_masking(self, masking_transform): + sample_rate = 8000 + n_fft = 400 + spectrogram = get_spectrogram( + get_whitenoise(sample_rate=sample_rate, duration=0.05, n_channels=2), + n_fft=n_fft, power=1) + deterministic_transform = _DeterministicWrapper(masking_transform(400)) + self.assert_grad(deterministic_transform, [spectrogram]) + + @parameterized.expand([(T.TimeMasking,), (T.FrequencyMasking,)]) + def test_masking_iid(self, masking_transform): + sample_rate = 8000 + n_fft = 400 + specs = [get_spectrogram( + get_whitenoise(sample_rate=sample_rate, duration=0.05, n_channels=2, seed=i), + n_fft=n_fft, power=1) + for i in range(3) + ] + + batch = torch.stack(specs) + assert batch.ndim == 4 + deterministic_transform = _DeterministicWrapper(masking_transform(400, True)) + self.assert_grad(deterministic_transform, [batch]) + def test_spectral_centroid(self): sample_rate = 8000 transform = T.SpectralCentroid(sample_rate=sample_rate) diff --git a/test/torchaudio_unittest/transforms/sox_compatibility_test.py b/test/torchaudio_unittest/transforms/sox_compatibility_test.py index 81582c8393..be6c9020ab 100644 --- a/test/torchaudio_unittest/transforms/sox_compatibility_test.py +++ b/test/torchaudio_unittest/transforms/sox_compatibility_test.py @@ -1,3 +1,6 @@ +import warnings + +import torch import torchaudio.transforms as T from parameterized import parameterized @@ -61,3 +64,25 @@ def test_vad(self, filename): data, sample_rate = load_wav(path) result = T.Vad(sample_rate)(data) self.assert_sox_effect(result, path, ['vad']) + + def test_vad_warning(self): + """vad should throw a warning if input dimension is greater than 2""" + sample_rate = 41100 + + data = torch.rand(5, 5, sample_rate) + with warnings.catch_warnings(record=True) as w: + warnings.simplefilter("always") + T.Vad(sample_rate)(data) + assert len(w) == 1 + + data = torch.rand(5, sample_rate) + with warnings.catch_warnings(record=True) as w: + warnings.simplefilter("always") + T.Vad(sample_rate)(data) + assert len(w) == 0 + + data = torch.rand(sample_rate) + with warnings.catch_warnings(record=True) as w: + warnings.simplefilter("always") + T.Vad(sample_rate)(data) + assert len(w) == 0 diff --git a/test/torchaudio_unittest/transforms/torchscript_consistency_impl.py b/test/torchaudio_unittest/transforms/torchscript_consistency_impl.py index 506ca9af6c..5258343181 100644 --- a/test/torchaudio_unittest/transforms/torchscript_consistency_impl.py +++ b/test/torchaudio_unittest/transforms/torchscript_consistency_impl.py @@ -59,6 +59,10 @@ def test_AmplitudeToDB(self): spec = torch.rand((6, 201)) self._assert_consistency(T.AmplitudeToDB(), spec) + def test_MelScale_invalid(self): + with self.assertRaises(ValueError): + torch.jit.script(T.MelScale()) + def test_MelScale(self): spec_f = torch.rand((1, 201, 6)) self._assert_consistency(T.MelScale(n_stft=201), spec_f) diff --git a/test/torchaudio_unittest/transforms/transforms_test.py b/test/torchaudio_unittest/transforms/transforms_test.py index ab7b2ed981..5aa88ead90 100644 --- a/test/torchaudio_unittest/transforms/transforms_test.py +++ b/test/torchaudio_unittest/transforms/transforms_test.py @@ -169,9 +169,11 @@ def test_resample_size(self): upsample_rate = sample_rate * 2 downsample_rate = sample_rate // 2 - invalid_resample = torchaudio.transforms.Resample(sample_rate, upsample_rate, resampling_method='foo') + invalid_resampling_method = 'foo' - self.assertRaises(ValueError, invalid_resample, waveform) + with self.assertRaises(ValueError): + torchaudio.transforms.Resample(sample_rate, upsample_rate, + resampling_method=invalid_resampling_method) upsample_resample = torchaudio.transforms.Resample( sample_rate, upsample_rate, resampling_method='sinc_interpolation') diff --git a/test/torchaudio_unittest/transforms/transforms_test_impl.py b/test/torchaudio_unittest/transforms/transforms_test_impl.py index 8a92662200..44f254e540 100644 --- a/test/torchaudio_unittest/transforms/transforms_test_impl.py +++ b/test/torchaudio_unittest/transforms/transforms_test_impl.py @@ -1,3 +1,5 @@ +import warnings + import torch import torchaudio.transforms as T @@ -39,7 +41,7 @@ def test_InverseMelScale(self): get_whitenoise(sample_rate=sample_rate, duration=1, n_channels=2), n_fft=n_fft, power=power).to(self.device, self.dtype) input = T.MelScale( - n_mels=n_mels, sample_rate=sample_rate + n_mels=n_mels, sample_rate=sample_rate, n_stft=n_stft ).to(self.device, self.dtype)(expected) # Run transform @@ -59,3 +61,19 @@ def test_InverseMelScale(self): assert _get_ratio(relative_diff < 1e-1) > 0.2 assert _get_ratio(relative_diff < 1e-3) > 5e-3 assert _get_ratio(relative_diff < 1e-5) > 1e-5 + + def test_melscale_unset_weight_warning(self): + """Issue a warning if MelScale initialized without a weight + + As part of the deprecation of lazy intialization behavior (#1510), + issue a warning if `n_stft` is not set. + """ + with warnings.catch_warnings(record=True) as caught_warnings: + warnings.simplefilter("always") + T.MelScale(n_mels=64, sample_rate=8000) + assert len(caught_warnings) == 1 + + with warnings.catch_warnings(record=True) as caught_warnings: + warnings.simplefilter("always") + T.MelScale(n_mels=64, sample_rate=8000, n_stft=201) + assert len(caught_warnings) == 0 diff --git a/torchaudio/compliance/kaldi.py b/torchaudio/compliance/kaldi.py index a5c3354c9b..22616038f5 100644 --- a/torchaudio/compliance/kaldi.py +++ b/torchaudio/compliance/kaldi.py @@ -755,7 +755,9 @@ def mfcc( def resample_waveform(waveform: Tensor, orig_freq: float, new_freq: float, - lowpass_filter_width: int = 6) -> Tensor: + lowpass_filter_width: int = 6, + rolloff: float = 0.99, + resampling_method: str = "sinc_interpolation") -> Tensor: r"""Resamples the waveform at the new frequency. This is a wrapper around ``torchaudio.functional.resample``. @@ -766,8 +768,13 @@ def resample_waveform(waveform: Tensor, new_freq (float): The desired frequency lowpass_filter_width (int, optional): Controls the sharpness of the filter, more == sharper but less efficient. We suggest around 4 to 10 for normal use. (Default: ``6``) + rolloff (float, optional): The roll-off frequency of the filter, as a fraction of the Nyquist. + Lower values reduce anti-aliasing, but also reduce some of the highest frequencies. (Default: ``0.99``) + resampling_method (str, optional): The resampling method to use. + Options: [``sinc_interpolation``, ``kaiser_window``] (Default: ``'sinc_interpolation'``) Returns: Tensor: The waveform at the new frequency """ - return torchaudio.functional.resample(waveform, orig_freq, new_freq, lowpass_filter_width) + return torchaudio.functional.resample(waveform, orig_freq, new_freq, lowpass_filter_width, + rolloff, resampling_method) diff --git a/torchaudio/csrc/CMakeLists.txt b/torchaudio/csrc/CMakeLists.txt index ebf577eb64..64661f96a5 100644 --- a/torchaudio/csrc/CMakeLists.txt +++ b/torchaudio/csrc/CMakeLists.txt @@ -19,6 +19,7 @@ if(BUILD_TRANSDUCER) rnnt/compute_alphas.cpp rnnt/compute_betas.cpp rnnt/compute.cpp + rnnt/autograd.cpp ) if (USE_CUDA) diff --git a/torchaudio/csrc/rnnt/autograd.cpp b/torchaudio/csrc/rnnt/autograd.cpp new file mode 100644 index 0000000000..73ad9f9b3c --- /dev/null +++ b/torchaudio/csrc/rnnt/autograd.cpp @@ -0,0 +1,74 @@ +#include +#include + +namespace torchaudio { +namespace rnnt { + +class RNNTLossFunction : public torch::autograd::Function { + public: + static torch::autograd::tensor_list forward( + torch::autograd::AutogradContext* ctx, + torch::Tensor& logits, + const torch::Tensor& targets, + const torch::Tensor& src_lengths, + const torch::Tensor& tgt_lengths, + int64_t blank, + double clamp, + bool fused_log_smax = true, + bool reuse_logits_for_grads = true) { + at::AutoNonVariableTypeMode g; + torch::Tensor undef; + auto result = rnnt_loss( + logits, + targets, + src_lengths, + tgt_lengths, + blank, + clamp, + fused_log_smax, + reuse_logits_for_grads); + auto costs = std::get<0>(result); + auto grads = std::get<1>(result).value_or(undef); + ctx->save_for_backward({grads}); + return {costs, grads}; + } + + static torch::autograd::tensor_list backward( + torch::autograd::AutogradContext* ctx, + torch::autograd::tensor_list grad_outputs) { + auto saved = ctx->get_saved_variables(); + auto grad = saved[0]; + auto grad_out = grad_outputs[0].view({-1, 1, 1, 1}); + auto result = grad * grad_out; + torch::Tensor undef; + return {result, undef, undef, undef, undef, undef, undef, undef}; + } +}; + +std::tuple> rnnt_loss_autograd( + torch::Tensor& logits, + const torch::Tensor& targets, + const torch::Tensor& src_lengths, + const torch::Tensor& tgt_lengths, + int64_t blank, + double clamp, + bool fused_log_smax = true, + bool reuse_logits_for_grads = true) { + auto results = RNNTLossFunction::apply( + logits, + targets, + src_lengths, + tgt_lengths, + blank, + clamp, + fused_log_smax, + reuse_logits_for_grads); + return std::make_tuple(results[0], results[1]); +} + +TORCH_LIBRARY_IMPL(torchaudio, Autograd, m) { + m.impl("rnnt_loss", rnnt_loss_autograd); +} + +} // namespace rnnt +} // namespace torchaudio diff --git a/torchaudio/csrc/rnnt/compute.cpp b/torchaudio/csrc/rnnt/compute.cpp index bce803fffa..f47f0f505d 100644 --- a/torchaudio/csrc/rnnt/compute.cpp +++ b/torchaudio/csrc/rnnt/compute.cpp @@ -1,4 +1,28 @@ #include +#include + +std::tuple> rnnt_loss( + torch::Tensor& logits, + const torch::Tensor& targets, + const torch::Tensor& src_lengths, + const torch::Tensor& tgt_lengths, + int64_t blank, + double clamp, + bool fused_log_smax = true, + bool reuse_logits_for_grads = true) { + static auto op = torch::Dispatcher::singleton() + .findSchemaOrThrow("torchaudio::rnnt_loss", "") + .typed(); + return op.call( + logits, + targets, + src_lengths, + tgt_lengths, + blank, + clamp, + fused_log_smax, + reuse_logits_for_grads); +} TORCH_LIBRARY_FRAGMENT(torchaudio, m) { m.def( diff --git a/torchaudio/csrc/rnnt/compute.h b/torchaudio/csrc/rnnt/compute.h new file mode 100644 index 0000000000..9616d45fc3 --- /dev/null +++ b/torchaudio/csrc/rnnt/compute.h @@ -0,0 +1,13 @@ +#pragma once + +#include + +std::tuple> rnnt_loss( + torch::Tensor& logits, + const torch::Tensor& targets, + const torch::Tensor& src_lengths, + const torch::Tensor& tgt_lengths, + int64_t blank, + double clamp, + bool fused_log_smax, + bool reuse_logits_for_grads); diff --git a/torchaudio/csrc/rnnt/transducer.h b/torchaudio/csrc/rnnt/transducer.h deleted file mode 100644 index 0553616114..0000000000 --- a/torchaudio/csrc/rnnt/transducer.h +++ /dev/null @@ -1,121 +0,0 @@ -#pragma once - -#include -#include - -namespace torchaudio { -namespace rnnt { - -template -status_t Compute( - const Workspace& workspace, - const DTYPE* logits, - const int* targets, - const int* srcLengths, - const int* tgtLengths, - DTYPE* costs, - DTYPE* gradients = nullptr) { - switch (workspace.GetOptions().device_) { - case CPU: { - status_t status = cpu::Compute( - /*workspace=*/workspace, - /*logits=*/logits, - /*targets=*/targets, - /*srcLengths=*/srcLengths, - /*tgtLengths=*/tgtLengths, - /*costs=*/costs, - /*gradients=*/gradients); - return status; - } - case GPU: { - status_t status = gpu::Compute( - /*workspace=*/workspace, - /*logits=*/logits, - /*targets=*/targets, - /*srcLengths=*/srcLengths, - /*tgtLengths=*/tgtLengths, - /*costs=*/costs, - /*gradients=*/gradients); - return status; - } - default: { - return FAILURE; - } - }; -} - -template -status_t ComputeAlphas( - const Workspace& workspace, - const DTYPE* logits, - const int* targets, - const int* srcLengths, - const int* tgtLengths, - DTYPE* alphas) { - switch (workspace.GetOptions().device_) { - case CPU: { - status_t status = cpu::ComputeAlphas( - /*workspace=*/workspace, - /*logits=*/logits, - /*targets=*/targets, - /*srcLengths=*/srcLengths, - /*tgtLengths=*/tgtLengths, - /*alphas=*/alphas); - return status; - } - case GPU: { - status_t status = gpu::ComputeAlphas( - /*workspace=*/workspace, - /*logits=*/logits, - /*targets=*/targets, - /*srcLengths=*/srcLengths, - /*tgtLengths=*/tgtLengths, - /*costs=*/alphas); - return status; - } - default: { - return FAILURE; - } - }; -} - -template -status_t ComputeBetas( - const Workspace& workspace, - const DTYPE* logits, - const int* targets, - const int* srcLengths, - const int* tgtLengths, - DTYPE* costs, - DTYPE* betas) { - switch (workspace.GetOptions().device_) { - case CPU: { - status_t status = cpu::ComputeBetas( - /*workspace=*/workspace, - /*logits=*/logits, - /*targets=*/targets, - /*srcLengths=*/srcLengths, - /*tgtLengths=*/tgtLengths, - /*costs=*/costs, - /*betas=*/betas); - return status; - } - case GPU: { - status_t status = gpu::ComputeBetas( - /*workspace=*/workspace, - /*logits=*/logits, - /*targets=*/targets, - /*srcLengths=*/srcLengths, - /*tgtLengths=*/tgtLengths, - /*costs=*/costs, - /*betas=*/betas); - return status; - } - default: { - return FAILURE; - } - }; -} - -} // namespace rnnt -} // namespace torchaudio diff --git a/torchaudio/functional/filtering.py b/torchaudio/functional/filtering.py index 93da27493b..85abe81339 100644 --- a/torchaudio/functional/filtering.py +++ b/torchaudio/functional/filtering.py @@ -1,4 +1,5 @@ import math +import warnings from typing import Optional import torch @@ -1374,7 +1375,10 @@ def vad( so in order to trim from the back, the reverse effect must also be used. Args: - waveform (Tensor): Tensor of audio of dimension `(..., time)` + waveform (Tensor): Tensor of audio of dimension `(channels, time)` or `(time)` + Tensor of shape `(channels, time)` is treated as a multi-channel recording + of the same event and the resulting output will be trimmed to the earliest + voice activity in any channel. sample_rate (int): Sample rate of audio signal. trigger_level (float, optional): The measurement level used to trigger activity detection. This may need to be cahnged depending on the noise level, signal level, @@ -1420,6 +1424,15 @@ def vad( http://sox.sourceforge.net/sox.html """ + if waveform.ndim > 2: + warnings.warn( + "Expected input tensor dimension of 1 for single channel" + f" or 2 for multi-channel. Got {waveform.ndim} instead. " + "Batch semantics is not supported. " + "Please refer to https://github.com/pytorch/audio/issues/1348" + " and https://github.com/pytorch/audio/issues/1468." + ) + measure_duration: float = ( 2.0 / measure_freq if measure_duration is None else measure_duration ) diff --git a/torchaudio/functional/functional.py b/torchaudio/functional/functional.py index b7d9b112b8..74271798eb 100644 --- a/torchaudio/functional/functional.py +++ b/torchaudio/functional/functional.py @@ -1298,8 +1298,36 @@ def compute_kaldi_pitch( return result -def _get_sinc_resample_kernel(orig_freq: int, new_freq: int, lowpass_filter_width: int, - device: torch.device, dtype: torch.dtype): +def _get_sinc_resample_kernel( + orig_freq: float, + new_freq: float, + gcd: int, + lowpass_filter_width: int, + rolloff: float, + resampling_method: str, + beta: Optional[float], + device: torch.device = torch.device("cpu"), + dtype: Optional[torch.dtype] = None): + + if not (int(orig_freq) == orig_freq and int(new_freq) == new_freq): + warnings.warn( + "Non-integer frequencies are being cast to ints and may result in poor resampling quality " + "because the underlying algorithm requires an integer ratio between `orig_freq` and `new_freq`. " + "Using non-integer valued frequencies will throw an error in the next release. " + "To work around this issue, manually convert both frequencies to integer values " + "that maintain their resampling rate ratio before passing them into the function " + "Example: To downsample a 44100 hz waveform by a factor of 8, use " + "`orig_freq=8` and `new_freq=1` instead of `orig_freq=44100` and `new_freq=5512.5` " + "For more information or to leave feedback about this change, please refer to " + "https://github.com/pytorch/audio/issues/1487." + ) + + if resampling_method not in ['sinc_interpolation', 'kaiser_window']: + raise ValueError('Invalid resampling method: {}'.format(resampling_method)) + + orig_freq = int(orig_freq) // gcd + new_freq = int(new_freq) // gcd + assert lowpass_filter_width > 0 kernels = [] base_freq = min(orig_freq, new_freq) @@ -1307,7 +1335,7 @@ def _get_sinc_resample_kernel(orig_freq: int, new_freq: int, lowpass_filter_widt # At first I thought I only needed this when downsampling, but when upsampling # you will get edge artifacts without this, as the edge is equivalent to zero padding, # which will add high freq artifacts. - base_freq *= 0.99 + base_freq *= rolloff # The key idea of the algorithm is that x(t) can be exactly reconstructed from x[i] (tensor) # using the sinc interpolation formula: @@ -1331,70 +1359,99 @@ def _get_sinc_resample_kernel(orig_freq: int, new_freq: int, lowpass_filter_widt # they will have a lot of almost zero values to the left or to the right... # There is probably a way to evaluate those filters more efficiently, but this is kept for # future work. - idx = torch.arange(-width, width + orig_freq, device=device, dtype=dtype) + idx_dtype = dtype if dtype is not None else torch.float64 + idx = torch.arange(-width, width + orig_freq, device=device, dtype=idx_dtype) for i in range(new_freq): t = (-i / new_freq + idx / orig_freq) * base_freq t = t.clamp_(-lowpass_filter_width, lowpass_filter_width) - t *= math.pi - # we do not use torch.hann_window here as we need to evaluate the window + + # we do not use built in torch windows here as we need to evaluate the window # at specific positions, not over a regular grid. - window = torch.cos(t / lowpass_filter_width / 2)**2 + if resampling_method == "sinc_interpolation": + window = torch.cos(t * math.pi / lowpass_filter_width / 2)**2 + else: + # kaiser_window + if beta is None: + beta = 14.769656459379492 + beta_tensor = torch.tensor(float(beta)) + window = torch.i0(beta_tensor * torch.sqrt(1 - (t / lowpass_filter_width) ** 2)) / torch.i0(beta_tensor) + t *= math.pi kernel = torch.where(t == 0, torch.tensor(1.).to(t), torch.sin(t) / t) kernel.mul_(window) kernels.append(kernel) scale = base_freq / orig_freq - return torch.stack(kernels).view(new_freq, 1, -1).mul_(scale), width + kernels = torch.stack(kernels).view(new_freq, 1, -1).mul_(scale) + if dtype is None: + kernels = kernels.to(dtype=torch.float32) + return kernels, width + + +def _apply_sinc_resample_kernel( + waveform: Tensor, + orig_freq: float, + new_freq: float, + gcd: int, + kernel: Tensor, + width: int, +): + orig_freq = int(orig_freq) // gcd + new_freq = int(new_freq) // gcd + + # pack batch + shape = waveform.size() + waveform = waveform.view(-1, shape[-1]) + + num_wavs, length = waveform.shape + waveform = torch.nn.functional.pad(waveform, (width, width + orig_freq)) + resampled = torch.nn.functional.conv1d(waveform[:, None], kernel, stride=orig_freq) + resampled = resampled.transpose(1, 2).reshape(num_wavs, -1) + target_length = int(math.ceil(new_freq * length / orig_freq)) + resampled = resampled[..., :target_length] + + # unpack batch + resampled = resampled.view(shape[:-1] + resampled.shape[-1:]) + return resampled def resample( waveform: Tensor, orig_freq: float, new_freq: float, - lowpass_filter_width: int = 6 + lowpass_filter_width: int = 6, + rolloff: float = 0.99, + resampling_method: str = "sinc_interpolation", + beta: Optional[float] = None, ) -> Tensor: - r"""Resamples the waveform at the new frequency. This matches Kaldi's OfflineFeatureTpl ResampleWaveform - which uses a LinearResample (resample a signal at linearly spaced intervals to upsample/downsample - a signal). LinearResample (LR) means that the output signal is at linearly spaced intervals (i.e - the output signal has a frequency of ``new_freq``). It uses sinc/bandlimited interpolation to - upsample/downsample the signal. + r"""Resamples the waveform at the new frequency using bandlimited interpolation. https://ccrma.stanford.edu/~jos/resample/Theory_Ideal_Bandlimited_Interpolation.html - https://github.com/kaldi-asr/kaldi/blob/master/src/feat/resample.h#L56 Args: waveform (Tensor): The input signal of dimension (..., time) orig_freq (float): The original frequency of the signal new_freq (float): The desired frequency lowpass_filter_width (int, optional): Controls the sharpness of the filter, more == sharper - but less efficient. We suggest around 4 to 10 for normal use. (Default: ``6``) + but less efficient. (Default: ``6``) + rolloff (float, optional): The roll-off frequency of the filter, as a fraction of the Nyquist. + Lower values reduce anti-aliasing, but also reduce some of the highest frequencies. (Default: ``0.99``) + resampling_method (str, optional): The resampling method to use. + Options: [``sinc_interpolation``, ``kaiser_window``] (Default: ``'sinc_interpolation'``) + beta (float or None): The shape parameter used for kaiser window. Returns: Tensor: The waveform at the new frequency of dimension (..., time). + + Note: ``transforms.Resample`` precomputes and reuses the resampling kernel, so using it will result in + more efficient computation if resampling multiple waveforms with the same resampling parameters. """ - # pack batch - shape = waveform.size() - waveform = waveform.view(-1, shape[-1]) assert orig_freq > 0.0 and new_freq > 0.0 - orig_freq = int(orig_freq) - new_freq = int(new_freq) - gcd = math.gcd(orig_freq, new_freq) - orig_freq = orig_freq // gcd - new_freq = new_freq // gcd - - kernel, width = _get_sinc_resample_kernel(orig_freq, new_freq, lowpass_filter_width, - waveform.device, waveform.dtype) + gcd = math.gcd(int(orig_freq), int(new_freq)) - num_wavs, length = waveform.shape - waveform = torch.nn.functional.pad(waveform, (width, width + orig_freq)) - resampled = torch.nn.functional.conv1d(waveform[:, None], kernel, stride=orig_freq) - resampled = resampled.transpose(1, 2).reshape(num_wavs, -1) - target_length = int(math.ceil(new_freq * length / orig_freq)) - resampled = resampled[..., :target_length] - - # unpack batch - resampled = resampled.view(shape[:-1] + resampled.shape[-1:]) + kernel, width = _get_sinc_resample_kernel(orig_freq, new_freq, gcd, lowpass_filter_width, rolloff, + resampling_method, beta, waveform.device, waveform.dtype) + resampled = _apply_sinc_resample_kernel(waveform, orig_freq, new_freq, gcd, kernel, width) return resampled diff --git a/torchaudio/models/__init__.py b/torchaudio/models/__init__.py index 5b134345af..6696d8ded2 100644 --- a/torchaudio/models/__init__.py +++ b/torchaudio/models/__init__.py @@ -1,9 +1,11 @@ from .wav2letter import Wav2Letter from .wavernn import WaveRNN from .conv_tasnet import ConvTasNet +from .deepspeech import DeepSpeech __all__ = [ 'Wav2Letter', 'WaveRNN', 'ConvTasNet', + 'DeepSpeech', ] diff --git a/torchaudio/models/deepspeech.py b/torchaudio/models/deepspeech.py new file mode 100644 index 0000000000..477993e411 --- /dev/null +++ b/torchaudio/models/deepspeech.py @@ -0,0 +1,92 @@ +import torch + +__all__ = ["DeepSpeech"] + + +class FullyConnected(torch.nn.Module): + """ + Args: + n_feature: Number of input features + n_hidden: Internal hidden unit size. + """ + + def __init__(self, + n_feature: int, + n_hidden: int, + dropout: float, + relu_max_clip: int = 20) -> None: + super(FullyConnected, self).__init__() + self.fc = torch.nn.Linear(n_feature, n_hidden, bias=True) + self.relu_max_clip = relu_max_clip + self.dropout = dropout + + def forward(self, x: torch.Tensor) -> torch.Tensor: + x = self.fc(x) + x = torch.nn.functional.relu(x) + x = torch.nn.functional.hardtanh(x, 0, self.relu_max_clip) + if self.dropout: + x = torch.nn.functional.dropout(x, self.dropout, self.training) + return x + + +class DeepSpeech(torch.nn.Module): + """ + DeepSpeech model architecture from + `"Deep Speech: Scaling up end-to-end speech recognition"` + paper. + + Args: + n_feature: Number of input features + n_hidden: Internal hidden unit size. + n_class: Number of output classes + """ + + def __init__( + self, + n_feature: int, + n_hidden: int = 2048, + n_class: int = 40, + dropout: float = 0.0, + ) -> None: + super(DeepSpeech, self).__init__() + self.n_hidden = n_hidden + self.fc1 = FullyConnected(n_feature, n_hidden, dropout) + self.fc2 = FullyConnected(n_hidden, n_hidden, dropout) + self.fc3 = FullyConnected(n_hidden, n_hidden, dropout) + self.bi_rnn = torch.nn.RNN( + n_hidden, n_hidden, num_layers=1, nonlinearity="relu", bidirectional=True + ) + self.fc4 = FullyConnected(n_hidden, n_hidden, dropout) + self.out = torch.nn.Linear(n_hidden, n_class) + + def forward(self, x: torch.Tensor) -> torch.Tensor: + """ + Args: + x (torch.Tensor): Tensor of dimension (batch, channel, time, feature). + Returns: + Tensor: Predictor tensor of dimension (batch, time, class). + """ + # N x C x T x F + x = self.fc1(x) + # N x C x T x H + x = self.fc2(x) + # N x C x T x H + x = self.fc3(x) + # N x C x T x H + x = x.squeeze(1) + # N x T x H + x = x.transpose(0, 1) + # T x N x H + x, _ = self.bi_rnn(x) + # The fifth (non-recurrent) layer takes both the forward and backward units as inputs + x = x[:, :, :self.n_hidden] + x[:, :, self.n_hidden:] + # T x N x H + x = self.fc4(x) + # T x N x H + x = self.out(x) + # T x N x n_class + x = x.permute(1, 0, 2) + # N x T x n_class + x = torch.nn.functional.log_softmax(x, dim=2) + # N x T x n_class + return x diff --git a/torchaudio/prototype/rnnt_loss.py b/torchaudio/prototype/rnnt_loss.py index 08c96ab0f2..2bce60835b 100644 --- a/torchaudio/prototype/rnnt_loss.py +++ b/torchaudio/prototype/rnnt_loss.py @@ -1,4 +1,5 @@ import torch +from torch import Tensor __all__ = [ "RNNTLoss", @@ -6,141 +7,15 @@ ] -def _rnnt_loss_alphas( - logits, - targets, - logit_lengths, - target_lengths, - blank=-1, - clamp=-1, -): - """ - Compute alphas for RNN transducer loss. - - See documentation for RNNTLoss - """ - targets = targets.to(device=logits.device) - logit_lengths = logit_lengths.to(device=logits.device) - target_lengths = target_lengths.to(device=logits.device) - - # make sure all int tensors are of type int32. - targets = targets.int() - logit_lengths = logit_lengths.int() - target_lengths = target_lengths.int() - - return torch.ops.torchaudio.rnnt_loss_alphas( - logits, - targets, - logit_lengths, - target_lengths, - blank, - clamp, - ) - - -def _rnnt_loss_betas( - logits, - targets, - logit_lengths, - target_lengths, - blank=-1, - clamp=-1, -): - """ - Compute betas for RNN transducer loss - - See documentation for RNNTLoss - """ - targets = targets.to(device=logits.device) - logit_lengths = logit_lengths.to(device=logits.device) - target_lengths = target_lengths.to(device=logits.device) - - # make sure all int tensors are of type int32. - targets = targets.int() - logit_lengths = logit_lengths.int() - target_lengths = target_lengths.int() - - return torch.ops.torchaudio.rnnt_loss_betas( - logits, - targets, - logit_lengths, - target_lengths, - blank, - clamp, - ) - - -class _RNNT(torch.autograd.Function): - @staticmethod - def forward( - ctx, - logits, - targets, - logit_lengths, - target_lengths, - blank=-1, - clamp=-1, - fused_log_softmax=True, - reuse_logits_for_grads=True, - ): - """ - See documentation for RNNTLoss - """ - - # move everything to the same device. - targets = targets.to(device=logits.device) - logit_lengths = logit_lengths.to(device=logits.device) - target_lengths = target_lengths.to(device=logits.device) - - # make sure all int tensors are of type int32. - targets = targets.int() - logit_lengths = logit_lengths.int() - target_lengths = target_lengths.int() - - if blank < 0: # reinterpret blank index if blank < 0. - blank = logits.shape[-1] + blank - - costs, gradients = torch.ops.torchaudio.rnnt_loss( - logits=logits, - targets=targets, - src_lengths=logit_lengths, - tgt_lengths=target_lengths, - blank=blank, - clamp=clamp, - fused_log_smax=fused_log_softmax, - reuse_logits_for_grads=reuse_logits_for_grads, - ) - - ctx.grads = gradients - - return costs - - @staticmethod - def backward(ctx, output_gradients): - output_gradients = output_gradients.view(-1, 1, 1, 1).to(ctx.grads) - ctx.grads.mul_(output_gradients).to(ctx.grads) - - return ( - ctx.grads, # logits - None, # targets - None, # logit_lengths - None, # target_lengths - None, # blank - None, # clamp - None, # fused_log_softmax - None, # reuse_logits_for_grads - ) - - def rnnt_loss( - logits, - targets, - logit_lengths, - target_lengths, - blank=-1, - clamp=-1, - fused_log_softmax=True, - reuse_logits_for_grads=True, + logits: Tensor, + targets: Tensor, + logit_lengths: Tensor, + target_lengths: Tensor, + blank: int = -1, + clamp: float = -1, + fused_log_softmax: bool = True, + reuse_logits_for_grads: bool = True, ): """ Compute the RNN Transducer Loss. @@ -166,17 +41,20 @@ def rnnt_loss( False # softmax needs the original logits value ) - cost = _RNNT.apply( - logits, - targets, - logit_lengths, - target_lengths, - blank, - clamp, - fused_log_softmax, - reuse_logits_for_grads, - ) - return cost + if blank < 0: # reinterpret blank index if blank < 0. + blank = logits.shape[-1] + blank + + costs, gradients = torch.ops.torchaudio.rnnt_loss( + logits=logits, + targets=targets, + src_lengths=logit_lengths, + tgt_lengths=target_lengths, + blank=blank, + clamp=clamp, + fused_log_smax=fused_log_softmax, + reuse_logits_for_grads=reuse_logits_for_grads,) + + return costs class RNNTLoss(torch.nn.Module): @@ -196,10 +74,10 @@ class RNNTLoss(torch.nn.Module): def __init__( self, - blank=-1, - clamp=-1, - fused_log_softmax=True, - reuse_logits_for_grads=True, + blank: int = -1, + clamp: float = -1., + fused_log_softmax: bool = True, + reuse_logits_for_grads: bool = True, ): super().__init__() self.blank = blank diff --git a/torchaudio/transforms.py b/torchaudio/transforms.py index fa38118043..49d3ff599b 100644 --- a/torchaudio/transforms.py +++ b/torchaudio/transforms.py @@ -8,6 +8,10 @@ from torch import Tensor from torchaudio import functional as F +from .functional.functional import ( + _get_sinc_resample_kernel, + _apply_sinc_resample_kernel, +) __all__ = [ 'Spectrogram', @@ -279,11 +283,34 @@ def __init__(self, assert f_min <= self.f_max, 'Require f_min: {} < f_max: {}'.format(f_min, self.f_max) + if n_stft is None or n_stft == 0: + warnings.warn( + 'Initialization of torchaudio.transforms.MelScale with an unset weight ' + '`n_stft=None` is deprecated and will be removed from a future release. ' + 'Please set a proper `n_stft` value. Typically this is `n_fft // 2 + 1`. ' + 'Refer to https://github.com/pytorch/audio/issues/1510 ' + 'for more details.' + ) + fb = torch.empty(0) if n_stft is None else F.create_fb_matrix( n_stft, self.f_min, self.f_max, self.n_mels, self.sample_rate, self.norm, self.mel_scale) self.register_buffer('fb', fb) + def __prepare_scriptable__(self): + r"""If `self.fb` is empty, the `forward` method will try to resize the parameter, + which does not work once the transform is scripted. However, this error does not happen + until the transform is executed. This is inconvenient especially if the resulting + TorchScript object is executed in other environments. Therefore, we check the + validity of `self.fb` here and fail if the resulting TS does not work. + + Returns: + MelScale: self + """ + if self.fb.numel() == 0: + raise ValueError("n_stft must be provided at construction") + return self + def forward(self, specgram: Tensor) -> Tensor: r""" Args: @@ -639,17 +666,40 @@ class Resample(torch.nn.Module): Args: orig_freq (float, optional): The original frequency of the signal. (Default: ``16000``) new_freq (float, optional): The desired frequency. (Default: ``16000``) - resampling_method (str, optional): The resampling method. (Default: ``'sinc_interpolation'``) + resampling_method (str, optional): The resampling method to use. + Options: [``sinc_interpolation``, ``kaiser_window``] (Default: ``'sinc_interpolation'``) + lowpass_filter_width (int, optional): Controls the sharpness of the filter, more == sharper + but less efficient. (Default: ``6``) + rolloff (float, optional): The roll-off frequency of the filter, as a fraction of the Nyquist. + Lower values reduce anti-aliasing, but also reduce some of the highest frequencies. (Default: ``0.99``) + beta (float or None): The shape parameter used for kaiser window. + + Note: If resampling on waveforms of higher precision than float32, there may be a small loss of precision + because the kernel is cached once as float32. If high precision resampling is important for your application, + the functional form will retain higher precision, but run slower because it does not cache the kernel. + Alternatively, you could rewrite a transform that caches a higher precision kernel. """ def __init__(self, - orig_freq: int = 16000, - new_freq: int = 16000, - resampling_method: str = 'sinc_interpolation') -> None: + orig_freq: float = 16000, + new_freq: float = 16000, + resampling_method: str = 'sinc_interpolation', + lowpass_filter_width: int = 6, + rolloff: float = 0.99, + beta: Optional[float] = None) -> None: super(Resample, self).__init__() + self.orig_freq = orig_freq self.new_freq = new_freq + self.gcd = math.gcd(int(self.orig_freq), int(self.new_freq)) self.resampling_method = resampling_method + self.lowpass_filter_width = lowpass_filter_width + self.rolloff = rolloff + + kernel, self.width = _get_sinc_resample_kernel(self.orig_freq, self.new_freq, self.gcd, + self.lowpass_filter_width, self.rolloff, + self.resampling_method, beta) + self.register_buffer('kernel', kernel) def forward(self, waveform: Tensor) -> Tensor: r""" @@ -659,10 +709,8 @@ def forward(self, waveform: Tensor) -> Tensor: Returns: Tensor: Output signal of dimension (..., time). """ - if self.resampling_method == 'sinc_interpolation': - return F.resample(waveform, self.orig_freq, self.new_freq) - - raise ValueError('Invalid resampling method: {}'.format(self.resampling_method)) + return _apply_sinc_resample_kernel(waveform, self.orig_freq, self.new_freq, self.gcd, + self.kernel, self.width) class ComplexNorm(torch.nn.Module): @@ -1078,7 +1126,10 @@ def __init__(self, def forward(self, waveform: Tensor) -> Tensor: r""" Args: - waveform (Tensor): Tensor of audio of dimension `(..., time)` + waveform (Tensor): Tensor of audio of dimension `(channels, time)` or `(time)` + Tensor of shape `(channels, time)` is treated as a multi-channel recording + of the same event and the resulting output will be trimmed to the earliest + voice activity in any channel. """ return F.vad( waveform=waveform, From 7198cc6d7ed83be39b8dc8aab56d5022e73380d7 Mon Sep 17 00:00:00 2001 From: Vasilis Vryniotis Date: Tue, 25 May 2021 11:04:49 -0700 Subject: [PATCH 50/73] Import audio #1497 ffe735bacfa918e6e21a5d751fd07afab3faaa15 Reviewed By: mthrok Differential Revision: D28678814 fbshipit-source-id: 3356fd88dc33ad9f20294ca19b0c3958ce55f1ae --- .circleci/config.yml | 1875 +++++++++++++++-- .circleci/config.yml.in | 20 +- .circleci/regenerate.py | 48 +- packaging/pkg_helpers.bash | 51 +- .../backend/sox_io/info_test.py | 11 + .../backend/sox_io/load_test.py | 11 + .../backend/sox_io/save_test.py | 13 + .../transforms/batch_consistency_test.py | 18 +- torchaudio/csrc/sox/effects.cpp | 4 +- torchaudio/csrc/sox/io.cpp | 9 +- torchaudio/csrc/sox/utils.cpp | 9 +- torchaudio/csrc/sox/utils.h | 5 +- 12 files changed, 1801 insertions(+), 273 deletions(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index 64a6ae9f9f..32c7effa9c 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -71,11 +71,23 @@ binary_common: &binary_common python_version: description: "Python version to build against (e.g., 3.8)" type: string + cuda_version: + description: "CUDA version to build against (e.g., cpu, cu101)" + type: string + default: "cpu" + wheel_docker_image: + description: "Wheel only: what docker image to use" + type: string + default: "pytorch/manylinux-cuda102" + conda_docker_image: + description: "Conda only: what docker image to use" + type: string + default: "pytorch/conda-builder:cuda102" environment: &environment PYTHON_VERSION: << parameters.python_version >> BUILD_VERSION: << parameters.build_version >> PYTORCH_VERSION: << parameters.pytorch_version >> - CU_VERSION: cpu + CU_VERSION: << parameters.cuda_version >> smoke_test_common: &smoke_test_common <<: *binary_common @@ -127,7 +139,7 @@ jobs: binary_linux_wheel: <<: *binary_common docker: - - image: "pytorch/manylinux-cuda102" + - image: << parameters.wheel_docker_image >> resource_class: 2xlarge+ steps: - checkout @@ -144,7 +156,7 @@ jobs: binary_linux_conda: <<: *binary_common docker: - - image: "pytorch/conda-cuda" + - image: "<< parameters.conda_docker_image >>" resource_class: 2xlarge+ steps: - checkout @@ -487,7 +499,7 @@ jobs: name: windows-gpu environment: <<: *environment - CUDA_VERSION: "10.1" + CUDA_VERSION: "10.2" steps: - checkout - designate_upload_channel @@ -619,114 +631,342 @@ workflows: - download_third_parties_nix: name: download_third_parties_nix - binary_linux_wheel: - name: binary_linux_wheel_py3.6 + cuda_version: cpu + name: binary_linux_wheel_py3.6_cpu + python_version: '3.6' + requires: + - download_third_parties_nix + - binary_linux_wheel: + cuda_version: cu102 + name: binary_linux_wheel_py3.6_cu102 + python_version: '3.6' + requires: + - download_third_parties_nix + wheel_docker_image: pytorch/manylinux-cuda102 + - binary_linux_wheel: + cuda_version: cu111 + name: binary_linux_wheel_py3.6_cu111 python_version: '3.6' requires: - download_third_parties_nix + wheel_docker_image: pytorch/manylinux-cuda111 + - binary_linux_wheel: + cuda_version: cpu + name: binary_linux_wheel_py3.7_cpu + python_version: '3.7' + requires: + - download_third_parties_nix + - binary_linux_wheel: + cuda_version: cu102 + name: binary_linux_wheel_py3.7_cu102 + python_version: '3.7' + requires: + - download_third_parties_nix + wheel_docker_image: pytorch/manylinux-cuda102 - binary_linux_wheel: - name: binary_linux_wheel_py3.7 + cuda_version: cu111 + name: binary_linux_wheel_py3.7_cu111 python_version: '3.7' requires: - download_third_parties_nix + wheel_docker_image: pytorch/manylinux-cuda111 + - binary_linux_wheel: + cuda_version: cpu + name: binary_linux_wheel_py3.8_cpu + python_version: '3.8' + requires: + - download_third_parties_nix + - binary_linux_wheel: + cuda_version: cu102 + name: binary_linux_wheel_py3.8_cu102 + python_version: '3.8' + requires: + - download_third_parties_nix + wheel_docker_image: pytorch/manylinux-cuda102 - binary_linux_wheel: - name: binary_linux_wheel_py3.8 + cuda_version: cu111 + name: binary_linux_wheel_py3.8_cu111 python_version: '3.8' requires: - download_third_parties_nix + wheel_docker_image: pytorch/manylinux-cuda111 + - binary_linux_wheel: + cuda_version: cpu + name: binary_linux_wheel_py3.9_cpu + python_version: '3.9' + requires: + - download_third_parties_nix + - binary_linux_wheel: + cuda_version: cu102 + name: binary_linux_wheel_py3.9_cu102 + python_version: '3.9' + requires: + - download_third_parties_nix + wheel_docker_image: pytorch/manylinux-cuda102 - binary_linux_wheel: - name: binary_linux_wheel_py3.9 + cuda_version: cu111 + name: binary_linux_wheel_py3.9_cu111 python_version: '3.9' requires: - download_third_parties_nix + wheel_docker_image: pytorch/manylinux-cuda111 - binary_macos_wheel: - name: binary_macos_wheel_py3.6 + cuda_version: cpu + name: binary_macos_wheel_py3.6_cpu python_version: '3.6' requires: - download_third_parties_nix - binary_macos_wheel: - name: binary_macos_wheel_py3.7 + cuda_version: cpu + name: binary_macos_wheel_py3.7_cpu python_version: '3.7' requires: - download_third_parties_nix - binary_macos_wheel: - name: binary_macos_wheel_py3.8 + cuda_version: cpu + name: binary_macos_wheel_py3.8_cpu python_version: '3.8' requires: - download_third_parties_nix - binary_macos_wheel: - name: binary_macos_wheel_py3.9 + cuda_version: cpu + name: binary_macos_wheel_py3.9_cpu python_version: '3.9' requires: - download_third_parties_nix - binary_windows_wheel: - name: binary_windows_wheel_py3.6 + cuda_version: cpu + name: binary_windows_wheel_py3.6_cpu + python_version: '3.6' + - binary_windows_wheel: + cuda_version: cu102 + name: binary_windows_wheel_py3.6_cu102 + python_version: '3.6' + wheel_docker_image: pytorch/manylinux-cuda102 + - binary_windows_wheel: + cuda_version: cu111 + name: binary_windows_wheel_py3.6_cu111 python_version: '3.6' + wheel_docker_image: pytorch/manylinux-cuda111 + - binary_windows_wheel: + cuda_version: cpu + name: binary_windows_wheel_py3.7_cpu + python_version: '3.7' + - binary_windows_wheel: + cuda_version: cu102 + name: binary_windows_wheel_py3.7_cu102 + python_version: '3.7' + wheel_docker_image: pytorch/manylinux-cuda102 - binary_windows_wheel: - name: binary_windows_wheel_py3.7 + cuda_version: cu111 + name: binary_windows_wheel_py3.7_cu111 python_version: '3.7' + wheel_docker_image: pytorch/manylinux-cuda111 + - binary_windows_wheel: + cuda_version: cpu + name: binary_windows_wheel_py3.8_cpu + python_version: '3.8' + - binary_windows_wheel: + cuda_version: cu102 + name: binary_windows_wheel_py3.8_cu102 + python_version: '3.8' + wheel_docker_image: pytorch/manylinux-cuda102 - binary_windows_wheel: - name: binary_windows_wheel_py3.8 + cuda_version: cu111 + name: binary_windows_wheel_py3.8_cu111 python_version: '3.8' + wheel_docker_image: pytorch/manylinux-cuda111 + - binary_windows_wheel: + cuda_version: cpu + name: binary_windows_wheel_py3.9_cpu + python_version: '3.9' + - binary_windows_wheel: + cuda_version: cu102 + name: binary_windows_wheel_py3.9_cu102 + python_version: '3.9' + wheel_docker_image: pytorch/manylinux-cuda102 - binary_windows_wheel: - name: binary_windows_wheel_py3.9 + cuda_version: cu111 + name: binary_windows_wheel_py3.9_cu111 python_version: '3.9' + wheel_docker_image: pytorch/manylinux-cuda111 + - binary_linux_conda: + conda_docker_image: pytorch/conda-builder:cpu + cuda_version: cpu + name: binary_linux_conda_py3.6_cpu + python_version: '3.6' + requires: + - download_third_parties_nix + - binary_linux_conda: + conda_docker_image: pytorch/conda-builder:cuda102 + cuda_version: cu102 + name: binary_linux_conda_py3.6_cu102 + python_version: '3.6' + requires: + - download_third_parties_nix - binary_linux_conda: - name: binary_linux_conda_py3.6 + conda_docker_image: pytorch/conda-builder:cuda111 + cuda_version: cu111 + name: binary_linux_conda_py3.6_cu111 python_version: '3.6' requires: - download_third_parties_nix - binary_linux_conda: - name: binary_linux_conda_py3.7 + conda_docker_image: pytorch/conda-builder:cpu + cuda_version: cpu + name: binary_linux_conda_py3.7_cpu + python_version: '3.7' + requires: + - download_third_parties_nix + - binary_linux_conda: + conda_docker_image: pytorch/conda-builder:cuda102 + cuda_version: cu102 + name: binary_linux_conda_py3.7_cu102 + python_version: '3.7' + requires: + - download_third_parties_nix + - binary_linux_conda: + conda_docker_image: pytorch/conda-builder:cuda111 + cuda_version: cu111 + name: binary_linux_conda_py3.7_cu111 python_version: '3.7' requires: - download_third_parties_nix - binary_linux_conda: - name: binary_linux_conda_py3.8 + conda_docker_image: pytorch/conda-builder:cpu + cuda_version: cpu + name: binary_linux_conda_py3.8_cpu + python_version: '3.8' + requires: + - download_third_parties_nix + - binary_linux_conda: + conda_docker_image: pytorch/conda-builder:cuda102 + cuda_version: cu102 + name: binary_linux_conda_py3.8_cu102 + python_version: '3.8' + requires: + - download_third_parties_nix + - binary_linux_conda: + conda_docker_image: pytorch/conda-builder:cuda111 + cuda_version: cu111 + name: binary_linux_conda_py3.8_cu111 python_version: '3.8' requires: - download_third_parties_nix - binary_linux_conda: - name: binary_linux_conda_py3.9 + conda_docker_image: pytorch/conda-builder:cpu + cuda_version: cpu + name: binary_linux_conda_py3.9_cpu + python_version: '3.9' + requires: + - download_third_parties_nix + - binary_linux_conda: + conda_docker_image: pytorch/conda-builder:cuda102 + cuda_version: cu102 + name: binary_linux_conda_py3.9_cu102 + python_version: '3.9' + requires: + - download_third_parties_nix + - binary_linux_conda: + conda_docker_image: pytorch/conda-builder:cuda111 + cuda_version: cu111 + name: binary_linux_conda_py3.9_cu111 python_version: '3.9' requires: - download_third_parties_nix - binary_macos_conda: - name: binary_macos_conda_py3.6 + conda_docker_image: pytorch/conda-builder:cpu + cuda_version: cpu + name: binary_macos_conda_py3.6_cpu python_version: '3.6' requires: - download_third_parties_nix - binary_macos_conda: - name: binary_macos_conda_py3.7 + conda_docker_image: pytorch/conda-builder:cpu + cuda_version: cpu + name: binary_macos_conda_py3.7_cpu python_version: '3.7' requires: - download_third_parties_nix - binary_macos_conda: - name: binary_macos_conda_py3.8 + conda_docker_image: pytorch/conda-builder:cpu + cuda_version: cpu + name: binary_macos_conda_py3.8_cpu python_version: '3.8' requires: - download_third_parties_nix - binary_macos_conda: - name: binary_macos_conda_py3.9 + conda_docker_image: pytorch/conda-builder:cpu + cuda_version: cpu + name: binary_macos_conda_py3.9_cpu python_version: '3.9' requires: - download_third_parties_nix - binary_windows_conda: - name: binary_windows_conda_py3.6 + conda_docker_image: pytorch/conda-builder:cpu + cuda_version: cpu + name: binary_windows_conda_py3.6_cpu + python_version: '3.6' + - binary_windows_conda: + conda_docker_image: pytorch/conda-builder:cuda102 + cuda_version: cu102 + name: binary_windows_conda_py3.6_cu102 + python_version: '3.6' + - binary_windows_conda: + conda_docker_image: pytorch/conda-builder:cuda111 + cuda_version: cu111 + name: binary_windows_conda_py3.6_cu111 python_version: '3.6' - binary_windows_conda: - name: binary_windows_conda_py3.7 + conda_docker_image: pytorch/conda-builder:cpu + cuda_version: cpu + name: binary_windows_conda_py3.7_cpu + python_version: '3.7' + - binary_windows_conda: + conda_docker_image: pytorch/conda-builder:cuda102 + cuda_version: cu102 + name: binary_windows_conda_py3.7_cu102 + python_version: '3.7' + - binary_windows_conda: + conda_docker_image: pytorch/conda-builder:cuda111 + cuda_version: cu111 + name: binary_windows_conda_py3.7_cu111 python_version: '3.7' - binary_windows_conda: - name: binary_windows_conda_py3.8 + conda_docker_image: pytorch/conda-builder:cpu + cuda_version: cpu + name: binary_windows_conda_py3.8_cpu + python_version: '3.8' + - binary_windows_conda: + conda_docker_image: pytorch/conda-builder:cuda102 + cuda_version: cu102 + name: binary_windows_conda_py3.8_cu102 + python_version: '3.8' + - binary_windows_conda: + conda_docker_image: pytorch/conda-builder:cuda111 + cuda_version: cu111 + name: binary_windows_conda_py3.8_cu111 python_version: '3.8' - binary_windows_conda: - name: binary_windows_conda_py3.9 + conda_docker_image: pytorch/conda-builder:cpu + cuda_version: cpu + name: binary_windows_conda_py3.9_cpu + python_version: '3.9' + - binary_windows_conda: + conda_docker_image: pytorch/conda-builder:cuda102 + cuda_version: cu102 + name: binary_windows_conda_py3.9_cu102 + python_version: '3.9' + - binary_windows_conda: + conda_docker_image: pytorch/conda-builder:cuda111 + cuda_version: cu111 + name: binary_windows_conda_py3.9_cu111 python_version: '3.9' - build_docs: name: build_docs python_version: '3.8' requires: - - binary_linux_wheel_py3.8 + - binary_linux_wheel_py3.8_cpu - upload_docs: context: org-member filters: @@ -743,94 +983,115 @@ workflows: name: docstring_parameters_sync python_version: '3.8' requires: - - binary_linux_wheel_py3.8 + - binary_linux_wheel_py3.8_cpu unittest: jobs: - download_third_parties_nix: name: download_third_parties_nix - unittest_linux_cpu: + cuda_version: cpu name: unittest_linux_cpu_py3.6 python_version: '3.6' requires: - download_third_parties_nix - stylecheck: + cuda_version: cpu name: stylecheck_py3.6 python_version: '3.6' - unittest_linux_cpu: + cuda_version: cpu name: unittest_linux_cpu_py3.7 python_version: '3.7' requires: - download_third_parties_nix - unittest_linux_cpu: + cuda_version: cpu name: unittest_linux_cpu_py3.8 python_version: '3.8' requires: - download_third_parties_nix - unittest_linux_cpu: + cuda_version: cpu name: unittest_linux_cpu_py3.9 python_version: '3.9' requires: - download_third_parties_nix - unittest_linux_gpu: + cuda_version: cu102 name: unittest_linux_gpu_py3.6 python_version: '3.6' requires: - download_third_parties_nix - unittest_linux_gpu: + cuda_version: cu102 name: unittest_linux_gpu_py3.7 python_version: '3.7' requires: - download_third_parties_nix - unittest_linux_gpu: + cuda_version: cu102 name: unittest_linux_gpu_py3.8 python_version: '3.8' requires: - download_third_parties_nix - unittest_linux_gpu: + cuda_version: cu102 name: unittest_linux_gpu_py3.9 python_version: '3.9' requires: - download_third_parties_nix - unittest_windows_cpu: + cuda_version: cpu name: unittest_windows_cpu_py3.6 python_version: '3.6' - unittest_windows_cpu: + cuda_version: cpu name: unittest_windows_cpu_py3.7 python_version: '3.7' - unittest_windows_cpu: + cuda_version: cpu name: unittest_windows_cpu_py3.8 python_version: '3.8' - unittest_windows_cpu: + cuda_version: cpu name: unittest_windows_cpu_py3.9 python_version: '3.9' - unittest_windows_gpu: + cuda_version: cu102 name: unittest_windows_gpu_py3.6 python_version: '3.6' - unittest_windows_gpu: + cuda_version: cu102 name: unittest_windows_gpu_py3.7 python_version: '3.7' - unittest_windows_gpu: + cuda_version: cu102 name: unittest_windows_gpu_py3.8 python_version: '3.8' - unittest_windows_gpu: + cuda_version: cu102 name: unittest_windows_gpu_py3.9 python_version: '3.9' - unittest_macos_cpu: + cuda_version: cpu name: unittest_macos_cpu_py3.6 python_version: '3.6' requires: - download_third_parties_nix - unittest_macos_cpu: + cuda_version: cpu name: unittest_macos_cpu_py3.7 python_version: '3.7' requires: - download_third_parties_nix - unittest_macos_cpu: + cuda_version: cpu name: unittest_macos_cpu_py3.8 python_version: '3.8' requires: - download_third_parties_nix - unittest_macos_cpu: + cuda_version: cpu name: unittest_macos_cpu_py3.9 python_version: '3.9' requires: @@ -850,13 +1111,14 @@ workflows: only: /v[0-9]+(\.[0-9]+)*-rc[0-9]+/ name: download_third_parties_nix - binary_linux_wheel: + cuda_version: cpu filters: branches: only: - nightly tags: only: /v[0-9]+(\.[0-9]+)*-rc[0-9]+/ - name: nightly_binary_linux_wheel_py3.6 + name: nightly_binary_linux_wheel_py3.6_cpu python_version: '3.6' requires: - download_third_parties_nix @@ -868,31 +1130,34 @@ workflows: - nightly tags: only: /v[0-9]+(\.[0-9]+)*-rc[0-9]+/ - name: nightly_binary_linux_wheel_py3.6_upload + name: nightly_binary_linux_wheel_py3.6_cpu_upload requires: - - nightly_binary_linux_wheel_py3.6 + - nightly_binary_linux_wheel_py3.6_cpu - smoke_test_linux_pip: + cuda_version: cpu filters: branches: only: - nightly tags: only: /v[0-9]+(\.[0-9]+)*-rc[0-9]+/ - name: nightly_binary_linux_wheel_py3.6_smoke_test_pip + name: nightly_binary_linux_wheel_py3.6_cpu_smoke_test_pip python_version: '3.6' requires: - - nightly_binary_linux_wheel_py3.6_upload + - nightly_binary_linux_wheel_py3.6_cpu_upload - binary_linux_wheel: + cuda_version: cu102 filters: branches: only: - nightly tags: only: /v[0-9]+(\.[0-9]+)*-rc[0-9]+/ - name: nightly_binary_linux_wheel_py3.7 - python_version: '3.7' + name: nightly_binary_linux_wheel_py3.6_cu102 + python_version: '3.6' requires: - download_third_parties_nix + wheel_docker_image: pytorch/manylinux-cuda102 - binary_wheel_upload: context: org-member filters: @@ -901,31 +1166,34 @@ workflows: - nightly tags: only: /v[0-9]+(\.[0-9]+)*-rc[0-9]+/ - name: nightly_binary_linux_wheel_py3.7_upload + name: nightly_binary_linux_wheel_py3.6_cu102_upload requires: - - nightly_binary_linux_wheel_py3.7 + - nightly_binary_linux_wheel_py3.6_cu102 - smoke_test_linux_pip: + cuda_version: cu102 filters: branches: only: - nightly tags: only: /v[0-9]+(\.[0-9]+)*-rc[0-9]+/ - name: nightly_binary_linux_wheel_py3.7_smoke_test_pip - python_version: '3.7' + name: nightly_binary_linux_wheel_py3.6_cu102_smoke_test_pip + python_version: '3.6' requires: - - nightly_binary_linux_wheel_py3.7_upload + - nightly_binary_linux_wheel_py3.6_cu102_upload - binary_linux_wheel: + cuda_version: cu111 filters: branches: only: - nightly tags: only: /v[0-9]+(\.[0-9]+)*-rc[0-9]+/ - name: nightly_binary_linux_wheel_py3.8 - python_version: '3.8' + name: nightly_binary_linux_wheel_py3.6_cu111 + python_version: '3.6' requires: - download_third_parties_nix + wheel_docker_image: pytorch/manylinux-cuda111 - binary_wheel_upload: context: org-member filters: @@ -934,29 +1202,31 @@ workflows: - nightly tags: only: /v[0-9]+(\.[0-9]+)*-rc[0-9]+/ - name: nightly_binary_linux_wheel_py3.8_upload + name: nightly_binary_linux_wheel_py3.6_cu111_upload requires: - - nightly_binary_linux_wheel_py3.8 + - nightly_binary_linux_wheel_py3.6_cu111 - smoke_test_linux_pip: + cuda_version: cu111 filters: branches: only: - nightly tags: only: /v[0-9]+(\.[0-9]+)*-rc[0-9]+/ - name: nightly_binary_linux_wheel_py3.8_smoke_test_pip - python_version: '3.8' + name: nightly_binary_linux_wheel_py3.6_cu111_smoke_test_pip + python_version: '3.6' requires: - - nightly_binary_linux_wheel_py3.8_upload + - nightly_binary_linux_wheel_py3.6_cu111_upload - binary_linux_wheel: + cuda_version: cpu filters: branches: only: - nightly tags: only: /v[0-9]+(\.[0-9]+)*-rc[0-9]+/ - name: nightly_binary_linux_wheel_py3.9 - python_version: '3.9' + name: nightly_binary_linux_wheel_py3.7_cpu + python_version: '3.7' requires: - download_third_parties_nix - binary_wheel_upload: @@ -967,31 +1237,34 @@ workflows: - nightly tags: only: /v[0-9]+(\.[0-9]+)*-rc[0-9]+/ - name: nightly_binary_linux_wheel_py3.9_upload + name: nightly_binary_linux_wheel_py3.7_cpu_upload requires: - - nightly_binary_linux_wheel_py3.9 + - nightly_binary_linux_wheel_py3.7_cpu - smoke_test_linux_pip: + cuda_version: cpu filters: branches: only: - nightly tags: only: /v[0-9]+(\.[0-9]+)*-rc[0-9]+/ - name: nightly_binary_linux_wheel_py3.9_smoke_test_pip - python_version: '3.9' + name: nightly_binary_linux_wheel_py3.7_cpu_smoke_test_pip + python_version: '3.7' requires: - - nightly_binary_linux_wheel_py3.9_upload - - binary_macos_wheel: + - nightly_binary_linux_wheel_py3.7_cpu_upload + - binary_linux_wheel: + cuda_version: cu102 filters: branches: only: - nightly tags: only: /v[0-9]+(\.[0-9]+)*-rc[0-9]+/ - name: nightly_binary_macos_wheel_py3.6 - python_version: '3.6' + name: nightly_binary_linux_wheel_py3.7_cu102 + python_version: '3.7' requires: - download_third_parties_nix + wheel_docker_image: pytorch/manylinux-cuda102 - binary_wheel_upload: context: org-member filters: @@ -1000,42 +1273,34 @@ workflows: - nightly tags: only: /v[0-9]+(\.[0-9]+)*-rc[0-9]+/ - name: nightly_binary_macos_wheel_py3.6_upload + name: nightly_binary_linux_wheel_py3.7_cu102_upload requires: - - nightly_binary_macos_wheel_py3.6 - - binary_macos_wheel: + - nightly_binary_linux_wheel_py3.7_cu102 + - smoke_test_linux_pip: + cuda_version: cu102 filters: branches: only: - nightly tags: only: /v[0-9]+(\.[0-9]+)*-rc[0-9]+/ - name: nightly_binary_macos_wheel_py3.7 + name: nightly_binary_linux_wheel_py3.7_cu102_smoke_test_pip python_version: '3.7' requires: - - download_third_parties_nix - - binary_wheel_upload: - context: org-member - filters: - branches: - only: - - nightly - tags: - only: /v[0-9]+(\.[0-9]+)*-rc[0-9]+/ - name: nightly_binary_macos_wheel_py3.7_upload - requires: - - nightly_binary_macos_wheel_py3.7 - - binary_macos_wheel: + - nightly_binary_linux_wheel_py3.7_cu102_upload + - binary_linux_wheel: + cuda_version: cu111 filters: branches: only: - nightly tags: only: /v[0-9]+(\.[0-9]+)*-rc[0-9]+/ - name: nightly_binary_macos_wheel_py3.8 - python_version: '3.8' + name: nightly_binary_linux_wheel_py3.7_cu111 + python_version: '3.7' requires: - download_third_parties_nix + wheel_docker_image: pytorch/manylinux-cuda111 - binary_wheel_upload: context: org-member filters: @@ -1044,40 +1309,33 @@ workflows: - nightly tags: only: /v[0-9]+(\.[0-9]+)*-rc[0-9]+/ - name: nightly_binary_macos_wheel_py3.8_upload + name: nightly_binary_linux_wheel_py3.7_cu111_upload requires: - - nightly_binary_macos_wheel_py3.8 - - binary_macos_wheel: + - nightly_binary_linux_wheel_py3.7_cu111 + - smoke_test_linux_pip: + cuda_version: cu111 filters: branches: only: - nightly tags: only: /v[0-9]+(\.[0-9]+)*-rc[0-9]+/ - name: nightly_binary_macos_wheel_py3.9 - python_version: '3.9' + name: nightly_binary_linux_wheel_py3.7_cu111_smoke_test_pip + python_version: '3.7' requires: - - download_third_parties_nix - - binary_wheel_upload: - context: org-member + - nightly_binary_linux_wheel_py3.7_cu111_upload + - binary_linux_wheel: + cuda_version: cpu filters: branches: only: - nightly tags: only: /v[0-9]+(\.[0-9]+)*-rc[0-9]+/ - name: nightly_binary_macos_wheel_py3.9_upload + name: nightly_binary_linux_wheel_py3.8_cpu + python_version: '3.8' requires: - - nightly_binary_macos_wheel_py3.9 - - binary_windows_wheel: - filters: - branches: - only: - - nightly - tags: - only: /v[0-9]+(\.[0-9]+)*-rc[0-9]+/ - name: nightly_binary_windows_wheel_py3.6 - python_version: '3.6' + - download_third_parties_nix - binary_wheel_upload: context: org-member filters: @@ -1086,29 +1344,34 @@ workflows: - nightly tags: only: /v[0-9]+(\.[0-9]+)*-rc[0-9]+/ - name: nightly_binary_windows_wheel_py3.6_upload + name: nightly_binary_linux_wheel_py3.8_cpu_upload requires: - - nightly_binary_windows_wheel_py3.6 - - smoke_test_windows_pip: + - nightly_binary_linux_wheel_py3.8_cpu + - smoke_test_linux_pip: + cuda_version: cpu filters: branches: only: - nightly tags: only: /v[0-9]+(\.[0-9]+)*-rc[0-9]+/ - name: nightly_binary_windows_wheel_py3.6_smoke_test_pip - python_version: '3.6' + name: nightly_binary_linux_wheel_py3.8_cpu_smoke_test_pip + python_version: '3.8' requires: - - nightly_binary_windows_wheel_py3.6_upload - - binary_windows_wheel: + - nightly_binary_linux_wheel_py3.8_cpu_upload + - binary_linux_wheel: + cuda_version: cu102 filters: branches: only: - nightly tags: only: /v[0-9]+(\.[0-9]+)*-rc[0-9]+/ - name: nightly_binary_windows_wheel_py3.7 - python_version: '3.7' + name: nightly_binary_linux_wheel_py3.8_cu102 + python_version: '3.8' + requires: + - download_third_parties_nix + wheel_docker_image: pytorch/manylinux-cuda102 - binary_wheel_upload: context: org-member filters: @@ -1117,29 +1380,34 @@ workflows: - nightly tags: only: /v[0-9]+(\.[0-9]+)*-rc[0-9]+/ - name: nightly_binary_windows_wheel_py3.7_upload + name: nightly_binary_linux_wheel_py3.8_cu102_upload requires: - - nightly_binary_windows_wheel_py3.7 - - smoke_test_windows_pip: + - nightly_binary_linux_wheel_py3.8_cu102 + - smoke_test_linux_pip: + cuda_version: cu102 filters: branches: only: - nightly tags: only: /v[0-9]+(\.[0-9]+)*-rc[0-9]+/ - name: nightly_binary_windows_wheel_py3.7_smoke_test_pip - python_version: '3.7' + name: nightly_binary_linux_wheel_py3.8_cu102_smoke_test_pip + python_version: '3.8' requires: - - nightly_binary_windows_wheel_py3.7_upload - - binary_windows_wheel: + - nightly_binary_linux_wheel_py3.8_cu102_upload + - binary_linux_wheel: + cuda_version: cu111 filters: branches: only: - nightly tags: only: /v[0-9]+(\.[0-9]+)*-rc[0-9]+/ - name: nightly_binary_windows_wheel_py3.8 + name: nightly_binary_linux_wheel_py3.8_cu111 python_version: '3.8' + requires: + - download_third_parties_nix + wheel_docker_image: pytorch/manylinux-cuda111 - binary_wheel_upload: context: org-member filters: @@ -1148,29 +1416,33 @@ workflows: - nightly tags: only: /v[0-9]+(\.[0-9]+)*-rc[0-9]+/ - name: nightly_binary_windows_wheel_py3.8_upload + name: nightly_binary_linux_wheel_py3.8_cu111_upload requires: - - nightly_binary_windows_wheel_py3.8 - - smoke_test_windows_pip: + - nightly_binary_linux_wheel_py3.8_cu111 + - smoke_test_linux_pip: + cuda_version: cu111 filters: branches: only: - nightly tags: only: /v[0-9]+(\.[0-9]+)*-rc[0-9]+/ - name: nightly_binary_windows_wheel_py3.8_smoke_test_pip + name: nightly_binary_linux_wheel_py3.8_cu111_smoke_test_pip python_version: '3.8' requires: - - nightly_binary_windows_wheel_py3.8_upload - - binary_windows_wheel: + - nightly_binary_linux_wheel_py3.8_cu111_upload + - binary_linux_wheel: + cuda_version: cpu filters: branches: only: - nightly tags: only: /v[0-9]+(\.[0-9]+)*-rc[0-9]+/ - name: nightly_binary_windows_wheel_py3.9 + name: nightly_binary_linux_wheel_py3.9_cpu python_version: '3.9' + requires: + - download_third_parties_nix - binary_wheel_upload: context: org-member filters: @@ -1179,32 +1451,35 @@ workflows: - nightly tags: only: /v[0-9]+(\.[0-9]+)*-rc[0-9]+/ - name: nightly_binary_windows_wheel_py3.9_upload + name: nightly_binary_linux_wheel_py3.9_cpu_upload requires: - - nightly_binary_windows_wheel_py3.9 - - smoke_test_windows_pip: + - nightly_binary_linux_wheel_py3.9_cpu + - smoke_test_linux_pip: + cuda_version: cpu filters: branches: only: - nightly tags: only: /v[0-9]+(\.[0-9]+)*-rc[0-9]+/ - name: nightly_binary_windows_wheel_py3.9_smoke_test_pip + name: nightly_binary_linux_wheel_py3.9_cpu_smoke_test_pip python_version: '3.9' requires: - - nightly_binary_windows_wheel_py3.9_upload - - binary_linux_conda: + - nightly_binary_linux_wheel_py3.9_cpu_upload + - binary_linux_wheel: + cuda_version: cu102 filters: branches: only: - nightly tags: only: /v[0-9]+(\.[0-9]+)*-rc[0-9]+/ - name: nightly_binary_linux_conda_py3.6 - python_version: '3.6' + name: nightly_binary_linux_wheel_py3.9_cu102 + python_version: '3.9' requires: - download_third_parties_nix - - binary_conda_upload: + wheel_docker_image: pytorch/manylinux-cuda102 + - binary_wheel_upload: context: org-member filters: branches: @@ -1212,32 +1487,35 @@ workflows: - nightly tags: only: /v[0-9]+(\.[0-9]+)*-rc[0-9]+/ - name: nightly_binary_linux_conda_py3.6_upload + name: nightly_binary_linux_wheel_py3.9_cu102_upload requires: - - nightly_binary_linux_conda_py3.6 - - smoke_test_linux_conda: + - nightly_binary_linux_wheel_py3.9_cu102 + - smoke_test_linux_pip: + cuda_version: cu102 filters: branches: only: - nightly tags: only: /v[0-9]+(\.[0-9]+)*-rc[0-9]+/ - name: nightly_binary_linux_conda_py3.6_smoke_test_conda - python_version: '3.6' + name: nightly_binary_linux_wheel_py3.9_cu102_smoke_test_pip + python_version: '3.9' requires: - - nightly_binary_linux_conda_py3.6_upload - - binary_linux_conda: + - nightly_binary_linux_wheel_py3.9_cu102_upload + - binary_linux_wheel: + cuda_version: cu111 filters: branches: only: - nightly tags: only: /v[0-9]+(\.[0-9]+)*-rc[0-9]+/ - name: nightly_binary_linux_conda_py3.7 - python_version: '3.7' + name: nightly_binary_linux_wheel_py3.9_cu111 + python_version: '3.9' requires: - download_third_parties_nix - - binary_conda_upload: + wheel_docker_image: pytorch/manylinux-cuda111 + - binary_wheel_upload: context: org-member filters: branches: @@ -1245,32 +1523,34 @@ workflows: - nightly tags: only: /v[0-9]+(\.[0-9]+)*-rc[0-9]+/ - name: nightly_binary_linux_conda_py3.7_upload + name: nightly_binary_linux_wheel_py3.9_cu111_upload requires: - - nightly_binary_linux_conda_py3.7 - - smoke_test_linux_conda: + - nightly_binary_linux_wheel_py3.9_cu111 + - smoke_test_linux_pip: + cuda_version: cu111 filters: branches: only: - nightly tags: only: /v[0-9]+(\.[0-9]+)*-rc[0-9]+/ - name: nightly_binary_linux_conda_py3.7_smoke_test_conda - python_version: '3.7' + name: nightly_binary_linux_wheel_py3.9_cu111_smoke_test_pip + python_version: '3.9' requires: - - nightly_binary_linux_conda_py3.7_upload - - binary_linux_conda: + - nightly_binary_linux_wheel_py3.9_cu111_upload + - binary_macos_wheel: + cuda_version: cpu filters: branches: only: - nightly tags: only: /v[0-9]+(\.[0-9]+)*-rc[0-9]+/ - name: nightly_binary_linux_conda_py3.8 - python_version: '3.8' + name: nightly_binary_macos_wheel_py3.6_cpu + python_version: '3.6' requires: - download_third_parties_nix - - binary_conda_upload: + - binary_wheel_upload: context: org-member filters: branches: @@ -1278,65 +1558,68 @@ workflows: - nightly tags: only: /v[0-9]+(\.[0-9]+)*-rc[0-9]+/ - name: nightly_binary_linux_conda_py3.8_upload + name: nightly_binary_macos_wheel_py3.6_cpu_upload requires: - - nightly_binary_linux_conda_py3.8 - - smoke_test_linux_conda: + - nightly_binary_macos_wheel_py3.6_cpu + - binary_macos_wheel: + cuda_version: cpu filters: branches: only: - nightly tags: only: /v[0-9]+(\.[0-9]+)*-rc[0-9]+/ - name: nightly_binary_linux_conda_py3.8_smoke_test_conda - python_version: '3.8' + name: nightly_binary_macos_wheel_py3.7_cpu + python_version: '3.7' requires: - - nightly_binary_linux_conda_py3.8_upload - - binary_linux_conda: + - download_third_parties_nix + - binary_wheel_upload: + context: org-member filters: branches: only: - nightly tags: only: /v[0-9]+(\.[0-9]+)*-rc[0-9]+/ - name: nightly_binary_linux_conda_py3.9 - python_version: '3.9' + name: nightly_binary_macos_wheel_py3.7_cpu_upload requires: - - download_third_parties_nix - - binary_conda_upload: - context: org-member + - nightly_binary_macos_wheel_py3.7_cpu + - binary_macos_wheel: + cuda_version: cpu filters: branches: only: - nightly tags: only: /v[0-9]+(\.[0-9]+)*-rc[0-9]+/ - name: nightly_binary_linux_conda_py3.9_upload + name: nightly_binary_macos_wheel_py3.8_cpu + python_version: '3.8' requires: - - nightly_binary_linux_conda_py3.9 - - smoke_test_linux_conda: + - download_third_parties_nix + - binary_wheel_upload: + context: org-member filters: branches: only: - nightly tags: only: /v[0-9]+(\.[0-9]+)*-rc[0-9]+/ - name: nightly_binary_linux_conda_py3.9_smoke_test_conda - python_version: '3.9' + name: nightly_binary_macos_wheel_py3.8_cpu_upload requires: - - nightly_binary_linux_conda_py3.9_upload - - binary_macos_conda: + - nightly_binary_macos_wheel_py3.8_cpu + - binary_macos_wheel: + cuda_version: cpu filters: branches: only: - nightly tags: only: /v[0-9]+(\.[0-9]+)*-rc[0-9]+/ - name: nightly_binary_macos_conda_py3.6 - python_version: '3.6' + name: nightly_binary_macos_wheel_py3.9_cpu + python_version: '3.9' requires: - download_third_parties_nix - - binary_conda_upload: + - binary_wheel_upload: context: org-member filters: branches: @@ -1344,21 +1627,20 @@ workflows: - nightly tags: only: /v[0-9]+(\.[0-9]+)*-rc[0-9]+/ - name: nightly_binary_macos_conda_py3.6_upload + name: nightly_binary_macos_wheel_py3.9_cpu_upload requires: - - nightly_binary_macos_conda_py3.6 - - binary_macos_conda: + - nightly_binary_macos_wheel_py3.9_cpu + - binary_windows_wheel: + cuda_version: cpu filters: branches: only: - nightly tags: only: /v[0-9]+(\.[0-9]+)*-rc[0-9]+/ - name: nightly_binary_macos_conda_py3.7 - python_version: '3.7' - requires: - - download_third_parties_nix - - binary_conda_upload: + name: nightly_binary_windows_wheel_py3.6_cpu + python_version: '3.6' + - binary_wheel_upload: context: org-member filters: branches: @@ -1366,63 +1648,1000 @@ workflows: - nightly tags: only: /v[0-9]+(\.[0-9]+)*-rc[0-9]+/ - name: nightly_binary_macos_conda_py3.7_upload + name: nightly_binary_windows_wheel_py3.6_cpu_upload requires: - - nightly_binary_macos_conda_py3.7 - - binary_macos_conda: + - nightly_binary_windows_wheel_py3.6_cpu + - smoke_test_windows_pip: + cuda_version: cpu filters: branches: only: - nightly tags: only: /v[0-9]+(\.[0-9]+)*-rc[0-9]+/ - name: nightly_binary_macos_conda_py3.8 - python_version: '3.8' + name: nightly_binary_windows_wheel_py3.6_cpu_smoke_test_pip + python_version: '3.6' requires: - - download_third_parties_nix - - binary_conda_upload: - context: org-member + - nightly_binary_windows_wheel_py3.6_cpu_upload + - binary_windows_wheel: + cuda_version: cu102 filters: branches: only: - nightly tags: only: /v[0-9]+(\.[0-9]+)*-rc[0-9]+/ - name: nightly_binary_macos_conda_py3.8_upload - requires: - - nightly_binary_macos_conda_py3.8 - - binary_macos_conda: + name: nightly_binary_windows_wheel_py3.6_cu102 + python_version: '3.6' + wheel_docker_image: pytorch/manylinux-cuda102 + - binary_wheel_upload: + context: org-member filters: branches: only: - nightly tags: only: /v[0-9]+(\.[0-9]+)*-rc[0-9]+/ - name: nightly_binary_macos_conda_py3.9 - python_version: '3.9' + name: nightly_binary_windows_wheel_py3.6_cu102_upload requires: - - download_third_parties_nix - - binary_conda_upload: - context: org-member + - nightly_binary_windows_wheel_py3.6_cu102 + - smoke_test_windows_pip: + cuda_version: cu102 filters: branches: only: - nightly tags: only: /v[0-9]+(\.[0-9]+)*-rc[0-9]+/ - name: nightly_binary_macos_conda_py3.9_upload + name: nightly_binary_windows_wheel_py3.6_cu102_smoke_test_pip + python_version: '3.6' requires: - - nightly_binary_macos_conda_py3.9 - - binary_windows_conda: + - nightly_binary_windows_wheel_py3.6_cu102_upload + - binary_windows_wheel: + cuda_version: cu111 filters: branches: only: - nightly tags: only: /v[0-9]+(\.[0-9]+)*-rc[0-9]+/ - name: nightly_binary_windows_conda_py3.6 + name: nightly_binary_windows_wheel_py3.6_cu111 python_version: '3.6' - - binary_conda_upload: + wheel_docker_image: pytorch/manylinux-cuda111 + - binary_wheel_upload: + context: org-member + filters: + branches: + only: + - nightly + tags: + only: /v[0-9]+(\.[0-9]+)*-rc[0-9]+/ + name: nightly_binary_windows_wheel_py3.6_cu111_upload + requires: + - nightly_binary_windows_wheel_py3.6_cu111 + - smoke_test_windows_pip: + cuda_version: cu111 + filters: + branches: + only: + - nightly + tags: + only: /v[0-9]+(\.[0-9]+)*-rc[0-9]+/ + name: nightly_binary_windows_wheel_py3.6_cu111_smoke_test_pip + python_version: '3.6' + requires: + - nightly_binary_windows_wheel_py3.6_cu111_upload + - binary_windows_wheel: + cuda_version: cpu + filters: + branches: + only: + - nightly + tags: + only: /v[0-9]+(\.[0-9]+)*-rc[0-9]+/ + name: nightly_binary_windows_wheel_py3.7_cpu + python_version: '3.7' + - binary_wheel_upload: + context: org-member + filters: + branches: + only: + - nightly + tags: + only: /v[0-9]+(\.[0-9]+)*-rc[0-9]+/ + name: nightly_binary_windows_wheel_py3.7_cpu_upload + requires: + - nightly_binary_windows_wheel_py3.7_cpu + - smoke_test_windows_pip: + cuda_version: cpu + filters: + branches: + only: + - nightly + tags: + only: /v[0-9]+(\.[0-9]+)*-rc[0-9]+/ + name: nightly_binary_windows_wheel_py3.7_cpu_smoke_test_pip + python_version: '3.7' + requires: + - nightly_binary_windows_wheel_py3.7_cpu_upload + - binary_windows_wheel: + cuda_version: cu102 + filters: + branches: + only: + - nightly + tags: + only: /v[0-9]+(\.[0-9]+)*-rc[0-9]+/ + name: nightly_binary_windows_wheel_py3.7_cu102 + python_version: '3.7' + wheel_docker_image: pytorch/manylinux-cuda102 + - binary_wheel_upload: + context: org-member + filters: + branches: + only: + - nightly + tags: + only: /v[0-9]+(\.[0-9]+)*-rc[0-9]+/ + name: nightly_binary_windows_wheel_py3.7_cu102_upload + requires: + - nightly_binary_windows_wheel_py3.7_cu102 + - smoke_test_windows_pip: + cuda_version: cu102 + filters: + branches: + only: + - nightly + tags: + only: /v[0-9]+(\.[0-9]+)*-rc[0-9]+/ + name: nightly_binary_windows_wheel_py3.7_cu102_smoke_test_pip + python_version: '3.7' + requires: + - nightly_binary_windows_wheel_py3.7_cu102_upload + - binary_windows_wheel: + cuda_version: cu111 + filters: + branches: + only: + - nightly + tags: + only: /v[0-9]+(\.[0-9]+)*-rc[0-9]+/ + name: nightly_binary_windows_wheel_py3.7_cu111 + python_version: '3.7' + wheel_docker_image: pytorch/manylinux-cuda111 + - binary_wheel_upload: + context: org-member + filters: + branches: + only: + - nightly + tags: + only: /v[0-9]+(\.[0-9]+)*-rc[0-9]+/ + name: nightly_binary_windows_wheel_py3.7_cu111_upload + requires: + - nightly_binary_windows_wheel_py3.7_cu111 + - smoke_test_windows_pip: + cuda_version: cu111 + filters: + branches: + only: + - nightly + tags: + only: /v[0-9]+(\.[0-9]+)*-rc[0-9]+/ + name: nightly_binary_windows_wheel_py3.7_cu111_smoke_test_pip + python_version: '3.7' + requires: + - nightly_binary_windows_wheel_py3.7_cu111_upload + - binary_windows_wheel: + cuda_version: cpu + filters: + branches: + only: + - nightly + tags: + only: /v[0-9]+(\.[0-9]+)*-rc[0-9]+/ + name: nightly_binary_windows_wheel_py3.8_cpu + python_version: '3.8' + - binary_wheel_upload: + context: org-member + filters: + branches: + only: + - nightly + tags: + only: /v[0-9]+(\.[0-9]+)*-rc[0-9]+/ + name: nightly_binary_windows_wheel_py3.8_cpu_upload + requires: + - nightly_binary_windows_wheel_py3.8_cpu + - smoke_test_windows_pip: + cuda_version: cpu + filters: + branches: + only: + - nightly + tags: + only: /v[0-9]+(\.[0-9]+)*-rc[0-9]+/ + name: nightly_binary_windows_wheel_py3.8_cpu_smoke_test_pip + python_version: '3.8' + requires: + - nightly_binary_windows_wheel_py3.8_cpu_upload + - binary_windows_wheel: + cuda_version: cu102 + filters: + branches: + only: + - nightly + tags: + only: /v[0-9]+(\.[0-9]+)*-rc[0-9]+/ + name: nightly_binary_windows_wheel_py3.8_cu102 + python_version: '3.8' + wheel_docker_image: pytorch/manylinux-cuda102 + - binary_wheel_upload: + context: org-member + filters: + branches: + only: + - nightly + tags: + only: /v[0-9]+(\.[0-9]+)*-rc[0-9]+/ + name: nightly_binary_windows_wheel_py3.8_cu102_upload + requires: + - nightly_binary_windows_wheel_py3.8_cu102 + - smoke_test_windows_pip: + cuda_version: cu102 + filters: + branches: + only: + - nightly + tags: + only: /v[0-9]+(\.[0-9]+)*-rc[0-9]+/ + name: nightly_binary_windows_wheel_py3.8_cu102_smoke_test_pip + python_version: '3.8' + requires: + - nightly_binary_windows_wheel_py3.8_cu102_upload + - binary_windows_wheel: + cuda_version: cu111 + filters: + branches: + only: + - nightly + tags: + only: /v[0-9]+(\.[0-9]+)*-rc[0-9]+/ + name: nightly_binary_windows_wheel_py3.8_cu111 + python_version: '3.8' + wheel_docker_image: pytorch/manylinux-cuda111 + - binary_wheel_upload: + context: org-member + filters: + branches: + only: + - nightly + tags: + only: /v[0-9]+(\.[0-9]+)*-rc[0-9]+/ + name: nightly_binary_windows_wheel_py3.8_cu111_upload + requires: + - nightly_binary_windows_wheel_py3.8_cu111 + - smoke_test_windows_pip: + cuda_version: cu111 + filters: + branches: + only: + - nightly + tags: + only: /v[0-9]+(\.[0-9]+)*-rc[0-9]+/ + name: nightly_binary_windows_wheel_py3.8_cu111_smoke_test_pip + python_version: '3.8' + requires: + - nightly_binary_windows_wheel_py3.8_cu111_upload + - binary_windows_wheel: + cuda_version: cpu + filters: + branches: + only: + - nightly + tags: + only: /v[0-9]+(\.[0-9]+)*-rc[0-9]+/ + name: nightly_binary_windows_wheel_py3.9_cpu + python_version: '3.9' + - binary_wheel_upload: + context: org-member + filters: + branches: + only: + - nightly + tags: + only: /v[0-9]+(\.[0-9]+)*-rc[0-9]+/ + name: nightly_binary_windows_wheel_py3.9_cpu_upload + requires: + - nightly_binary_windows_wheel_py3.9_cpu + - smoke_test_windows_pip: + cuda_version: cpu + filters: + branches: + only: + - nightly + tags: + only: /v[0-9]+(\.[0-9]+)*-rc[0-9]+/ + name: nightly_binary_windows_wheel_py3.9_cpu_smoke_test_pip + python_version: '3.9' + requires: + - nightly_binary_windows_wheel_py3.9_cpu_upload + - binary_windows_wheel: + cuda_version: cu102 + filters: + branches: + only: + - nightly + tags: + only: /v[0-9]+(\.[0-9]+)*-rc[0-9]+/ + name: nightly_binary_windows_wheel_py3.9_cu102 + python_version: '3.9' + wheel_docker_image: pytorch/manylinux-cuda102 + - binary_wheel_upload: + context: org-member + filters: + branches: + only: + - nightly + tags: + only: /v[0-9]+(\.[0-9]+)*-rc[0-9]+/ + name: nightly_binary_windows_wheel_py3.9_cu102_upload + requires: + - nightly_binary_windows_wheel_py3.9_cu102 + - smoke_test_windows_pip: + cuda_version: cu102 + filters: + branches: + only: + - nightly + tags: + only: /v[0-9]+(\.[0-9]+)*-rc[0-9]+/ + name: nightly_binary_windows_wheel_py3.9_cu102_smoke_test_pip + python_version: '3.9' + requires: + - nightly_binary_windows_wheel_py3.9_cu102_upload + - binary_windows_wheel: + cuda_version: cu111 + filters: + branches: + only: + - nightly + tags: + only: /v[0-9]+(\.[0-9]+)*-rc[0-9]+/ + name: nightly_binary_windows_wheel_py3.9_cu111 + python_version: '3.9' + wheel_docker_image: pytorch/manylinux-cuda111 + - binary_wheel_upload: + context: org-member + filters: + branches: + only: + - nightly + tags: + only: /v[0-9]+(\.[0-9]+)*-rc[0-9]+/ + name: nightly_binary_windows_wheel_py3.9_cu111_upload + requires: + - nightly_binary_windows_wheel_py3.9_cu111 + - smoke_test_windows_pip: + cuda_version: cu111 + filters: + branches: + only: + - nightly + tags: + only: /v[0-9]+(\.[0-9]+)*-rc[0-9]+/ + name: nightly_binary_windows_wheel_py3.9_cu111_smoke_test_pip + python_version: '3.9' + requires: + - nightly_binary_windows_wheel_py3.9_cu111_upload + - binary_linux_conda: + conda_docker_image: pytorch/conda-builder:cpu + cuda_version: cpu + filters: + branches: + only: + - nightly + tags: + only: /v[0-9]+(\.[0-9]+)*-rc[0-9]+/ + name: nightly_binary_linux_conda_py3.6_cpu + python_version: '3.6' + requires: + - download_third_parties_nix + - binary_conda_upload: + context: org-member + filters: + branches: + only: + - nightly + tags: + only: /v[0-9]+(\.[0-9]+)*-rc[0-9]+/ + name: nightly_binary_linux_conda_py3.6_cpu_upload + requires: + - nightly_binary_linux_conda_py3.6_cpu + - smoke_test_linux_conda: + cuda_version: cpu + filters: + branches: + only: + - nightly + tags: + only: /v[0-9]+(\.[0-9]+)*-rc[0-9]+/ + name: nightly_binary_linux_conda_py3.6_cpu_smoke_test_conda + python_version: '3.6' + requires: + - nightly_binary_linux_conda_py3.6_cpu_upload + - binary_linux_conda: + conda_docker_image: pytorch/conda-builder:cuda102 + cuda_version: cu102 + filters: + branches: + only: + - nightly + tags: + only: /v[0-9]+(\.[0-9]+)*-rc[0-9]+/ + name: nightly_binary_linux_conda_py3.6_cu102 + python_version: '3.6' + requires: + - download_third_parties_nix + - binary_conda_upload: + context: org-member + filters: + branches: + only: + - nightly + tags: + only: /v[0-9]+(\.[0-9]+)*-rc[0-9]+/ + name: nightly_binary_linux_conda_py3.6_cu102_upload + requires: + - nightly_binary_linux_conda_py3.6_cu102 + - smoke_test_linux_conda: + cuda_version: cu102 + filters: + branches: + only: + - nightly + tags: + only: /v[0-9]+(\.[0-9]+)*-rc[0-9]+/ + name: nightly_binary_linux_conda_py3.6_cu102_smoke_test_conda + python_version: '3.6' + requires: + - nightly_binary_linux_conda_py3.6_cu102_upload + - binary_linux_conda: + conda_docker_image: pytorch/conda-builder:cuda111 + cuda_version: cu111 + filters: + branches: + only: + - nightly + tags: + only: /v[0-9]+(\.[0-9]+)*-rc[0-9]+/ + name: nightly_binary_linux_conda_py3.6_cu111 + python_version: '3.6' + requires: + - download_third_parties_nix + - binary_conda_upload: + context: org-member + filters: + branches: + only: + - nightly + tags: + only: /v[0-9]+(\.[0-9]+)*-rc[0-9]+/ + name: nightly_binary_linux_conda_py3.6_cu111_upload + requires: + - nightly_binary_linux_conda_py3.6_cu111 + - smoke_test_linux_conda: + cuda_version: cu111 + filters: + branches: + only: + - nightly + tags: + only: /v[0-9]+(\.[0-9]+)*-rc[0-9]+/ + name: nightly_binary_linux_conda_py3.6_cu111_smoke_test_conda + python_version: '3.6' + requires: + - nightly_binary_linux_conda_py3.6_cu111_upload + - binary_linux_conda: + conda_docker_image: pytorch/conda-builder:cpu + cuda_version: cpu + filters: + branches: + only: + - nightly + tags: + only: /v[0-9]+(\.[0-9]+)*-rc[0-9]+/ + name: nightly_binary_linux_conda_py3.7_cpu + python_version: '3.7' + requires: + - download_third_parties_nix + - binary_conda_upload: + context: org-member + filters: + branches: + only: + - nightly + tags: + only: /v[0-9]+(\.[0-9]+)*-rc[0-9]+/ + name: nightly_binary_linux_conda_py3.7_cpu_upload + requires: + - nightly_binary_linux_conda_py3.7_cpu + - smoke_test_linux_conda: + cuda_version: cpu + filters: + branches: + only: + - nightly + tags: + only: /v[0-9]+(\.[0-9]+)*-rc[0-9]+/ + name: nightly_binary_linux_conda_py3.7_cpu_smoke_test_conda + python_version: '3.7' + requires: + - nightly_binary_linux_conda_py3.7_cpu_upload + - binary_linux_conda: + conda_docker_image: pytorch/conda-builder:cuda102 + cuda_version: cu102 + filters: + branches: + only: + - nightly + tags: + only: /v[0-9]+(\.[0-9]+)*-rc[0-9]+/ + name: nightly_binary_linux_conda_py3.7_cu102 + python_version: '3.7' + requires: + - download_third_parties_nix + - binary_conda_upload: + context: org-member + filters: + branches: + only: + - nightly + tags: + only: /v[0-9]+(\.[0-9]+)*-rc[0-9]+/ + name: nightly_binary_linux_conda_py3.7_cu102_upload + requires: + - nightly_binary_linux_conda_py3.7_cu102 + - smoke_test_linux_conda: + cuda_version: cu102 + filters: + branches: + only: + - nightly + tags: + only: /v[0-9]+(\.[0-9]+)*-rc[0-9]+/ + name: nightly_binary_linux_conda_py3.7_cu102_smoke_test_conda + python_version: '3.7' + requires: + - nightly_binary_linux_conda_py3.7_cu102_upload + - binary_linux_conda: + conda_docker_image: pytorch/conda-builder:cuda111 + cuda_version: cu111 + filters: + branches: + only: + - nightly + tags: + only: /v[0-9]+(\.[0-9]+)*-rc[0-9]+/ + name: nightly_binary_linux_conda_py3.7_cu111 + python_version: '3.7' + requires: + - download_third_parties_nix + - binary_conda_upload: + context: org-member + filters: + branches: + only: + - nightly + tags: + only: /v[0-9]+(\.[0-9]+)*-rc[0-9]+/ + name: nightly_binary_linux_conda_py3.7_cu111_upload + requires: + - nightly_binary_linux_conda_py3.7_cu111 + - smoke_test_linux_conda: + cuda_version: cu111 + filters: + branches: + only: + - nightly + tags: + only: /v[0-9]+(\.[0-9]+)*-rc[0-9]+/ + name: nightly_binary_linux_conda_py3.7_cu111_smoke_test_conda + python_version: '3.7' + requires: + - nightly_binary_linux_conda_py3.7_cu111_upload + - binary_linux_conda: + conda_docker_image: pytorch/conda-builder:cpu + cuda_version: cpu + filters: + branches: + only: + - nightly + tags: + only: /v[0-9]+(\.[0-9]+)*-rc[0-9]+/ + name: nightly_binary_linux_conda_py3.8_cpu + python_version: '3.8' + requires: + - download_third_parties_nix + - binary_conda_upload: + context: org-member + filters: + branches: + only: + - nightly + tags: + only: /v[0-9]+(\.[0-9]+)*-rc[0-9]+/ + name: nightly_binary_linux_conda_py3.8_cpu_upload + requires: + - nightly_binary_linux_conda_py3.8_cpu + - smoke_test_linux_conda: + cuda_version: cpu + filters: + branches: + only: + - nightly + tags: + only: /v[0-9]+(\.[0-9]+)*-rc[0-9]+/ + name: nightly_binary_linux_conda_py3.8_cpu_smoke_test_conda + python_version: '3.8' + requires: + - nightly_binary_linux_conda_py3.8_cpu_upload + - binary_linux_conda: + conda_docker_image: pytorch/conda-builder:cuda102 + cuda_version: cu102 + filters: + branches: + only: + - nightly + tags: + only: /v[0-9]+(\.[0-9]+)*-rc[0-9]+/ + name: nightly_binary_linux_conda_py3.8_cu102 + python_version: '3.8' + requires: + - download_third_parties_nix + - binary_conda_upload: + context: org-member + filters: + branches: + only: + - nightly + tags: + only: /v[0-9]+(\.[0-9]+)*-rc[0-9]+/ + name: nightly_binary_linux_conda_py3.8_cu102_upload + requires: + - nightly_binary_linux_conda_py3.8_cu102 + - smoke_test_linux_conda: + cuda_version: cu102 + filters: + branches: + only: + - nightly + tags: + only: /v[0-9]+(\.[0-9]+)*-rc[0-9]+/ + name: nightly_binary_linux_conda_py3.8_cu102_smoke_test_conda + python_version: '3.8' + requires: + - nightly_binary_linux_conda_py3.8_cu102_upload + - binary_linux_conda: + conda_docker_image: pytorch/conda-builder:cuda111 + cuda_version: cu111 + filters: + branches: + only: + - nightly + tags: + only: /v[0-9]+(\.[0-9]+)*-rc[0-9]+/ + name: nightly_binary_linux_conda_py3.8_cu111 + python_version: '3.8' + requires: + - download_third_parties_nix + - binary_conda_upload: + context: org-member + filters: + branches: + only: + - nightly + tags: + only: /v[0-9]+(\.[0-9]+)*-rc[0-9]+/ + name: nightly_binary_linux_conda_py3.8_cu111_upload + requires: + - nightly_binary_linux_conda_py3.8_cu111 + - smoke_test_linux_conda: + cuda_version: cu111 + filters: + branches: + only: + - nightly + tags: + only: /v[0-9]+(\.[0-9]+)*-rc[0-9]+/ + name: nightly_binary_linux_conda_py3.8_cu111_smoke_test_conda + python_version: '3.8' + requires: + - nightly_binary_linux_conda_py3.8_cu111_upload + - binary_linux_conda: + conda_docker_image: pytorch/conda-builder:cpu + cuda_version: cpu + filters: + branches: + only: + - nightly + tags: + only: /v[0-9]+(\.[0-9]+)*-rc[0-9]+/ + name: nightly_binary_linux_conda_py3.9_cpu + python_version: '3.9' + requires: + - download_third_parties_nix + - binary_conda_upload: + context: org-member + filters: + branches: + only: + - nightly + tags: + only: /v[0-9]+(\.[0-9]+)*-rc[0-9]+/ + name: nightly_binary_linux_conda_py3.9_cpu_upload + requires: + - nightly_binary_linux_conda_py3.9_cpu + - smoke_test_linux_conda: + cuda_version: cpu + filters: + branches: + only: + - nightly + tags: + only: /v[0-9]+(\.[0-9]+)*-rc[0-9]+/ + name: nightly_binary_linux_conda_py3.9_cpu_smoke_test_conda + python_version: '3.9' + requires: + - nightly_binary_linux_conda_py3.9_cpu_upload + - binary_linux_conda: + conda_docker_image: pytorch/conda-builder:cuda102 + cuda_version: cu102 + filters: + branches: + only: + - nightly + tags: + only: /v[0-9]+(\.[0-9]+)*-rc[0-9]+/ + name: nightly_binary_linux_conda_py3.9_cu102 + python_version: '3.9' + requires: + - download_third_parties_nix + - binary_conda_upload: + context: org-member + filters: + branches: + only: + - nightly + tags: + only: /v[0-9]+(\.[0-9]+)*-rc[0-9]+/ + name: nightly_binary_linux_conda_py3.9_cu102_upload + requires: + - nightly_binary_linux_conda_py3.9_cu102 + - smoke_test_linux_conda: + cuda_version: cu102 + filters: + branches: + only: + - nightly + tags: + only: /v[0-9]+(\.[0-9]+)*-rc[0-9]+/ + name: nightly_binary_linux_conda_py3.9_cu102_smoke_test_conda + python_version: '3.9' + requires: + - nightly_binary_linux_conda_py3.9_cu102_upload + - binary_linux_conda: + conda_docker_image: pytorch/conda-builder:cuda111 + cuda_version: cu111 + filters: + branches: + only: + - nightly + tags: + only: /v[0-9]+(\.[0-9]+)*-rc[0-9]+/ + name: nightly_binary_linux_conda_py3.9_cu111 + python_version: '3.9' + requires: + - download_third_parties_nix + - binary_conda_upload: + context: org-member + filters: + branches: + only: + - nightly + tags: + only: /v[0-9]+(\.[0-9]+)*-rc[0-9]+/ + name: nightly_binary_linux_conda_py3.9_cu111_upload + requires: + - nightly_binary_linux_conda_py3.9_cu111 + - smoke_test_linux_conda: + cuda_version: cu111 + filters: + branches: + only: + - nightly + tags: + only: /v[0-9]+(\.[0-9]+)*-rc[0-9]+/ + name: nightly_binary_linux_conda_py3.9_cu111_smoke_test_conda + python_version: '3.9' + requires: + - nightly_binary_linux_conda_py3.9_cu111_upload + - binary_macos_conda: + conda_docker_image: pytorch/conda-builder:cpu + cuda_version: cpu + filters: + branches: + only: + - nightly + tags: + only: /v[0-9]+(\.[0-9]+)*-rc[0-9]+/ + name: nightly_binary_macos_conda_py3.6_cpu + python_version: '3.6' + requires: + - download_third_parties_nix + - binary_conda_upload: + context: org-member + filters: + branches: + only: + - nightly + tags: + only: /v[0-9]+(\.[0-9]+)*-rc[0-9]+/ + name: nightly_binary_macos_conda_py3.6_cpu_upload + requires: + - nightly_binary_macos_conda_py3.6_cpu + - binary_macos_conda: + conda_docker_image: pytorch/conda-builder:cpu + cuda_version: cpu + filters: + branches: + only: + - nightly + tags: + only: /v[0-9]+(\.[0-9]+)*-rc[0-9]+/ + name: nightly_binary_macos_conda_py3.7_cpu + python_version: '3.7' + requires: + - download_third_parties_nix + - binary_conda_upload: + context: org-member + filters: + branches: + only: + - nightly + tags: + only: /v[0-9]+(\.[0-9]+)*-rc[0-9]+/ + name: nightly_binary_macos_conda_py3.7_cpu_upload + requires: + - nightly_binary_macos_conda_py3.7_cpu + - binary_macos_conda: + conda_docker_image: pytorch/conda-builder:cpu + cuda_version: cpu + filters: + branches: + only: + - nightly + tags: + only: /v[0-9]+(\.[0-9]+)*-rc[0-9]+/ + name: nightly_binary_macos_conda_py3.8_cpu + python_version: '3.8' + requires: + - download_third_parties_nix + - binary_conda_upload: + context: org-member + filters: + branches: + only: + - nightly + tags: + only: /v[0-9]+(\.[0-9]+)*-rc[0-9]+/ + name: nightly_binary_macos_conda_py3.8_cpu_upload + requires: + - nightly_binary_macos_conda_py3.8_cpu + - binary_macos_conda: + conda_docker_image: pytorch/conda-builder:cpu + cuda_version: cpu + filters: + branches: + only: + - nightly + tags: + only: /v[0-9]+(\.[0-9]+)*-rc[0-9]+/ + name: nightly_binary_macos_conda_py3.9_cpu + python_version: '3.9' + requires: + - download_third_parties_nix + - binary_conda_upload: + context: org-member + filters: + branches: + only: + - nightly + tags: + only: /v[0-9]+(\.[0-9]+)*-rc[0-9]+/ + name: nightly_binary_macos_conda_py3.9_cpu_upload + requires: + - nightly_binary_macos_conda_py3.9_cpu + - binary_windows_conda: + conda_docker_image: pytorch/conda-builder:cpu + cuda_version: cpu + filters: + branches: + only: + - nightly + tags: + only: /v[0-9]+(\.[0-9]+)*-rc[0-9]+/ + name: nightly_binary_windows_conda_py3.6_cpu + python_version: '3.6' + - binary_conda_upload: + context: org-member + filters: + branches: + only: + - nightly + tags: + only: /v[0-9]+(\.[0-9]+)*-rc[0-9]+/ + name: nightly_binary_windows_conda_py3.6_cpu_upload + requires: + - nightly_binary_windows_conda_py3.6_cpu + - smoke_test_windows_conda: + cuda_version: cpu + filters: + branches: + only: + - nightly + tags: + only: /v[0-9]+(\.[0-9]+)*-rc[0-9]+/ + name: nightly_binary_windows_conda_py3.6_cpu_smoke_test_conda + python_version: '3.6' + requires: + - nightly_binary_windows_conda_py3.6_cpu_upload + - binary_windows_conda: + conda_docker_image: pytorch/conda-builder:cuda102 + cuda_version: cu102 + filters: + branches: + only: + - nightly + tags: + only: /v[0-9]+(\.[0-9]+)*-rc[0-9]+/ + name: nightly_binary_windows_conda_py3.6_cu102 + python_version: '3.6' + - binary_conda_upload: + context: org-member + filters: + branches: + only: + - nightly + tags: + only: /v[0-9]+(\.[0-9]+)*-rc[0-9]+/ + name: nightly_binary_windows_conda_py3.6_cu102_upload + requires: + - nightly_binary_windows_conda_py3.6_cu102 + - smoke_test_windows_conda: + cuda_version: cu102 + filters: + branches: + only: + - nightly + tags: + only: /v[0-9]+(\.[0-9]+)*-rc[0-9]+/ + name: nightly_binary_windows_conda_py3.6_cu102_smoke_test_conda + python_version: '3.6' + requires: + - nightly_binary_windows_conda_py3.6_cu102_upload + - binary_windows_conda: + conda_docker_image: pytorch/conda-builder:cuda111 + cuda_version: cu111 + filters: + branches: + only: + - nightly + tags: + only: /v[0-9]+(\.[0-9]+)*-rc[0-9]+/ + name: nightly_binary_windows_conda_py3.6_cu111 + python_version: '3.6' + - binary_conda_upload: context: org-member filters: branches: @@ -1430,28 +2649,99 @@ workflows: - nightly tags: only: /v[0-9]+(\.[0-9]+)*-rc[0-9]+/ - name: nightly_binary_windows_conda_py3.6_upload + name: nightly_binary_windows_conda_py3.6_cu111_upload requires: - - nightly_binary_windows_conda_py3.6 + - nightly_binary_windows_conda_py3.6_cu111 - smoke_test_windows_conda: + cuda_version: cu111 filters: branches: only: - nightly tags: only: /v[0-9]+(\.[0-9]+)*-rc[0-9]+/ - name: nightly_binary_windows_conda_py3.6_smoke_test_conda + name: nightly_binary_windows_conda_py3.6_cu111_smoke_test_conda python_version: '3.6' requires: - - nightly_binary_windows_conda_py3.6_upload + - nightly_binary_windows_conda_py3.6_cu111_upload + - binary_windows_conda: + conda_docker_image: pytorch/conda-builder:cpu + cuda_version: cpu + filters: + branches: + only: + - nightly + tags: + only: /v[0-9]+(\.[0-9]+)*-rc[0-9]+/ + name: nightly_binary_windows_conda_py3.7_cpu + python_version: '3.7' + - binary_conda_upload: + context: org-member + filters: + branches: + only: + - nightly + tags: + only: /v[0-9]+(\.[0-9]+)*-rc[0-9]+/ + name: nightly_binary_windows_conda_py3.7_cpu_upload + requires: + - nightly_binary_windows_conda_py3.7_cpu + - smoke_test_windows_conda: + cuda_version: cpu + filters: + branches: + only: + - nightly + tags: + only: /v[0-9]+(\.[0-9]+)*-rc[0-9]+/ + name: nightly_binary_windows_conda_py3.7_cpu_smoke_test_conda + python_version: '3.7' + requires: + - nightly_binary_windows_conda_py3.7_cpu_upload + - binary_windows_conda: + conda_docker_image: pytorch/conda-builder:cuda102 + cuda_version: cu102 + filters: + branches: + only: + - nightly + tags: + only: /v[0-9]+(\.[0-9]+)*-rc[0-9]+/ + name: nightly_binary_windows_conda_py3.7_cu102 + python_version: '3.7' + - binary_conda_upload: + context: org-member + filters: + branches: + only: + - nightly + tags: + only: /v[0-9]+(\.[0-9]+)*-rc[0-9]+/ + name: nightly_binary_windows_conda_py3.7_cu102_upload + requires: + - nightly_binary_windows_conda_py3.7_cu102 + - smoke_test_windows_conda: + cuda_version: cu102 + filters: + branches: + only: + - nightly + tags: + only: /v[0-9]+(\.[0-9]+)*-rc[0-9]+/ + name: nightly_binary_windows_conda_py3.7_cu102_smoke_test_conda + python_version: '3.7' + requires: + - nightly_binary_windows_conda_py3.7_cu102_upload - binary_windows_conda: + conda_docker_image: pytorch/conda-builder:cuda111 + cuda_version: cu111 filters: branches: only: - nightly tags: only: /v[0-9]+(\.[0-9]+)*-rc[0-9]+/ - name: nightly_binary_windows_conda_py3.7 + name: nightly_binary_windows_conda_py3.7_cu111 python_version: '3.7' - binary_conda_upload: context: org-member @@ -1461,28 +2751,99 @@ workflows: - nightly tags: only: /v[0-9]+(\.[0-9]+)*-rc[0-9]+/ - name: nightly_binary_windows_conda_py3.7_upload + name: nightly_binary_windows_conda_py3.7_cu111_upload requires: - - nightly_binary_windows_conda_py3.7 + - nightly_binary_windows_conda_py3.7_cu111 - smoke_test_windows_conda: + cuda_version: cu111 filters: branches: only: - nightly tags: only: /v[0-9]+(\.[0-9]+)*-rc[0-9]+/ - name: nightly_binary_windows_conda_py3.7_smoke_test_conda + name: nightly_binary_windows_conda_py3.7_cu111_smoke_test_conda python_version: '3.7' requires: - - nightly_binary_windows_conda_py3.7_upload + - nightly_binary_windows_conda_py3.7_cu111_upload + - binary_windows_conda: + conda_docker_image: pytorch/conda-builder:cpu + cuda_version: cpu + filters: + branches: + only: + - nightly + tags: + only: /v[0-9]+(\.[0-9]+)*-rc[0-9]+/ + name: nightly_binary_windows_conda_py3.8_cpu + python_version: '3.8' + - binary_conda_upload: + context: org-member + filters: + branches: + only: + - nightly + tags: + only: /v[0-9]+(\.[0-9]+)*-rc[0-9]+/ + name: nightly_binary_windows_conda_py3.8_cpu_upload + requires: + - nightly_binary_windows_conda_py3.8_cpu + - smoke_test_windows_conda: + cuda_version: cpu + filters: + branches: + only: + - nightly + tags: + only: /v[0-9]+(\.[0-9]+)*-rc[0-9]+/ + name: nightly_binary_windows_conda_py3.8_cpu_smoke_test_conda + python_version: '3.8' + requires: + - nightly_binary_windows_conda_py3.8_cpu_upload + - binary_windows_conda: + conda_docker_image: pytorch/conda-builder:cuda102 + cuda_version: cu102 + filters: + branches: + only: + - nightly + tags: + only: /v[0-9]+(\.[0-9]+)*-rc[0-9]+/ + name: nightly_binary_windows_conda_py3.8_cu102 + python_version: '3.8' + - binary_conda_upload: + context: org-member + filters: + branches: + only: + - nightly + tags: + only: /v[0-9]+(\.[0-9]+)*-rc[0-9]+/ + name: nightly_binary_windows_conda_py3.8_cu102_upload + requires: + - nightly_binary_windows_conda_py3.8_cu102 + - smoke_test_windows_conda: + cuda_version: cu102 + filters: + branches: + only: + - nightly + tags: + only: /v[0-9]+(\.[0-9]+)*-rc[0-9]+/ + name: nightly_binary_windows_conda_py3.8_cu102_smoke_test_conda + python_version: '3.8' + requires: + - nightly_binary_windows_conda_py3.8_cu102_upload - binary_windows_conda: + conda_docker_image: pytorch/conda-builder:cuda111 + cuda_version: cu111 filters: branches: only: - nightly tags: only: /v[0-9]+(\.[0-9]+)*-rc[0-9]+/ - name: nightly_binary_windows_conda_py3.8 + name: nightly_binary_windows_conda_py3.8_cu111 python_version: '3.8' - binary_conda_upload: context: org-member @@ -1492,28 +2853,99 @@ workflows: - nightly tags: only: /v[0-9]+(\.[0-9]+)*-rc[0-9]+/ - name: nightly_binary_windows_conda_py3.8_upload + name: nightly_binary_windows_conda_py3.8_cu111_upload requires: - - nightly_binary_windows_conda_py3.8 + - nightly_binary_windows_conda_py3.8_cu111 - smoke_test_windows_conda: + cuda_version: cu111 filters: branches: only: - nightly tags: only: /v[0-9]+(\.[0-9]+)*-rc[0-9]+/ - name: nightly_binary_windows_conda_py3.8_smoke_test_conda + name: nightly_binary_windows_conda_py3.8_cu111_smoke_test_conda python_version: '3.8' requires: - - nightly_binary_windows_conda_py3.8_upload + - nightly_binary_windows_conda_py3.8_cu111_upload + - binary_windows_conda: + conda_docker_image: pytorch/conda-builder:cpu + cuda_version: cpu + filters: + branches: + only: + - nightly + tags: + only: /v[0-9]+(\.[0-9]+)*-rc[0-9]+/ + name: nightly_binary_windows_conda_py3.9_cpu + python_version: '3.9' + - binary_conda_upload: + context: org-member + filters: + branches: + only: + - nightly + tags: + only: /v[0-9]+(\.[0-9]+)*-rc[0-9]+/ + name: nightly_binary_windows_conda_py3.9_cpu_upload + requires: + - nightly_binary_windows_conda_py3.9_cpu + - smoke_test_windows_conda: + cuda_version: cpu + filters: + branches: + only: + - nightly + tags: + only: /v[0-9]+(\.[0-9]+)*-rc[0-9]+/ + name: nightly_binary_windows_conda_py3.9_cpu_smoke_test_conda + python_version: '3.9' + requires: + - nightly_binary_windows_conda_py3.9_cpu_upload + - binary_windows_conda: + conda_docker_image: pytorch/conda-builder:cuda102 + cuda_version: cu102 + filters: + branches: + only: + - nightly + tags: + only: /v[0-9]+(\.[0-9]+)*-rc[0-9]+/ + name: nightly_binary_windows_conda_py3.9_cu102 + python_version: '3.9' + - binary_conda_upload: + context: org-member + filters: + branches: + only: + - nightly + tags: + only: /v[0-9]+(\.[0-9]+)*-rc[0-9]+/ + name: nightly_binary_windows_conda_py3.9_cu102_upload + requires: + - nightly_binary_windows_conda_py3.9_cu102 + - smoke_test_windows_conda: + cuda_version: cu102 + filters: + branches: + only: + - nightly + tags: + only: /v[0-9]+(\.[0-9]+)*-rc[0-9]+/ + name: nightly_binary_windows_conda_py3.9_cu102_smoke_test_conda + python_version: '3.9' + requires: + - nightly_binary_windows_conda_py3.9_cu102_upload - binary_windows_conda: + conda_docker_image: pytorch/conda-builder:cuda111 + cuda_version: cu111 filters: branches: only: - nightly tags: only: /v[0-9]+(\.[0-9]+)*-rc[0-9]+/ - name: nightly_binary_windows_conda_py3.9 + name: nightly_binary_windows_conda_py3.9_cu111 python_version: '3.9' - binary_conda_upload: context: org-member @@ -1523,20 +2955,21 @@ workflows: - nightly tags: only: /v[0-9]+(\.[0-9]+)*-rc[0-9]+/ - name: nightly_binary_windows_conda_py3.9_upload + name: nightly_binary_windows_conda_py3.9_cu111_upload requires: - - nightly_binary_windows_conda_py3.9 + - nightly_binary_windows_conda_py3.9_cu111 - smoke_test_windows_conda: + cuda_version: cu111 filters: branches: only: - nightly tags: only: /v[0-9]+(\.[0-9]+)*-rc[0-9]+/ - name: nightly_binary_windows_conda_py3.9_smoke_test_conda + name: nightly_binary_windows_conda_py3.9_cu111_smoke_test_conda python_version: '3.9' requires: - - nightly_binary_windows_conda_py3.9_upload + - nightly_binary_windows_conda_py3.9_cu111_upload docker_build: triggers: - schedule: diff --git a/.circleci/config.yml.in b/.circleci/config.yml.in index 16b47bde79..aff66edf1d 100644 --- a/.circleci/config.yml.in +++ b/.circleci/config.yml.in @@ -71,11 +71,23 @@ binary_common: &binary_common python_version: description: "Python version to build against (e.g., 3.8)" type: string + cuda_version: + description: "CUDA version to build against (e.g., cpu, cu101)" + type: string + default: "cpu" + wheel_docker_image: + description: "Wheel only: what docker image to use" + type: string + default: "pytorch/manylinux-cuda102" + conda_docker_image: + description: "Conda only: what docker image to use" + type: string + default: "pytorch/conda-builder:cuda102" environment: &environment PYTHON_VERSION: << parameters.python_version >> BUILD_VERSION: << parameters.build_version >> PYTORCH_VERSION: << parameters.pytorch_version >> - CU_VERSION: cpu + CU_VERSION: << parameters.cuda_version >> smoke_test_common: &smoke_test_common <<: *binary_common @@ -127,7 +139,7 @@ jobs: binary_linux_wheel: <<: *binary_common docker: - - image: "pytorch/manylinux-cuda102" + - image: << parameters.wheel_docker_image >> resource_class: 2xlarge+ steps: - checkout @@ -144,7 +156,7 @@ jobs: binary_linux_conda: <<: *binary_common docker: - - image: "pytorch/conda-cuda" + - image: "<< parameters.conda_docker_image >>" resource_class: 2xlarge+ steps: - checkout @@ -487,7 +499,7 @@ jobs: name: windows-gpu environment: <<: *environment - CUDA_VERSION: "10.1" + CUDA_VERSION: "10.2" steps: - checkout - designate_upload_channel diff --git a/.circleci/regenerate.py b/.circleci/regenerate.py index 137fed87c4..f1720979fb 100755 --- a/.circleci/regenerate.py +++ b/.circleci/regenerate.py @@ -21,6 +21,10 @@ PYTHON_VERSIONS = ["3.6", "3.7", "3.8", "3.9"] +CU_VERSIONS_DICT = {"linux": ["cpu", "cu102", "cu111"], + "windows": ["cpu", "cu102", "cu111"], + "macos": ["cpu"]} + DOC_VERSION = ('linux', '3.8') @@ -31,7 +35,8 @@ def build_workflows(prefix='', upload=False, filter_branch=None, indentation=6): for btype in ["wheel", "conda"]: for os_type in ["linux", "macos", "windows"]: for python_version in PYTHON_VERSIONS: - w += build_workflow_pair(btype, os_type, python_version, filter_branch, prefix, upload) + for cu_version in CU_VERSIONS_DICT[os_type]: + w += build_workflow_pair(btype, os_type, python_version, cu_version, filter_branch, prefix, upload) if not filter_branch: # Build on every pull request, but upload only on nightly and tags @@ -53,27 +58,19 @@ def build_download_job(filter_branch): return [{"download_third_parties_nix": job}] -def build_workflow_pair(btype, os_type, python_version, filter_branch, prefix='', upload=False): +def build_workflow_pair(btype, os_type, python_version, cu_version, filter_branch, prefix='', upload=False): w = [] - base_workflow_name = "{prefix}binary_{os_type}_{btype}_py{python_version}".format( - prefix=prefix, - os_type=os_type, - btype=btype, - python_version=python_version, - ) - - w.append(generate_base_workflow(base_workflow_name, python_version, filter_branch, os_type, btype)) + base_workflow_name = f"{prefix}binary_{os_type}_{btype}_py{python_version}_{cu_version}" + w.append(generate_base_workflow(base_workflow_name, python_version, cu_version, filter_branch, os_type, btype)) if upload: - is_py3_linux = os_type in ['linux', "windows"] and not python_version.startswith("2.") - w.append(generate_upload_workflow(base_workflow_name, filter_branch, btype)) - if filter_branch == 'nightly' and is_py3_linux: + if filter_branch == 'nightly' and os_type != 'macos': pydistro = 'pip' if btype == 'wheel' else 'conda' - w.append(generate_smoketest_workflow(pydistro, base_workflow_name, filter_branch, python_version, os_type)) + w.append(generate_smoketest_workflow(pydistro, base_workflow_name, filter_branch, python_version, cu_version, os_type)) return w @@ -82,7 +79,7 @@ def build_doc_job(filter_branch): job = { "name": "build_docs", "python_version": "3.8", - "requires": ["binary_linux_wheel_py3.8", ], + "requires": ["binary_linux_wheel_py3.8_cpu", ], } if filter_branch: @@ -107,7 +104,7 @@ def docstring_parameters_sync_job(filter_branch): job = { "name": "docstring_parameters_sync", "python_version": "3.8", - "requires": ["binary_linux_wheel_py3.8", ], + "requires": ["binary_linux_wheel_py3.8_cpu", ], } if filter_branch: @@ -115,15 +112,20 @@ def docstring_parameters_sync_job(filter_branch): return [{"docstring_parameters_sync": job}] -def generate_base_workflow(base_workflow_name, python_version, filter_branch, os_type, btype): +def generate_base_workflow(base_workflow_name, python_version, cu_version, filter_branch, os_type, btype): d = { "name": base_workflow_name, "python_version": python_version, + "cuda_version": cu_version, } if os_type in ['linux', 'macos']: d['requires'] = ['download_third_parties_nix'] + if btype == 'conda': + d['conda_docker_image'] = f'pytorch/conda-builder:{cu_version.replace("cu1","cuda1")}' + elif cu_version != 'cpu': + d['wheel_docker_image'] = f'pytorch/manylinux-{cu_version.replace("cu1","cuda1")}' if filter_branch: d["filters"] = gen_filter_branch_tree(filter_branch) @@ -157,23 +159,23 @@ def generate_upload_workflow(base_workflow_name, filter_branch, btype): return {"binary_{btype}_upload".format(btype=btype): d} -def generate_smoketest_workflow(pydistro, base_workflow_name, filter_branch, python_version, os_type): +def generate_smoketest_workflow(pydistro, base_workflow_name, filter_branch, python_version, cu_version, os_type): required_build_suffix = "_upload" required_build_name = base_workflow_name + required_build_suffix - smoke_suffix = "smoke_test_{pydistro}".format(pydistro=pydistro) + smoke_suffix = f"smoke_test_{pydistro}".format(pydistro=pydistro) d = { - "name": "{base_workflow_name}_{smoke_suffix}".format( - base_workflow_name=base_workflow_name, smoke_suffix=smoke_suffix), + "name": f"{base_workflow_name}_{smoke_suffix}", "requires": [required_build_name], "python_version": python_version, + "cuda_version": cu_version, } if filter_branch: d["filters"] = gen_filter_branch_tree(filter_branch) - return {"smoke_test_{os_type}_{pydistro}".format(os_type=os_type, pydistro=pydistro): d} + return {f"smoke_test_{os_type}_{pydistro}": d} def indent(indentation, data_list): @@ -192,6 +194,7 @@ def unittest_workflows(indentation=6): job = { "name": f"unittest_{os_type}_{device_type}_py{python_version}", "python_version": python_version, + "cuda_version": 'cpu' if device_type=="cpu" else "cu102", } if os_type != "windows": @@ -204,6 +207,7 @@ def unittest_workflows(indentation=6): "stylecheck": { "name": f"stylecheck_py{python_version}", "python_version": python_version, + "cuda_version": 'cpu' if device_type=="cpu" else "cu102", } }) return indent(indentation, jobs) diff --git a/packaging/pkg_helpers.bash b/packaging/pkg_helpers.bash index 5dc5397042..173aa4ca07 100644 --- a/packaging/pkg_helpers.bash +++ b/packaging/pkg_helpers.bash @@ -52,17 +52,60 @@ setup_cuda() { # Now work out the CUDA settings case "$CU_VERSION" in + cu112) + if [[ "$OSTYPE" == "msys" ]]; then + export CUDA_HOME="C:\\Program Files\\NVIDIA GPU Computing Toolkit\\CUDA\\v11.2" + else + export CUDA_HOME=/usr/local/cuda-11.2/ + fi + export FORCE_CUDA=1 + export TORCH_CUDA_ARCH_LIST="3.5;5.0+PTX;6.0;7.0;7.5;8.0;8.6" + ;; + cu111) + if [[ "$OSTYPE" == "msys" ]]; then + export CUDA_HOME="C:\\Program Files\\NVIDIA GPU Computing Toolkit\\CUDA\\v11.1" + else + export CUDA_HOME=/usr/local/cuda-11.1/ + fi + export FORCE_CUDA=1 + export TORCH_CUDA_ARCH_LIST="3.5;5.0+PTX;6.0;7.0;7.5;8.0;8.6" + ;; + cu110) + if [[ "$OSTYPE" == "msys" ]]; then + export CUDA_HOME="C:\\Program Files\\NVIDIA GPU Computing Toolkit\\CUDA\\v11.0" + else + export CUDA_HOME=/usr/local/cuda-11.0/ + fi + export FORCE_CUDA=1 + export TORCH_CUDA_ARCH_LIST="3.5;5.0+PTX;6.0;7.0;7.5;8.0" + ;; + cu102) + if [[ "$OSTYPE" == "msys" ]]; then + export CUDA_HOME="C:\\Program Files\\NVIDIA GPU Computing Toolkit\\CUDA\\v10.2" + else + export CUDA_HOME=/usr/local/cuda-10.2/ + fi + export FORCE_CUDA=1 + export TORCH_CUDA_ARCH_LIST="3.5;5.0+PTX;6.0;7.0;7.5" + ;; + cu101) + if [[ "$OSTYPE" == "msys" ]]; then + export CUDA_HOME="C:\\Program Files\\NVIDIA GPU Computing Toolkit\\CUDA\\v10.1" + else + export CUDA_HOME=/usr/local/cuda-10.1/ + fi + export FORCE_CUDA=1 + export TORCH_CUDA_ARCH_LIST="3.5;5.0+PTX;6.0;7.0;7.5" + ;; cu100) export CUDA_HOME=/usr/local/cuda-10.0/ export FORCE_CUDA=1 - # Hard-coding gencode flags is temporary situation until - # https://github.com/pytorch/pytorch/pull/23408 lands - export NVCC_FLAGS="-gencode=arch=compute_35,code=sm_35 -gencode=arch=compute_50,code=sm_50 -gencode=arch=compute_60,code=sm_60 -gencode=arch=compute_70,code=sm_70 -gencode=arch=compute_75,code=sm_75 -gencode=arch=compute_50,code=compute_50" + export TORCH_CUDA_ARCH_LIST="3.5;5.0+PTX;6.0;7.0;7.5" ;; cu92) export CUDA_HOME=/usr/local/cuda-9.2/ export FORCE_CUDA=1 - export NVCC_FLAGS="-gencode=arch=compute_35,code=sm_35 -gencode=arch=compute_50,code=sm_50 -gencode=arch=compute_60,code=sm_60 -gencode=arch=compute_70,code=sm_70 -gencode=arch=compute_50,code=compute_50" + export TORCH_CUDA_ARCH_LIST="3.5;5.0+PTX;6.0;7.0" ;; cpu) ;; diff --git a/test/torchaudio_unittest/backend/sox_io/info_test.py b/test/torchaudio_unittest/backend/sox_io/info_test.py index d459061eee..a7f5bdf02e 100644 --- a/test/torchaudio_unittest/backend/sox_io/info_test.py +++ b/test/torchaudio_unittest/backend/sox_io/info_test.py @@ -476,3 +476,14 @@ def test_requests(self, ext, dtype): assert sinfo.num_frames == num_frames assert sinfo.bits_per_sample == bits_per_sample assert sinfo.encoding == get_encoding(ext, dtype) + + +@skipIfNoSox +class TestInfoNoSuchFile(PytorchTestCase): + def test_info_fail(self): + """ + When attempted to get info on a non-existing file, error message must contain the file path. + """ + path = "non_existing_audio.wav" + with self.assertRaisesRegex(RuntimeError, "^Error loading audio file: failed to open file {0}$".format(path)): + sox_io_backend.info(path) diff --git a/test/torchaudio_unittest/backend/sox_io/load_test.py b/test/torchaudio_unittest/backend/sox_io/load_test.py index f8d06a4da9..824d012cfd 100644 --- a/test/torchaudio_unittest/backend/sox_io/load_test.py +++ b/test/torchaudio_unittest/backend/sox_io/load_test.py @@ -522,3 +522,14 @@ def test_frame(self, frame_offset, num_frames): assert sr == sample_rate self.assertEqual(expected, found) + + +@skipIfNoSox +class TestLoadNoSuchFile(PytorchTestCase): + def test_load_fail(self): + """ + When attempted to load a non-existing file, error message must contain the file path. + """ + path = "non_existing_audio.wav" + with self.assertRaisesRegex(RuntimeError, "^Error loading audio file: failed to open file {0}$".format(path)): + sox_io_backend.load(path) diff --git a/test/torchaudio_unittest/backend/sox_io/save_test.py b/test/torchaudio_unittest/backend/sox_io/save_test.py index 4356972342..9592e78d2d 100644 --- a/test/torchaudio_unittest/backend/sox_io/save_test.py +++ b/test/torchaudio_unittest/backend/sox_io/save_test.py @@ -1,6 +1,8 @@ import io +import os import unittest +import torch from torchaudio.backend import sox_io_backend from parameterized import parameterized @@ -387,3 +389,14 @@ def test_save_tensor_preserve(self, dtype): sox_io_backend.save(path, data, 8000) self.assertEqual(data, expected) + + +@skipIfNoSox +class TestSaveNonExistingDirectory(PytorchTestCase): + def test_save_fail(self): + """ + When attempted to save into a non-existing dir, error message must contain the file path. + """ + path = os.path.join("non_existing_directory", "foo.wav") + with self.assertRaisesRegex(RuntimeError, "^Error saving audio file: failed to open file {0}$".format(path)): + sox_io_backend.save(path, torch.zeros(1, 1), 8000) diff --git a/test/torchaudio_unittest/transforms/batch_consistency_test.py b/test/torchaudio_unittest/transforms/batch_consistency_test.py index cab68e0152..609f1ee631 100644 --- a/test/torchaudio_unittest/transforms/batch_consistency_test.py +++ b/test/torchaudio_unittest/transforms/batch_consistency_test.py @@ -74,8 +74,7 @@ def test_batch_compute_deltas(self): self.assertEqual(computed, expected) def test_batch_mulaw(self): - test_filepath = common_utils.get_asset_path('steam-train-whistle-daniel_simon.wav') - waveform, _ = torchaudio.load(test_filepath) # (2, 278756), 44100 + waveform = common_utils.get_whitenoise(sample_rate=8000, duration=1, n_channels=2) # Single then transform then batch waveform_encoded = torchaudio.transforms.MuLawEncoding()(waveform) @@ -99,8 +98,7 @@ def test_batch_mulaw(self): self.assertEqual(computed, expected) def test_batch_spectrogram(self): - test_filepath = common_utils.get_asset_path('steam-train-whistle-daniel_simon.wav') - waveform, _ = torchaudio.load(test_filepath) # (2, 278756), 44100 + waveform = common_utils.get_whitenoise(sample_rate=8000, duration=1, n_channels=2) # Single then transform then batch expected = torchaudio.transforms.Spectrogram()(waveform).repeat(3, 1, 1, 1) @@ -110,8 +108,7 @@ def test_batch_spectrogram(self): self.assertEqual(computed, expected) def test_batch_melspectrogram(self): - test_filepath = common_utils.get_asset_path('steam-train-whistle-daniel_simon.wav') - waveform, _ = torchaudio.load(test_filepath) # (2, 278756), 44100 + waveform = common_utils.get_whitenoise(sample_rate=8000, duration=1, n_channels=2) # Single then transform then batch expected = torchaudio.transforms.MelSpectrogram()(waveform).repeat(3, 1, 1, 1) @@ -121,8 +118,7 @@ def test_batch_melspectrogram(self): self.assertEqual(computed, expected) def test_batch_mfcc(self): - test_filepath = common_utils.get_asset_path('steam-train-whistle-daniel_simon.wav') - waveform, _ = torchaudio.load(test_filepath) + waveform = common_utils.get_whitenoise(sample_rate=8000, duration=1, n_channels=2) # Single then transform then batch expected = torchaudio.transforms.MFCC()(waveform).repeat(3, 1, 1, 1) @@ -160,8 +156,7 @@ def test_batch_TimeStretch(self, test_pseudo_complex): self.assertEqual(computed, expected, atol=1e-5, rtol=1e-5) def test_batch_Fade(self): - test_filepath = common_utils.get_asset_path('steam-train-whistle-daniel_simon.wav') - waveform, _ = torchaudio.load(test_filepath) # (2, 278756), 44100 + waveform = common_utils.get_whitenoise(sample_rate=8000, duration=1, n_channels=2) fade_in_len = 3000 fade_out_len = 3000 @@ -173,8 +168,7 @@ def test_batch_Fade(self): self.assertEqual(computed, expected) def test_batch_Vol(self): - test_filepath = common_utils.get_asset_path('steam-train-whistle-daniel_simon.wav') - waveform, _ = torchaudio.load(test_filepath) # (2, 278756), 44100 + waveform = common_utils.get_whitenoise(sample_rate=8000, duration=1, n_channels=2) # Single then transform then batch expected = torchaudio.transforms.Vol(gain=1.1)(waveform).repeat(3, 1, 1) diff --git a/torchaudio/csrc/sox/effects.cpp b/torchaudio/csrc/sox/effects.cpp index 8ffc6327ac..7568c46d08 100644 --- a/torchaudio/csrc/sox/effects.cpp +++ b/torchaudio/csrc/sox/effects.cpp @@ -101,7 +101,7 @@ std::tuple apply_effects_file( /*encoding=*/nullptr, /*filetype=*/format.has_value() ? format.value().c_str() : nullptr)); - validate_input_file(sf); + validate_input_file(sf, path); const auto dtype = get_dtype(sf->encoding.encoding, sf->signal.precision); @@ -204,7 +204,7 @@ std::tuple apply_effects_fileobj( /*filetype=*/format.has_value() ? format.value().c_str() : nullptr)); // In case of streamed data, length can be 0 - validate_input_file(sf); + validate_input_memfile(sf); // Prepare output buffer std::vector out_buffer; diff --git a/torchaudio/csrc/sox/io.cpp b/torchaudio/csrc/sox/io.cpp index 8e2ebce4e2..a075a23f74 100644 --- a/torchaudio/csrc/sox/io.cpp +++ b/torchaudio/csrc/sox/io.cpp @@ -19,9 +19,7 @@ std::tuple get_info_file( /*encoding=*/nullptr, /*filetype=*/format.has_value() ? format.value().c_str() : nullptr)); - if (static_cast(sf) == nullptr) { - throw std::runtime_error("Error opening audio file"); - } + validate_input_file(sf, path); return std::make_tuple( static_cast(sf->signal.rate), @@ -123,7 +121,8 @@ void save_audio_file( /*overwrite_permitted=*/nullptr)); if (static_cast(sf) == nullptr) { - throw std::runtime_error("Error saving audio file: failed to open file."); + throw std::runtime_error( + "Error saving audio file: failed to open file " + path); } torchaudio::sox_effects_chain::SoxEffectsChain chain( @@ -177,7 +176,7 @@ std::tuple get_info_fileobj( /*filetype=*/format.has_value() ? format.value().c_str() : nullptr)); // In case of streamed data, length can be 0 - validate_input_file(sf); + validate_input_memfile(sf); return std::make_tuple( static_cast(sf->signal.rate), diff --git a/torchaudio/csrc/sox/utils.cpp b/torchaudio/csrc/sox/utils.cpp index b46067626c..efb489a529 100644 --- a/torchaudio/csrc/sox/utils.cpp +++ b/torchaudio/csrc/sox/utils.cpp @@ -81,15 +81,20 @@ void SoxFormat::close() { } } -void validate_input_file(const SoxFormat& sf) { +void validate_input_file(const SoxFormat& sf, const std::string& path) { if (static_cast(sf) == nullptr) { - throw std::runtime_error("Error loading audio file: failed to open file."); + throw std::runtime_error( + "Error loading audio file: failed to open file " + path); } if (sf->encoding.encoding == SOX_ENCODING_UNKNOWN) { throw std::runtime_error("Error loading audio file: unknown encoding."); } } +void validate_input_memfile(const SoxFormat& sf) { + return validate_input_file(sf, ""); +} + void validate_input_tensor(const torch::Tensor tensor) { if (!tensor.device().is_cpu()) { throw std::runtime_error("Input tensor has to be on CPU."); diff --git a/torchaudio/csrc/sox/utils.h b/torchaudio/csrc/sox/utils.h index 7e736dbe8d..67624b8597 100644 --- a/torchaudio/csrc/sox/utils.h +++ b/torchaudio/csrc/sox/utils.h @@ -56,7 +56,10 @@ struct SoxFormat { /// /// Verify that input file is found, has known encoding, and not empty -void validate_input_file(const SoxFormat& sf); +void validate_input_file(const SoxFormat& sf, const std::string& path); + +/// Verify that input memory buffer has known encoding, and not empty +void validate_input_memfile(const SoxFormat& sf); /// /// Verify that input Tensor is 2D, CPU and either uin8, int16, int32 or float32 From e2049fe79ae433196e76c04b76c847b72f90ac99 Mon Sep 17 00:00:00 2001 From: Moto Hira Date: Wed, 9 Jun 2021 11:34:37 -0700 Subject: [PATCH 51/73] Import torchaudio #1554 afb6626 Summary: Import torchaudio #1554 afb6626 Reviewed By: NicolasHug Differential Revision: D28891382 fbshipit-source-id: 9b6e06ff94b2ec2f6d948049cc74046dee721471 --- .circleci/config.yml | 172 ++ .circleci/regenerate.py | 11 +- .circleci/unittest/linux/scripts/install.sh | 7 +- .circleci/unittest/windows/scripts/install.sh | 7 +- .gitmodules | 3 + README.md | 47 +- docs/requirements.txt | 1 + docs/source/_static/css/pytorch_theme.css | 118 -- docs/source/compliance.kaldi.rst | 5 - docs/source/conf.py | 22 +- docs/source/functional.rst | 11 +- docs/source/models.rst | 72 +- docs/source/refs.bib | 90 + docs/source/rnnt_loss.rst | 13 +- docs/source/transforms.rst | 34 +- examples/libtorchaudio/.gitignore | 3 +- examples/libtorchaudio/CMakeLists.txt | 2 + examples/libtorchaudio/README.md | 2 + examples/libtorchaudio/build.sh | 1 + .../speech_recognition/CMakeLists.txt | 6 + .../speech_recognition/README.md | 187 ++ .../build_pipeline_from_fairseq.py | 202 ++ ..._pipeline_from_huggingface_transformers.py | 142 ++ .../speech_recognition/parse_librispeech.py | 55 + .../speech_recognition/parse_voxforge.py | 67 + .../speech_recognition/transcribe.cpp | 38 + .../speech_recognition/transcribe_list.cpp | 66 + packaging/build_conda.sh | 2 +- packaging/build_wheel.sh | 2 +- packaging/pkg_helpers.bash | 4 + setup.py | 2 +- .../assets/kaldi/resample-16000-1000.ark | Bin 2021 -> 0 bytes .../assets/kaldi/resample-16000-10000.ark | Bin 20021 -> 0 bytes .../assets/kaldi/resample-16000-11000.ark | Bin 22021 -> 0 bytes .../assets/kaldi/resample-16000-12000.ark | Bin 24021 -> 0 bytes .../assets/kaldi/resample-16000-13000.ark | Bin 26021 -> 0 bytes .../assets/kaldi/resample-16000-14000.ark | Bin 28021 -> 0 bytes .../assets/kaldi/resample-16000-15000.ark | Bin 30021 -> 0 bytes .../assets/kaldi/resample-16000-16000.ark | Bin 32021 -> 0 bytes .../assets/kaldi/resample-16000-17000.ark | Bin 34021 -> 0 bytes .../assets/kaldi/resample-16000-18000.ark | Bin 36021 -> 0 bytes .../assets/kaldi/resample-16000-19000.ark | Bin 38021 -> 0 bytes .../assets/kaldi/resample-16000-2000.ark | Bin 4021 -> 0 bytes .../assets/kaldi/resample-16000-20000.ark | Bin 40021 -> 0 bytes .../assets/kaldi/resample-16000-21000.ark | Bin 42021 -> 0 bytes .../assets/kaldi/resample-16000-22000.ark | Bin 44021 -> 0 bytes .../assets/kaldi/resample-16000-23000.ark | Bin 46021 -> 0 bytes .../assets/kaldi/resample-16000-24000.ark | Bin 48021 -> 0 bytes .../assets/kaldi/resample-16000-25000.ark | Bin 50021 -> 0 bytes .../assets/kaldi/resample-16000-26000.ark | Bin 52021 -> 0 bytes .../assets/kaldi/resample-16000-27000.ark | Bin 54021 -> 0 bytes .../assets/kaldi/resample-16000-28000.ark | Bin 56021 -> 0 bytes .../assets/kaldi/resample-16000-29000.ark | Bin 58021 -> 0 bytes .../assets/kaldi/resample-16000-3000.ark | Bin 6021 -> 0 bytes .../assets/kaldi/resample-16000-30000.ark | Bin 60021 -> 0 bytes .../assets/kaldi/resample-16000-31000.ark | Bin 62021 -> 0 bytes .../assets/kaldi/resample-16000-32000.ark | Bin 64021 -> 0 bytes .../assets/kaldi/resample-16000-4000.ark | Bin 8021 -> 0 bytes .../assets/kaldi/resample-16000-5000.ark | Bin 10021 -> 0 bytes .../assets/kaldi/resample-16000-6000.ark | Bin 12021 -> 0 bytes .../assets/kaldi/resample-16000-7000.ark | Bin 14021 -> 0 bytes .../assets/kaldi/resample-16000-8000.ark | Bin 16021 -> 0 bytes .../assets/kaldi/resample-16000-9000.ark | Bin 18021 -> 0 bytes .../fairseq/generate_fairseq_model_config.py | 106 + .../assets/wav2vec2/fairseq/libri960_big.json | 54 + .../wav2vec2/fairseq/wav2vec_large_960h.json | 146 ++ .../fairseq/wav2vec_large_lv60k_960h.json | 146 ++ .../wav2vec_large_lv60k_self_960h.json | 146 ++ .../wav2vec2/fairseq/wav2vec_small.json | 54 + .../wav2vec2/fairseq/wav2vec_small_960h.json | 146 ++ .../wav2vec2/fairseq/wav2vec_vox_new.json | 54 + .../assets/wav2vec2/fairseq/xlsr_53_56k.json | 51 + .../generate_huggingface_model_config.py | 37 + .../common_utils/__init__.py | 2 + .../common_utils/case_utils.py | 4 + .../compliance/generate_fbank_data.py | 155 -- .../compliance/generate_test_stft_data.py | 75 - test/torchaudio_unittest/compliance/utils.py | 27 - .../compliance_kaldi_test.py | 185 -- .../functional/batch_consistency_test.py | 11 + .../functional/functional_impl.py | 74 + .../torchscript_consistency_impl.py | 18 +- .../{compliance => models}/__init__.py | 0 .../{ => models}/models_test.py | 0 .../models/wav2vec2/__init__.py | 0 .../wav2vec2/fairseq_integration_test.py | 167 ++ .../wav2vec2/huggingface_intergration_test.py | 192 ++ .../models/wav2vec2/model_test.py | 182 ++ .../rnnt/autograd_cpu_test.py | 10 + .../rnnt/autograd_cuda_test.py | 11 + .../torchaudio_unittest/rnnt/autograd_impl.py | 99 + .../rnnt/numpy_transducer.py | 5 +- .../transforms/transforms_test_impl.py | 13 + third_party/sox/CMakeLists.txt | 3 +- third_party/sox/patch/config.guess | 1700 +++++++++++++++++ torchaudio/backend/soundfile_backend.py | 27 +- torchaudio/compliance/kaldi.py | 29 - torchaudio/datasets/commonvoice.py | 31 +- torchaudio/functional/filtering.py | 80 +- torchaudio/functional/functional.py | 71 +- torchaudio/models/__init__.py | 11 + torchaudio/models/conv_tasnet.py | 21 +- torchaudio/models/deepspeech.py | 4 +- torchaudio/models/wav2letter.py | 4 +- torchaudio/models/wav2vec2/__init__.py | 15 + torchaudio/models/wav2vec2/components.py | 687 +++++++ torchaudio/models/wav2vec2/model.py | 247 +++ torchaudio/models/wav2vec2/utils/__init__.py | 7 + .../models/wav2vec2/utils/import_fairseq.py | 205 ++ .../wav2vec2/utils/import_huggingface.py | 71 + torchaudio/models/wavernn.py | 7 +- torchaudio/prototype/rnnt_loss.py | 14 +- torchaudio/transforms.py | 63 +- 113 files changed, 5973 insertions(+), 888 deletions(-) delete mode 100644 docs/source/_static/css/pytorch_theme.css create mode 100644 docs/source/refs.bib create mode 100644 examples/libtorchaudio/speech_recognition/CMakeLists.txt create mode 100644 examples/libtorchaudio/speech_recognition/README.md create mode 100644 examples/libtorchaudio/speech_recognition/build_pipeline_from_fairseq.py create mode 100644 examples/libtorchaudio/speech_recognition/build_pipeline_from_huggingface_transformers.py create mode 100644 examples/libtorchaudio/speech_recognition/parse_librispeech.py create mode 100644 examples/libtorchaudio/speech_recognition/parse_voxforge.py create mode 100644 examples/libtorchaudio/speech_recognition/transcribe.cpp create mode 100644 examples/libtorchaudio/speech_recognition/transcribe_list.cpp delete mode 100644 test/torchaudio_unittest/assets/kaldi/resample-16000-1000.ark delete mode 100644 test/torchaudio_unittest/assets/kaldi/resample-16000-10000.ark delete mode 100644 test/torchaudio_unittest/assets/kaldi/resample-16000-11000.ark delete mode 100644 test/torchaudio_unittest/assets/kaldi/resample-16000-12000.ark delete mode 100644 test/torchaudio_unittest/assets/kaldi/resample-16000-13000.ark delete mode 100644 test/torchaudio_unittest/assets/kaldi/resample-16000-14000.ark delete mode 100644 test/torchaudio_unittest/assets/kaldi/resample-16000-15000.ark delete mode 100644 test/torchaudio_unittest/assets/kaldi/resample-16000-16000.ark delete mode 100644 test/torchaudio_unittest/assets/kaldi/resample-16000-17000.ark delete mode 100644 test/torchaudio_unittest/assets/kaldi/resample-16000-18000.ark delete mode 100644 test/torchaudio_unittest/assets/kaldi/resample-16000-19000.ark delete mode 100644 test/torchaudio_unittest/assets/kaldi/resample-16000-2000.ark delete mode 100644 test/torchaudio_unittest/assets/kaldi/resample-16000-20000.ark delete mode 100644 test/torchaudio_unittest/assets/kaldi/resample-16000-21000.ark delete mode 100644 test/torchaudio_unittest/assets/kaldi/resample-16000-22000.ark delete mode 100644 test/torchaudio_unittest/assets/kaldi/resample-16000-23000.ark delete mode 100644 test/torchaudio_unittest/assets/kaldi/resample-16000-24000.ark delete mode 100644 test/torchaudio_unittest/assets/kaldi/resample-16000-25000.ark delete mode 100644 test/torchaudio_unittest/assets/kaldi/resample-16000-26000.ark delete mode 100644 test/torchaudio_unittest/assets/kaldi/resample-16000-27000.ark delete mode 100644 test/torchaudio_unittest/assets/kaldi/resample-16000-28000.ark delete mode 100644 test/torchaudio_unittest/assets/kaldi/resample-16000-29000.ark delete mode 100644 test/torchaudio_unittest/assets/kaldi/resample-16000-3000.ark delete mode 100644 test/torchaudio_unittest/assets/kaldi/resample-16000-30000.ark delete mode 100644 test/torchaudio_unittest/assets/kaldi/resample-16000-31000.ark delete mode 100644 test/torchaudio_unittest/assets/kaldi/resample-16000-32000.ark delete mode 100644 test/torchaudio_unittest/assets/kaldi/resample-16000-4000.ark delete mode 100644 test/torchaudio_unittest/assets/kaldi/resample-16000-5000.ark delete mode 100644 test/torchaudio_unittest/assets/kaldi/resample-16000-6000.ark delete mode 100644 test/torchaudio_unittest/assets/kaldi/resample-16000-7000.ark delete mode 100644 test/torchaudio_unittest/assets/kaldi/resample-16000-8000.ark delete mode 100644 test/torchaudio_unittest/assets/kaldi/resample-16000-9000.ark create mode 100644 test/torchaudio_unittest/assets/wav2vec2/fairseq/generate_fairseq_model_config.py create mode 100644 test/torchaudio_unittest/assets/wav2vec2/fairseq/libri960_big.json create mode 100644 test/torchaudio_unittest/assets/wav2vec2/fairseq/wav2vec_large_960h.json create mode 100644 test/torchaudio_unittest/assets/wav2vec2/fairseq/wav2vec_large_lv60k_960h.json create mode 100644 test/torchaudio_unittest/assets/wav2vec2/fairseq/wav2vec_large_lv60k_self_960h.json create mode 100644 test/torchaudio_unittest/assets/wav2vec2/fairseq/wav2vec_small.json create mode 100644 test/torchaudio_unittest/assets/wav2vec2/fairseq/wav2vec_small_960h.json create mode 100644 test/torchaudio_unittest/assets/wav2vec2/fairseq/wav2vec_vox_new.json create mode 100644 test/torchaudio_unittest/assets/wav2vec2/fairseq/xlsr_53_56k.json create mode 100644 test/torchaudio_unittest/assets/wav2vec2/huggingface/generate_huggingface_model_config.py delete mode 100644 test/torchaudio_unittest/compliance/generate_fbank_data.py delete mode 100644 test/torchaudio_unittest/compliance/generate_test_stft_data.py delete mode 100644 test/torchaudio_unittest/compliance/utils.py rename test/torchaudio_unittest/{compliance => models}/__init__.py (100%) rename test/torchaudio_unittest/{ => models}/models_test.py (100%) create mode 100644 test/torchaudio_unittest/models/wav2vec2/__init__.py create mode 100644 test/torchaudio_unittest/models/wav2vec2/fairseq_integration_test.py create mode 100644 test/torchaudio_unittest/models/wav2vec2/huggingface_intergration_test.py create mode 100644 test/torchaudio_unittest/models/wav2vec2/model_test.py create mode 100644 test/torchaudio_unittest/rnnt/autograd_cpu_test.py create mode 100644 test/torchaudio_unittest/rnnt/autograd_cuda_test.py create mode 100644 test/torchaudio_unittest/rnnt/autograd_impl.py create mode 100644 third_party/sox/patch/config.guess create mode 100644 torchaudio/models/wav2vec2/__init__.py create mode 100644 torchaudio/models/wav2vec2/components.py create mode 100644 torchaudio/models/wav2vec2/model.py create mode 100644 torchaudio/models/wav2vec2/utils/__init__.py create mode 100644 torchaudio/models/wav2vec2/utils/import_fairseq.py create mode 100644 torchaudio/models/wav2vec2/utils/import_huggingface.py diff --git a/.circleci/config.yml b/.circleci/config.yml index 32c7effa9c..cb796d03eb 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -650,6 +650,13 @@ workflows: requires: - download_third_parties_nix wheel_docker_image: pytorch/manylinux-cuda111 + - binary_linux_wheel: + cuda_version: rocm4.1 + name: binary_linux_wheel_py3.6_rocm4.1 + python_version: '3.6' + requires: + - download_third_parties_nix + wheel_docker_image: pytorch/manylinux-rocm:4.1 - binary_linux_wheel: cuda_version: cpu name: binary_linux_wheel_py3.7_cpu @@ -670,6 +677,13 @@ workflows: requires: - download_third_parties_nix wheel_docker_image: pytorch/manylinux-cuda111 + - binary_linux_wheel: + cuda_version: rocm4.1 + name: binary_linux_wheel_py3.7_rocm4.1 + python_version: '3.7' + requires: + - download_third_parties_nix + wheel_docker_image: pytorch/manylinux-rocm:4.1 - binary_linux_wheel: cuda_version: cpu name: binary_linux_wheel_py3.8_cpu @@ -690,6 +704,13 @@ workflows: requires: - download_third_parties_nix wheel_docker_image: pytorch/manylinux-cuda111 + - binary_linux_wheel: + cuda_version: rocm4.1 + name: binary_linux_wheel_py3.8_rocm4.1 + python_version: '3.8' + requires: + - download_third_parties_nix + wheel_docker_image: pytorch/manylinux-rocm:4.1 - binary_linux_wheel: cuda_version: cpu name: binary_linux_wheel_py3.9_cpu @@ -710,6 +731,13 @@ workflows: requires: - download_third_parties_nix wheel_docker_image: pytorch/manylinux-cuda111 + - binary_linux_wheel: + cuda_version: rocm4.1 + name: binary_linux_wheel_py3.9_rocm4.1 + python_version: '3.9' + requires: + - download_third_parties_nix + wheel_docker_image: pytorch/manylinux-rocm:4.1 - binary_macos_wheel: cuda_version: cpu name: binary_macos_wheel_py3.6_cpu @@ -1217,6 +1245,42 @@ workflows: python_version: '3.6' requires: - nightly_binary_linux_wheel_py3.6_cu111_upload + - binary_linux_wheel: + cuda_version: rocm4.1 + filters: + branches: + only: + - nightly + tags: + only: /v[0-9]+(\.[0-9]+)*-rc[0-9]+/ + name: nightly_binary_linux_wheel_py3.6_rocm4.1 + python_version: '3.6' + requires: + - download_third_parties_nix + wheel_docker_image: pytorch/manylinux-rocm:4.1 + - binary_wheel_upload: + context: org-member + filters: + branches: + only: + - nightly + tags: + only: /v[0-9]+(\.[0-9]+)*-rc[0-9]+/ + name: nightly_binary_linux_wheel_py3.6_rocm4.1_upload + requires: + - nightly_binary_linux_wheel_py3.6_rocm4.1 + - smoke_test_linux_pip: + cuda_version: rocm4.1 + filters: + branches: + only: + - nightly + tags: + only: /v[0-9]+(\.[0-9]+)*-rc[0-9]+/ + name: nightly_binary_linux_wheel_py3.6_rocm4.1_smoke_test_pip + python_version: '3.6' + requires: + - nightly_binary_linux_wheel_py3.6_rocm4.1_upload - binary_linux_wheel: cuda_version: cpu filters: @@ -1324,6 +1388,42 @@ workflows: python_version: '3.7' requires: - nightly_binary_linux_wheel_py3.7_cu111_upload + - binary_linux_wheel: + cuda_version: rocm4.1 + filters: + branches: + only: + - nightly + tags: + only: /v[0-9]+(\.[0-9]+)*-rc[0-9]+/ + name: nightly_binary_linux_wheel_py3.7_rocm4.1 + python_version: '3.7' + requires: + - download_third_parties_nix + wheel_docker_image: pytorch/manylinux-rocm:4.1 + - binary_wheel_upload: + context: org-member + filters: + branches: + only: + - nightly + tags: + only: /v[0-9]+(\.[0-9]+)*-rc[0-9]+/ + name: nightly_binary_linux_wheel_py3.7_rocm4.1_upload + requires: + - nightly_binary_linux_wheel_py3.7_rocm4.1 + - smoke_test_linux_pip: + cuda_version: rocm4.1 + filters: + branches: + only: + - nightly + tags: + only: /v[0-9]+(\.[0-9]+)*-rc[0-9]+/ + name: nightly_binary_linux_wheel_py3.7_rocm4.1_smoke_test_pip + python_version: '3.7' + requires: + - nightly_binary_linux_wheel_py3.7_rocm4.1_upload - binary_linux_wheel: cuda_version: cpu filters: @@ -1431,6 +1531,42 @@ workflows: python_version: '3.8' requires: - nightly_binary_linux_wheel_py3.8_cu111_upload + - binary_linux_wheel: + cuda_version: rocm4.1 + filters: + branches: + only: + - nightly + tags: + only: /v[0-9]+(\.[0-9]+)*-rc[0-9]+/ + name: nightly_binary_linux_wheel_py3.8_rocm4.1 + python_version: '3.8' + requires: + - download_third_parties_nix + wheel_docker_image: pytorch/manylinux-rocm:4.1 + - binary_wheel_upload: + context: org-member + filters: + branches: + only: + - nightly + tags: + only: /v[0-9]+(\.[0-9]+)*-rc[0-9]+/ + name: nightly_binary_linux_wheel_py3.8_rocm4.1_upload + requires: + - nightly_binary_linux_wheel_py3.8_rocm4.1 + - smoke_test_linux_pip: + cuda_version: rocm4.1 + filters: + branches: + only: + - nightly + tags: + only: /v[0-9]+(\.[0-9]+)*-rc[0-9]+/ + name: nightly_binary_linux_wheel_py3.8_rocm4.1_smoke_test_pip + python_version: '3.8' + requires: + - nightly_binary_linux_wheel_py3.8_rocm4.1_upload - binary_linux_wheel: cuda_version: cpu filters: @@ -1538,6 +1674,42 @@ workflows: python_version: '3.9' requires: - nightly_binary_linux_wheel_py3.9_cu111_upload + - binary_linux_wheel: + cuda_version: rocm4.1 + filters: + branches: + only: + - nightly + tags: + only: /v[0-9]+(\.[0-9]+)*-rc[0-9]+/ + name: nightly_binary_linux_wheel_py3.9_rocm4.1 + python_version: '3.9' + requires: + - download_third_parties_nix + wheel_docker_image: pytorch/manylinux-rocm:4.1 + - binary_wheel_upload: + context: org-member + filters: + branches: + only: + - nightly + tags: + only: /v[0-9]+(\.[0-9]+)*-rc[0-9]+/ + name: nightly_binary_linux_wheel_py3.9_rocm4.1_upload + requires: + - nightly_binary_linux_wheel_py3.9_rocm4.1 + - smoke_test_linux_pip: + cuda_version: rocm4.1 + filters: + branches: + only: + - nightly + tags: + only: /v[0-9]+(\.[0-9]+)*-rc[0-9]+/ + name: nightly_binary_linux_wheel_py3.9_rocm4.1_smoke_test_pip + python_version: '3.9' + requires: + - nightly_binary_linux_wheel_py3.9_rocm4.1_upload - binary_macos_wheel: cuda_version: cpu filters: diff --git a/.circleci/regenerate.py b/.circleci/regenerate.py index f1720979fb..0f64498754 100755 --- a/.circleci/regenerate.py +++ b/.circleci/regenerate.py @@ -21,7 +21,7 @@ PYTHON_VERSIONS = ["3.6", "3.7", "3.8", "3.9"] -CU_VERSIONS_DICT = {"linux": ["cpu", "cu102", "cu111"], +CU_VERSIONS_DICT = {"linux": ["cpu", "cu102", "cu111","rocm4.1"], "windows": ["cpu", "cu102", "cu111"], "macos": ["cpu"]} @@ -36,7 +36,10 @@ def build_workflows(prefix='', upload=False, filter_branch=None, indentation=6): for os_type in ["linux", "macos", "windows"]: for python_version in PYTHON_VERSIONS: for cu_version in CU_VERSIONS_DICT[os_type]: - w += build_workflow_pair(btype, os_type, python_version, cu_version, filter_branch, prefix, upload) + if cu_version.startswith("rocm") and btype=="conda": + pass + else: + w += build_workflow_pair(btype, os_type, python_version, cu_version, filter_branch, prefix, upload) if not filter_branch: # Build on every pull request, but upload only on nightly and tags @@ -124,8 +127,10 @@ def generate_base_workflow(base_workflow_name, python_version, cu_version, filte d['requires'] = ['download_third_parties_nix'] if btype == 'conda': d['conda_docker_image'] = f'pytorch/conda-builder:{cu_version.replace("cu1","cuda1")}' - elif cu_version != 'cpu': + elif cu_version.startswith('cu'): d['wheel_docker_image'] = f'pytorch/manylinux-{cu_version.replace("cu1","cuda1")}' + elif cu_version.startswith('rocm'): + d["wheel_docker_image"] = f"pytorch/manylinux-rocm:{cu_version[len('rocm'):]}" if filter_branch: d["filters"] = gen_filter_branch_tree(filter_branch) diff --git a/.circleci/unittest/linux/scripts/install.sh b/.circleci/unittest/linux/scripts/install.sh index 3b0cd4bc4c..50a02f11e3 100755 --- a/.circleci/unittest/linux/scripts/install.sh +++ b/.circleci/unittest/linux/scripts/install.sh @@ -56,5 +56,10 @@ fi ( set -x conda install -y -c conda-forge ${NUMBA_DEV_CHANNEL} 'librosa>=0.8.0' parameterized 'requests>=2.20' - pip install kaldi-io SoundFile coverage pytest pytest-cov scipy + pip install kaldi-io SoundFile coverage pytest pytest-cov scipy transformers ) +# Install fairseq +git clone https://github.com/pytorch/fairseq +cd fairseq +git checkout e6eddd80 +pip install . diff --git a/.circleci/unittest/windows/scripts/install.sh b/.circleci/unittest/windows/scripts/install.sh index 9ed4f203ad..770bbf31dd 100644 --- a/.circleci/unittest/windows/scripts/install.sh +++ b/.circleci/unittest/windows/scripts/install.sh @@ -44,5 +44,10 @@ fi ( set -x conda install -y -c conda-forge ${NUMBA_DEV_CHANNEL} 'librosa>=0.8.0' parameterized 'requests>=2.20' - pip install kaldi-io SoundFile coverage pytest pytest-cov scipy + pip install kaldi-io SoundFile coverage pytest pytest-cov scipy transformers ) +# Install fairseq +git clone https://github.com/pytorch/fairseq +cd fairseq +git checkout e6eddd80 +pip install . diff --git a/.gitmodules b/.gitmodules index 724846120c..90318aa60c 100644 --- a/.gitmodules +++ b/.gitmodules @@ -2,3 +2,6 @@ path = third_party/kaldi/submodule url = https://github.com/kaldi-asr/kaldi ignore = dirty +[submodule "examples/libtorchaudio/simplectc"] + path = examples/libtorchaudio/simplectc + url = https://github.com/mthrok/ctcdecode diff --git a/README.md b/README.md index 820301c041..2080b5b6fb 100644 --- a/README.md +++ b/README.md @@ -2,7 +2,6 @@ torchaudio: an audio library for PyTorch ======================================== [![Build Status](https://circleci.com/gh/pytorch/audio.svg?style=svg)](https://app.circleci.com/pipelines/github/pytorch/audio) -[![Coverage](https://codecov.io/gh/pytorch/audio/branch/master/graph/badge.svg)](https://codecov.io/gh/pytorch/audio) [![Documentation](https://img.shields.io/badge/dynamic/json.svg?label=docs&url=https%3A%2F%2Fpypi.org%2Fpypi%2Ftorchaudio%2Fjson&query=%24.info.version&colorB=brightgreen&prefix=v)](https://pytorch.org/audio/) The aim of torchaudio is to apply [PyTorch](https://github.com/pytorch/pytorch) to @@ -15,16 +14,13 @@ having all the computations be through PyTorch operations which makes it easy to use and feel like a natural extension. - [Support audio I/O (Load files, Save files)](http://pytorch.org/audio/stable/) - - Load the following formats into a torch Tensor using SoX - - mp3, wav, aac, ogg, flac, avr, cdda, cvs/vms, - - aiff, au, amr, mp2, mp4, ac3, avi, wmv, - - mpeg, ircam and any other format supported by libsox. - - [Kaldi (ark/scp)](http://pytorch.org/audio/stable/kaldi_io.html) -- [Dataloaders for common audio datasets (VCTK, YesNo)](http://pytorch.org/audio/stable/datasets.html) + - Load a variety of audio formats, such as `wav`, `mp3`, `ogg`, `flac`, `opus`, `sphere`, into a torch Tensor using SoX + - [Kaldi (ark/scp)](http://pytorch.org/audio/stable/kaldi_io.html) +- [Dataloaders for common audio datasets](http://pytorch.org/audio/stable/datasets.html) - Common audio transforms - [Spectrogram, AmplitudeToDB, MelScale, MelSpectrogram, MFCC, MuLawEncoding, MuLawDecoding, Resample](http://pytorch.org/audio/stable/transforms.html) - Compliance interfaces: Run code using PyTorch that align with other libraries - - [Kaldi: spectrogram, fbank, mfcc, resample_waveform](https://pytorch.org/audio/stable/compliance.kaldi.html) + - [Kaldi: spectrogram, fbank, mfcc](https://pytorch.org/audio/stable/compliance.kaldi.html) Dependencies ------------ @@ -36,6 +32,7 @@ The following are the corresponding ``torchaudio`` versions and supported Python | ``torch`` | ``torchaudio`` | ``python`` | | ------------------------ | ------------------------ | ------------------------------- | | ``master`` / ``nightly`` | ``master`` / ``nightly`` | ``>=3.6``, ``<=3.9`` | +| ``1.9.0`` | ``0.9.0`` | ``>=3.6``, ``<=3.9`` | | ``1.8.0`` | ``0.8.0`` | ``>=3.6``, ``<=3.9`` | | ``1.7.1`` | ``0.7.2`` | ``>=3.6``, ``<=3.9`` | | ``1.7.0`` | ``0.7.0`` | ``>=3.6``, ``<=3.8`` | @@ -107,34 +104,6 @@ call "C:\Program Files (x86)\Microsoft Visual Studio\2019\Community\VC\Auxiliary This is known to work on linux and unix distributions such as Ubuntu and CentOS 7 and macOS. If you try this on a new system and find a solution to make it work, feel free to share it by opening an issue. -#### Troubleshooting - -
checking build system type... ./config.guess: unable to guess system type - -Since the configuration file for codecs are old, they cannot correctly detect the new environments, such as Jetson Aarch. You need to replace the `config.guess` file in `./third_party/tmp/lame-3.99.5/config.guess` and/or `./third_party/tmp/libmad-0.15.1b/config.guess` with [the latest one](https://github.com/gcc-mirror/gcc/blob/master/config.guess). - -See also: [#658](https://github.com/pytorch/audio/issues/658) - -
- -
Undefined reference to `tgetnum' when using `BUILD_SOX` - -If while building from within an anaconda environment you come across errors similar to the following: - -``` -../bin/ld: console.c:(.text+0xc1): undefined reference to `tgetnum' -``` - -Install `ncurses` from `conda-forge` before running `python setup.py install`: - -``` -# Install ncurses from conda-forge -conda install -c conda-forge ncurses -``` - -
- - Quick Usage ----------- @@ -161,7 +130,9 @@ waveform, sample_rate = torchaudio.load('foo.wav') # load tensor from file, as torchaudio.save('foo_save.wav', waveform, sample_rate) # save tensor to file, as usual ``` -Unlike SoX, SoundFile does not currently support mp3. +**Note** +- SoundFile currently does not support mp3. +- "soundfile" backend is not supported by TorchScript. API Reference ------------- @@ -205,7 +176,7 @@ Transforms expect and return the following dimensions. * `Fade`: (channel, time) -> (channel, time) * `Vol`: (channel, time) -> (channel, time) -Complex numbers are supported via tensors of dimension (..., 2), and torchaudio provides `complex_norm` and `angle` to convert such a tensor into its magnitude and phase. Here, and in the documentation, we use an ellipsis "..." as a placeholder for the rest of the dimensions of a tensor, e.g. optional batching and channel dimensions. +Here, and in the documentation, we use an ellipsis "..." as a placeholder for the rest of the dimensions of a tensor, e.g. optional batching and channel dimensions. Contributing Guidelines ----------------------- diff --git a/docs/requirements.txt b/docs/requirements.txt index 99a7811de6..fa5ea2b7e6 100644 --- a/docs/requirements.txt +++ b/docs/requirements.txt @@ -1,4 +1,5 @@ sphinx==2.4.4 -e git+git://github.com/pytorch/pytorch_sphinx_theme.git#egg=pytorch_sphinx_theme sphinxcontrib.katex +sphinxcontrib.bibtex matplotlib diff --git a/docs/source/_static/css/pytorch_theme.css b/docs/source/_static/css/pytorch_theme.css deleted file mode 100644 index 0e54497643..0000000000 --- a/docs/source/_static/css/pytorch_theme.css +++ /dev/null @@ -1,118 +0,0 @@ -body { - font-family: "Lato","proxima-nova","Helvetica Neue",Arial,sans-serif; -} - -/* Default header fonts are ugly */ -h1, h2, .rst-content .toctree-wrapper p.caption, h3, h4, h5, h6, legend, p.caption { - font-family: "Lato","proxima-nova","Helvetica Neue",Arial,sans-serif; -} - -/* Use white for docs background */ -.wy-side-nav-search { - background-color: #fff; -} - -.wy-nav-content-wrap, .wy-menu li.current > a { - background-color: #fff; -} - -@media screen and (min-width: 1400px) { - .wy-nav-content-wrap { - background-color: rgba(0, 0, 0, 0.0470588); - } - - .wy-nav-content { - background-color: #fff; - } -} - -/* Fixes for mobile */ -.wy-nav-top { - background-color: #fff; - background-image: url('../img/pytorch-logo-dark.svg'); - background-repeat: no-repeat; - background-position: center; - padding: 0; - margin: 0.4045em 0.809em; - color: #333; -} - -.wy-nav-top > a { - display: none; -} - -@media screen and (max-width: 768px) { - .wy-side-nav-search>a img.logo { - height: 60px; - } -} - -/* This is needed to ensure that logo above search scales properly */ -.wy-side-nav-search a { - display: block; -} - -/* This ensures that multiple constructors will remain in separate lines. */ -.rst-content dl:not(.docutils) dt { - display: table; -} - -/* Use our red for literals (it's very similar to the original color) */ -.rst-content tt.literal, .rst-content tt.literal, .rst-content code.literal { - color: #F05732; -} - -.rst-content tt.xref, a .rst-content tt, .rst-content tt.xref, -.rst-content code.xref, a .rst-content tt, a .rst-content code { - color: #404040; -} - -/* Change link colors (except for the menu) */ - -a { - color: #F05732; -} - -a:hover { - color: #F05732; -} - - -a:visited { - color: #D44D2C; -} - -.wy-menu a { - color: #b3b3b3; -} - -.wy-menu a:hover { - color: #b3b3b3; -} - -/* Default footer text is quite big */ -footer { - font-size: 80%; -} - -footer .rst-footer-buttons { - font-size: 125%; /* revert footer settings - 1/80% = 125% */ -} - -footer p { - font-size: 100%; -} - -/* For hidden headers that appear in TOC tree */ -/* see http://stackoverflow.com/a/32363545/3343043 */ -.rst-content .hidden-section { - display: none; -} - -nav .hidden-section { - display: inherit; -} - -.wy-side-nav-search>div.version { - color: #000; -} diff --git a/docs/source/compliance.kaldi.rst b/docs/source/compliance.kaldi.rst index cc75021d69..72827ca3fb 100644 --- a/docs/source/compliance.kaldi.rst +++ b/docs/source/compliance.kaldi.rst @@ -29,8 +29,3 @@ Functions ~~~~~~~~~~~~~~~~~~~~~~~~~~ .. autofunction:: mfcc - -:hidden:`resample_waveform` -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -.. autofunction:: resample_waveform diff --git a/docs/source/conf.py b/docs/source/conf.py index f78858e381..c3364d7fd7 100644 --- a/docs/source/conf.py +++ b/docs/source/conf.py @@ -41,6 +41,7 @@ 'sphinx.ext.napoleon', 'sphinx.ext.viewcode', 'sphinxcontrib.katex', + 'sphinxcontrib.bibtex', ] # katex options @@ -55,6 +56,8 @@ ] ''' +bibtex_bibfiles = ['refs.bib'] + napoleon_use_ivar = True napoleon_numpy_docstring = False napoleon_google_docstring = True @@ -133,22 +136,9 @@ # relative to this directory. They are copied after the builtin static files, # so a file named "default.css" will overwrite the builtin "default.css". html_static_path = ['_static'] - - -def setup(app): - # NOTE: in Sphinx 1.8+ `html_css_files` is an official configuration value - # and can be moved outside of this function (and the setup(app) function - # can be deleted). - html_css_files = [ - 'https://cdn.jsdelivr.net/npm/katex@0.10.0-beta/dist/katex.min.css' - ] - - # In Sphinx 1.8 it was renamed to `add_css_file`, 1.7 and prior it is - # `add_stylesheet` (deprecated in 1.8). - add_css = getattr(app, 'add_css_file', app.add_stylesheet) - for css_file in html_css_files: - add_css(css_file) - +html_css_files = [ + 'https://cdn.jsdelivr.net/npm/katex@0.10.0-beta/dist/katex.min.css' +] # -- Options for HTMLHelp output ------------------------------------------ diff --git a/docs/source/functional.rst b/docs/source/functional.rst index 98517929ea..37593da3fc 100644 --- a/docs/source/functional.rst +++ b/docs/source/functional.rst @@ -56,6 +56,11 @@ apply_codec .. autofunction:: apply_codec +resample +-------- + +.. autofunction:: resample + :hidden:`Complex Utility` ~~~~~~~~~~~~~~~~~~~~~~~~~ @@ -231,7 +236,7 @@ vad .. autofunction:: spectral_centroid -:hidden:`resample` ---------------------------- +References +~~~~~~~~~~ -.. autofunction:: resample +.. footbibliography:: diff --git a/docs/source/models.rst b/docs/source/models.rst index 2030eefd28..39e162baa0 100644 --- a/docs/source/models.rst +++ b/docs/source/models.rst @@ -2,40 +2,94 @@ :class: hidden-section torchaudio.models -====================== +================= .. currentmodule:: torchaudio.models The models subpackage contains definitions of models for addressing common audio tasks. -:hidden:`ConvTasNet` -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +ConvTasNet +~~~~~~~~~~ .. autoclass:: ConvTasNet .. automethod:: forward -:hidden:`DeepSpeech` -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +DeepSpeech +~~~~~~~~~~ .. autoclass:: DeepSpeech .. automethod:: forward -:hidden:`Wav2Letter` -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +Wav2Letter +~~~~~~~~~~ .. autoclass:: Wav2Letter .. automethod:: forward -:hidden:`WaveRNN` -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Wav2Vec2.0 +~~~~~~~~~~ + +Wav2Vec2Model +------------- + +.. autoclass:: Wav2Vec2Model + + .. automethod:: extract_features + + .. automethod:: forward + +Factory Functions +----------------- + +wav2vec2_base +------------- + +.. autofunction:: wav2vec2_base + +wav2vec2_large +-------------- + +.. autofunction:: wav2vec2_large + +wav2vec2_large_lv60k +-------------------- + +.. autofunction:: wav2vec2_large_lv60k + +.. currentmodule:: torchaudio.models.wav2vec2.utils + +Utility Functions +----------------- + +import_huggingface_model +------------------------ + +.. autofunction:: import_huggingface_model + +import_fairseq_model +-------------------- + +.. autofunction:: import_fairseq_model + +.. currentmodule:: torchaudio.models + +WaveRNN +~~~~~~~ .. autoclass:: WaveRNN .. automethod:: forward + +References +~~~~~~~~~~ + +.. footbibliography:: + diff --git a/docs/source/refs.bib b/docs/source/refs.bib new file mode 100644 index 0000000000..c6ddb3b61a --- /dev/null +++ b/docs/source/refs.bib @@ -0,0 +1,90 @@ +@misc{baevski2020wav2vec, + title={wav2vec 2.0: A Framework for Self-Supervised Learning of Speech Representations}, + author={Alexei Baevski and Henry Zhou and Abdelrahman Mohamed and Michael Auli}, + year={2020}, + eprint={2006.11477}, + archivePrefix={arXiv}, + primaryClass={cs.CL} +} +@misc{hannun2014deep, + title={Deep Speech: Scaling up end-to-end speech recognition}, + author={Awni Hannun and Carl Case and Jared Casper and Bryan Catanzaro and Greg Diamos and Erich Elsen and Ryan Prenger and Sanjeev Satheesh and Shubho Sengupta and Adam Coates and Andrew Y. Ng}, + year={2014}, + eprint={1412.5567}, + archivePrefix={arXiv}, + primaryClass={cs.CL} +} +@misc{graves2012sequence, + title={Sequence Transduction with Recurrent Neural Networks}, + author={Alex Graves}, + year={2012}, + eprint={1211.3711}, + archivePrefix={arXiv}, + primaryClass={cs.NE} +} +@misc{collobert2016wav2letter, + title={Wav2Letter: an End-to-End ConvNet-based Speech Recognition System}, + author={Ronan Collobert and Christian Puhrsch and Gabriel Synnaeve}, + year={2016}, + eprint={1609.03193}, + archivePrefix={arXiv}, + primaryClass={cs.LG} +} +@misc{kalchbrenner2018efficient, + title={Efficient Neural Audio Synthesis}, + author={Nal Kalchbrenner and Erich Elsen and Karen Simonyan and Seb Noury and Norman Casagrande and Edward Lockhart and Florian Stimberg and Aaron van den Oord and Sander Dieleman and Koray Kavukcuoglu}, + year={2018}, + eprint={1802.08435}, + archivePrefix={arXiv}, + primaryClass={cs.SD} +} +@article{Luo_2019, + title={Conv-TasNet: Surpassing Ideal Timeโ€“Frequency Magnitude Masking for Speech Separation}, + volume={27}, + ISSN={2329-9304}, + url={http://dx.doi.org/10.1109/TASLP.2019.2915167}, + DOI={10.1109/taslp.2019.2915167}, + number={8}, + journal={IEEE/ACM Transactions on Audio, Speech, and Language Processing}, + publisher={Institute of Electrical and Electronics Engineers (IEEE)}, + author={Luo, Yi and Mesgarani, Nima}, + year={2019}, + month={Aug}, + pages={1256โ€“1266} +} +@InProceedings{ brian_mcfee-proc-scipy-2015, + author = { {B}rian {M}c{F}ee and {C}olin {R}affel and {D}awen {L}iang and {D}aniel {P}.{W}. {E}llis and {M}att {M}c{V}icar and {E}ric {B}attenberg and {O}riol {N}ieto }, + title = { librosa: {A}udio and {M}usic {S}ignal {A}nalysis in {P}ython }, + booktitle = { {P}roceedings of the 14th {P}ython in {S}cience {C}onference }, + pages = { 18 - 24 }, + year = { 2015 }, + editor = { {K}athryn {H}uff and {J}ames {B}ergstra }, + doi = { 10.25080/Majora-7b98e3ed-003 } +} +@INPROCEEDINGS{6701851, + author={Perraudin, Nathanaรซl and Balazs, Peter and Sรธndergaard, Peter L.}, + booktitle={2013 IEEE Workshop on Applications of Signal Processing to Audio and Acoustics}, + title={A fast Griffin-Lim algorithm}, + year={2013}, + volume={}, + number={}, + pages={1-4}, + doi={10.1109/WASPAA.2013.6701851}} +@INPROCEEDINGS{1172092, + author={Griffin, D. and Jae Lim}, + booktitle={ICASSP '83. IEEE International Conference on Acoustics, Speech, and Signal Processing}, + title={Signal estimation from modified short-time Fourier transform}, + year={1983}, + volume={8}, + number={}, + pages={804-807}, + doi={10.1109/ICASSP.1983.1172092}} +@INPROCEEDINGS{6854049, + author={Ghahremani, Pegah and BabaAli, Bagher and Povey, Daniel and Riedhammer, Korbinian and Trmal, Jan and Khudanpur, Sanjeev}, + booktitle={2014 IEEE International Conference on Acoustics, Speech and Signal Processing (ICASSP)}, + title={A pitch extraction algorithm tuned for automatic speech recognition}, + year={2014}, + volume={}, + number={}, + pages={2494-2498}, + doi={10.1109/ICASSP.2014.6854049}} diff --git a/docs/source/rnnt_loss.rst b/docs/source/rnnt_loss.rst index 0c3b075d65..6e8ac81909 100644 --- a/docs/source/rnnt_loss.rst +++ b/docs/source/rnnt_loss.rst @@ -2,7 +2,7 @@ :class: hidden-section torchaudio.prototype.rnnt_loss -=============================== +============================== .. currentmodule:: torchaudio.prototype.rnnt_loss @@ -11,13 +11,18 @@ torchaudio.prototype.rnnt_loss The RNN transducer loss is a prototype feature, see `here `_ to learn more about the nomenclature. It is only available within the nightlies, and also needs to be imported explicitly using: :code:`from torchaudio.prototype.rnnt_loss import rnnt_loss, RNNTLoss`. rnnt_loss ---------- +~~~~~~~~~ .. autofunction:: rnnt_loss -:hidden:`RNNTLoss` -~~~~~~~~~~~~~~~~~~ +RNNTLoss +~~~~~~~~ .. autoclass:: RNNTLoss .. automethod:: forward + +References +~~~~~~~~~~ + +.. footbibliography:: diff --git a/docs/source/transforms.rst b/docs/source/transforms.rst index 8269193e22..787673f8df 100644 --- a/docs/source/transforms.rst +++ b/docs/source/transforms.rst @@ -53,99 +53,105 @@ Transforms are common audio transforms. They can be chained together using :clas .. automethod:: forward :hidden:`MFCC` -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +~~~~~~~~~~~~~~ .. autoclass:: MFCC .. automethod:: forward :hidden:`MuLawEncoding` -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +~~~~~~~~~~~~~~~~~~~~~~~ .. autoclass:: MuLawEncoding .. automethod:: forward :hidden:`MuLawDecoding` -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +~~~~~~~~~~~~~~~~~~~~~~~ .. autoclass:: MuLawDecoding .. automethod:: forward :hidden:`Resample` -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +~~~~~~~~~~~~~~~~~~ .. autoclass:: Resample .. automethod:: forward :hidden:`ComplexNorm` -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +~~~~~~~~~~~~~~~~~~~~~ .. autoclass:: ComplexNorm .. automethod:: forward :hidden:`ComputeDeltas` -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +~~~~~~~~~~~~~~~~~~~~~~~ .. autoclass:: ComputeDeltas .. automethod:: forward :hidden:`TimeStretch` -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +~~~~~~~~~~~~~~~~~~~~~ .. autoclass:: TimeStretch .. automethod:: forward :hidden:`Fade` -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +~~~~~~~~~~~~~~ .. autoclass:: Fade .. automethod:: forward :hidden:`FrequencyMasking` -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +~~~~~~~~~~~~~~~~~~~~~~~~~~ .. autoclass:: FrequencyMasking .. automethod:: forward :hidden:`TimeMasking` -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +~~~~~~~~~~~~~~~~~~~~~ .. autoclass:: TimeMasking .. automethod:: forward :hidden:`Vol` -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +~~~~~~~~~~~~~ .. autoclass:: Vol .. automethod:: forward :hidden:`SlidingWindowCmn` -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +~~~~~~~~~~~~~~~~~~~~~~~~~~ .. autoclass:: SlidingWindowCmn .. automethod:: forward :hidden:`SpectralCentroid` -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +~~~~~~~~~~~~~~~~~~~~~~~~~~ .. autoclass:: SpectralCentroid .. automethod:: forward :hidden:`Vad` -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +~~~~~~~~~~~~~ .. autoclass:: Vad .. automethod:: forward + + +References +~~~~~~~~~~ + +.. footbibliography:: diff --git a/examples/libtorchaudio/.gitignore b/examples/libtorchaudio/.gitignore index f03338dc7d..d2c4084e75 100644 --- a/examples/libtorchaudio/.gitignore +++ b/examples/libtorchaudio/.gitignore @@ -1,3 +1,4 @@ build data/output.wav -data/pipeline.zip +*.zip +output diff --git a/examples/libtorchaudio/CMakeLists.txt b/examples/libtorchaudio/CMakeLists.txt index 6a359bd47e..6d7607cc0e 100644 --- a/examples/libtorchaudio/CMakeLists.txt +++ b/examples/libtorchaudio/CMakeLists.txt @@ -14,4 +14,6 @@ message("libtorchaudio CMakeLists: ${TORCH_CXX_FLAGS}") set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${TORCH_CXX_FLAGS}") add_subdirectory(../.. libtorchaudio) +add_subdirectory(simplectc) add_subdirectory(augmentation) +add_subdirectory(speech_recognition) diff --git a/examples/libtorchaudio/README.md b/examples/libtorchaudio/README.md index be6611ea85..477a3d7e54 100644 --- a/examples/libtorchaudio/README.md +++ b/examples/libtorchaudio/README.md @@ -1,6 +1,7 @@ # Libtorchaudio Examples * [Augmentation](./augmentation) +* [Speech Recognition with wav2vec2.0](./speech_recognition) ## Build @@ -14,6 +15,7 @@ It is currently not distributed, and it will be built alongside with the applica The following commands will build `libtorchaudio` and applications. ```bash +git submodule update mkdir build cd build cmake -GNinja \ diff --git a/examples/libtorchaudio/build.sh b/examples/libtorchaudio/build.sh index 11ca65f751..ac51caf34c 100755 --- a/examples/libtorchaudio/build.sh +++ b/examples/libtorchaudio/build.sh @@ -8,6 +8,7 @@ build_dir="${this_dir}/build" mkdir -p "${build_dir}" cd "${build_dir}" +git submodule update cmake -GNinja \ -DCMAKE_PREFIX_PATH="$(python -c 'import torch;print(torch.utils.cmake_prefix_path)')" \ -DBUILD_SOX=ON \ diff --git a/examples/libtorchaudio/speech_recognition/CMakeLists.txt b/examples/libtorchaudio/speech_recognition/CMakeLists.txt new file mode 100644 index 0000000000..3771a33442 --- /dev/null +++ b/examples/libtorchaudio/speech_recognition/CMakeLists.txt @@ -0,0 +1,6 @@ +add_executable(transcribe transcribe.cpp) +add_executable(transcribe_list transcribe_list.cpp) +target_link_libraries(transcribe "${TORCH_LIBRARIES}" "${TORCHAUDIO_LIBRARY}" "${CTCDECODE_LIBRARY}") +target_link_libraries(transcribe_list "${TORCH_LIBRARIES}" "${TORCHAUDIO_LIBRARY}" "${CTCDECODE_LIBRARY}") +set_property(TARGET transcribe PROPERTY CXX_STANDARD 14) +set_property(TARGET transcribe_list PROPERTY CXX_STANDARD 14) diff --git a/examples/libtorchaudio/speech_recognition/README.md b/examples/libtorchaudio/speech_recognition/README.md new file mode 100644 index 0000000000..6a617a8ebf --- /dev/null +++ b/examples/libtorchaudio/speech_recognition/README.md @@ -0,0 +1,187 @@ +# Speech Recognition with wav2vec2.0 + +This example demonstarates how you can use torchaudio's I/O features and models to run speech recognition in C++ application. + +**NOTE** +This example uses `"sox_io"` backend for loading audio, which does not work on Windows. To make it work on +Windows, you need to replace the part of loading audio and converting it to Tensor object. + +## 1. Create a transcription pipeline TorchScript file + +We will create a TorchScript that performs the following processes; + +1. Load audio from a file. +1. Pass audio to encoder which produces the sequence of probability distribution on labels. +1. Pass the encoder output to decoder which generates transcripts. + +For building decoder, we borrow the pre-trained weights published by `fairseq` and/or Hugging Face Transformers, then convert it `torchaudio`'s format, which supports TorchScript. + +### 1.1. From `fairseq` + +For `fairseq` models, you can download pre-trained weights +You can download a model from [`fairseq` repository](https://github.com/pytorch/fairseq/tree/master/examples/wav2vec). Here, we will use `Base / 960h` model. You also need to download [the letter dictionary file](https://github.com/pytorch/fairseq/tree/master/examples/wav2vec#evaluating-a-ctc-model). + +For the decoder part, we use [simple_ctc](https://github.com/mthrok/ctcdecode), which also supports TorchScript. + +```bash +mkdir -p pipeline-fairseq +python build_pipeline_from_fairseq.py \ + --model-file "wav2vec_small_960.pt" \ + --dict-dir \ + --output-path "./pipeline-fairseq/" +``` + +The above command should create the following TorchScript object files in the output directory. + +``` +decoder.zip encoder.zip loader.zip +``` + +* `loader.zip` loads audio file and generate waveform Tensor. +* `encoder.zip` receives waveform Tensor and generates the sequence of probability distribution over the label. +* `decoder.zip` receives the probability distribution over the label and generates a transcript. + +### 1.2. From Hugging Face Transformers + + +[Hugging Face Transformers](https://huggingface.co/transformers/index.html) and [Hugging Face Model Hub](https://huggingface.co/models) provides `wav2vec2.0` models fine-tuned on variety of datasets and languages. + +We can also import the model published on Hugging Face Hub and run it in our C++ application. +In the following example, we will try the Geremeny model, ([facebook/wav2vec2-large-xlsr-53-german](https://huggingface.co/facebook/wav2vec2-large-xlsr-53-german/tree/main)) on [VoxForge Germany dataset](http://www.voxforge.org/de/downloads). + +```bash +mkdir -p pipeline-hf +python build_pipeline_from_huggingface_transformers.py \ + --model facebook/wav2vec2-large-xlsr-53-german \ + --output-path ./pipeline-hf/ +``` + +The resulting TorchScript object files should be same as the `fairseq` example. + +## 2. Build the application + +Please refer to [the top level README.md](../README.md) + +## 3. Run the application + +Now we run the C++ application [`transcribe`](./transcribe.cpp), with the TorchScript object we created in Step.1.1. and an input audio file. + +```bash +../build/speech_recognition/transcribe ./pipeline-fairseq ../data/input.wav +``` + +This will output something like the following. + +``` +Loading module from: ./pipeline/loader.zip +Loading module from: ./pipeline/encoder.zip +Loading module from: ./pipeline/decoder.zip +Loading the audio +Running inference +Generating the transcription +I HAD THAT CURIOSITY BESIDE ME AT THIS MOMENT +Done. +``` + +## 4. Evaluate the pipeline on Librispeech dataset + +Let's evaluate this word error rate (WER) of this application using [Librispeech dataset](https://www.openslr.org/12). + +### 4.1. Create a list of audio paths + +For the sake of simplifying our C++ code, we will first parse the Librispeech dataset to get the list of audio path + +```bash +python parse_librispeech.py /LibriSpeech/test-clean ./flist.txt +``` + +The list should look like the following; + +```bash +head flist.txt + +1089-134691-0000 /LibriSpeech/test-clean/1089/134691/1089-134691-0000.flac HE COULD WAIT NO LONGER +``` + +### 4.2. Run the transcription + +[`transcribe_list`](./transcribe_list.cpp) processes the input flist list and feed the audio path one by one to the pipeline, then generate reference file and hypothesis file. + +```bash +../build/speech_recognition/transcribe_list ./pipeline-fairseq ./flist.txt +``` + +### 4.3. Score WER + +You need `sclite` for this step. You can download the code from [SCTK repository](https://github.com/usnistgov/SCTK). + +```bash +# in the output directory +sclite -r ref.trn -h hyp.trn -i wsj -o pralign -o sum +``` + +WER can be found in the resulting `hyp.trn.sys`. Check out the column that starts with `Sum/Avg` the first column of the third block is `100 - WER`. + +In our test, we got the following results. + +| model | Fine Tune | test-clean | test-other | +|:-----------------------------------------:|----------:|:----------:|:----------:| +| Base
`wav2vec_small_960` | 960h | 3.1 | 7.7 | +| Large
`wav2vec_big_960` | 960h | 2.6 | 5.9 | +| Large (LV-60)
`wav2vec2_vox_960h_new` | 960h | 2.9 | 6.2 | +| Large (LV-60) + Self Training
`wav2vec_vox_960h_pl` | 960h | 1.9 | 4.5 | + + +You can also check `hyp.trn.pra` file to see what errors were made. + +``` +id: (3528-168669-0005) +Scores: (#C #S #D #I) 7 1 0 0 +REF: there is a stone to be RAISED heavy +HYP: there is a stone to be RACED heavy +Eval: S +``` + +## 5. Evaluate the pipeline on VoxForge dataset + +Now we use the pipeline we created in step 1.2. This time with German language dataset from VoxForge. + +### 5.1. Create a list of audio paths + +Download an archive from http://www.repository.voxforge1.org/downloads/de/Trunk/Audio/Main/16kHz_16bit/, and extract it to your local file system, then run the following to generate the file list. + +```bash +python parse_voxforge.py > ./flist-de.txt +``` + +The list should look like + +```bash +head flist-de.txt +de5-001 /datasets/voxforge/de/guenter-20140214-afn/wav/de5-001.wav ES SOLL ETWA FรœNFZIGTAUSEND VERSCHIEDENE SORTEN GEBEN +``` + +### 5.2. Run the application and score WER + +This process is same as the Librispeech example. We just use the pipeline with the Germany model and file list of Germany dataset. Refer to the corresponding ssection in Librispeech evaluation.. + +```bash +../build/speech_recognition/transcribe_list ./pipeline-hf ./flist-de.txt +``` + +Then + +```bash +# in the output directory +sclite -r ref.trn -h hyp.trn -i wsj -o pralign -o sum +``` + +You can find the detail of evalauation result in PRA. + +``` +id: (guenter-20140214-afn/mfc/de5-012) +Scores: (#C #S #D #I) 4 1 1 0 +REF: die ausgaben kร–nnen gigantisch STEIGE N +HYP: die ausgaben kร–nnen gigantisch ****** STEIGEN +Eval: D S +``` diff --git a/examples/libtorchaudio/speech_recognition/build_pipeline_from_fairseq.py b/examples/libtorchaudio/speech_recognition/build_pipeline_from_fairseq.py new file mode 100644 index 0000000000..3b6dbafe41 --- /dev/null +++ b/examples/libtorchaudio/speech_recognition/build_pipeline_from_fairseq.py @@ -0,0 +1,202 @@ +#!/usr/bin/evn python3 +"""Build Speech Recognition pipeline based on fairseq's wav2vec2.0 and dump it to TorchScript file. + +To use this script, you need `fairseq`. +""" +import os +import argparse +import logging + +import torch +from torch.utils.mobile_optimizer import optimize_for_mobile +import torchaudio +from torchaudio.models.wav2vec2.utils.import_fairseq import import_fairseq_model +import fairseq +import simple_ctc + +_LG = logging.getLogger(__name__) + + +def _parse_args(): + parser = argparse.ArgumentParser( + description=__doc__, + ) + parser.add_argument( + '--model-file', + required=True, + help='Path to the input pretrained weight file.' + ) + parser.add_argument( + '--dict-dir', + help=( + 'Path to the directory in which `dict.ltr.txt` file is found. ' + 'Required only when the model is finetuned.' + ) + ) + parser.add_argument( + '--output-path', + help='Path to the directory, where the TorchScript-ed pipelines are saved.', + ) + parser.add_argument( + '--test-file', + help='Path to a test audio file.', + ) + parser.add_argument( + '--debug', + action='store_true', + help=( + 'When enabled, individual components are separately tested ' + 'for the numerical compatibility and TorchScript compatibility.' + ) + ) + parser.add_argument( + '--quantize', + action='store_true', + help='Apply quantization to model.' + ) + parser.add_argument( + '--optimize-for-mobile', + action='store_true', + help='Apply optmization for mobile.' + ) + return parser.parse_args() + + +class Loader(torch.nn.Module): + def forward(self, audio_path: str) -> torch.Tensor: + waveform, sample_rate = torchaudio.load(audio_path) + if sample_rate != 16000: + waveform = torchaudio.functional.resample(waveform, float(sample_rate), 16000.) + return waveform + + +class Encoder(torch.nn.Module): + def __init__(self, encoder: torch.nn.Module): + super().__init__() + self.encoder = encoder + + def forward(self, waveform: torch.Tensor) -> torch.Tensor: + result, _ = self.encoder(waveform) + return result + + +class Decoder(torch.nn.Module): + def __init__(self, decoder: torch.nn.Module): + super().__init__() + self.decoder = decoder + + def forward(self, emission: torch.Tensor) -> str: + result = self.decoder.decode(emission) + return ''.join(result.label_sequences[0][0]).replace('|', ' ') + + +def _get_decoder(): + labels = [ + "", + "", + "", + "", + "|", + "E", + "T", + "A", + "O", + "N", + "I", + "H", + "S", + "R", + "D", + "L", + "U", + "M", + "W", + "C", + "F", + "G", + "Y", + "P", + "B", + "V", + "K", + "'", + "X", + "J", + "Q", + "Z", + ] + + return Decoder( + simple_ctc.BeamSearchDecoder( + labels, + cutoff_top_n=40, + cutoff_prob=0.8, + beam_size=100, + num_processes=1, + blank_id=0, + is_nll=True, + ) + ) + + +def _load_fairseq_model(input_file, data_dir=None): + overrides = {} + if data_dir: + overrides['data'] = data_dir + + model, _, _ = fairseq.checkpoint_utils.load_model_ensemble_and_task( + [input_file], arg_overrides=overrides + ) + model = model[0] + return model + + +def _get_model(model_file, dict_dir): + original = _load_fairseq_model(model_file, dict_dir) + model = import_fairseq_model(original.w2v_encoder) + return model + + +def _main(): + args = _parse_args() + _init_logging(args.debug) + loader = Loader() + model = _get_model(args.model_file, args.dict_dir).eval() + encoder = Encoder(model) + decoder = _get_decoder() + _LG.info(encoder) + + if args.quantize: + _LG.info('Quantizing the model') + model.encoder.transformer.pos_conv_embed.__prepare_scriptable__() + encoder = torch.quantization.quantize_dynamic( + encoder, qconfig_spec={torch.nn.Linear}, dtype=torch.qint8) + _LG.info(encoder) + + # test + if args.test_file: + _LG.info('Testing with %s', args.test_file) + waveform = loader(args.test_file) + emission = encoder(waveform) + transcript = decoder(emission) + _LG.info(transcript) + + torch.jit.script(loader).save(os.path.join(args.output_path, 'loader.zip')) + torch.jit.script(decoder).save(os.path.join(args.output_path, 'decoder.zip')) + scripted = torch.jit.script(encoder) + if args.optimize_for_mobile: + scripted = optimize_for_mobile(scripted) + scripted.save(os.path.join(args.output_path, 'encoder.zip')) + + +def _init_logging(debug=False): + level = logging.DEBUG if debug else logging.INFO + format_ = ( + '%(message)s' if not debug else + '%(asctime)s: %(levelname)7s: %(funcName)10s: %(message)s' + ) + logging.basicConfig(level=level, format=format_) + + +if __name__ == '__main__': + _main() diff --git a/examples/libtorchaudio/speech_recognition/build_pipeline_from_huggingface_transformers.py b/examples/libtorchaudio/speech_recognition/build_pipeline_from_huggingface_transformers.py new file mode 100644 index 0000000000..5c6466f205 --- /dev/null +++ b/examples/libtorchaudio/speech_recognition/build_pipeline_from_huggingface_transformers.py @@ -0,0 +1,142 @@ +#!/usr/bin/env python3 +import argparse +import logging +import os + +import torch +import torchaudio +from torchaudio.models.wav2vec2.utils.import_huggingface import import_huggingface_model +import simple_ctc + + +_LG = logging.getLogger(__name__) + + +def _parse_args(): + parser = argparse.ArgumentParser( + description=__doc__, + ) + parser.add_argument( + '--model', + required=True, + help='Path to the input pretrained weight file.' + ) + parser.add_argument( + '--output-path', + help='Path to the directory, where the Torchscript-ed pipelines are saved.', + ) + parser.add_argument( + '--test-file', + help='Path to a test audio file.', + ) + parser.add_argument( + '--quantize', + action='store_true', + help='Quantize the model.', + ) + parser.add_argument( + '--debug', + action='store_true', + help=( + 'When enabled, individual components are separately tested ' + 'for the numerical compatibility and TorchScript compatibility.' + ) + ) + return parser.parse_args() + + +class Loader(torch.nn.Module): + def forward(self, audio_path: str) -> torch.Tensor: + waveform, sample_rate = torchaudio.load(audio_path) + if sample_rate != 16000: + waveform = torchaudio.functional.resample(waveform, float(sample_rate), 16000.) + return waveform + + +class Encoder(torch.nn.Module): + def __init__(self, encoder: torch.nn.Module): + super().__init__() + self.encoder = encoder + + def forward(self, waveform: torch.Tensor) -> torch.Tensor: + length = torch.tensor([waveform.shape[1]]) + result, length = self.encoder(waveform, length) + return result + + +class Decoder(torch.nn.Module): + def __init__(self, decoder: torch.nn.Module): + super().__init__() + self.decoder = decoder + + def forward(self, emission: torch.Tensor) -> str: + result = self.decoder.decode(emission) + return ''.join(result.label_sequences[0][0]).replace('|', ' ') + + +def _get_model(model_id): + from transformers import Wav2Vec2ForCTC, Wav2Vec2Processor + tokenizer = Wav2Vec2Processor.from_pretrained(model_id).tokenizer + labels = [k for k, v in sorted(tokenizer.get_vocab().items(), key=lambda kv: kv[1])] + original = Wav2Vec2ForCTC.from_pretrained(model_id) + model = import_huggingface_model(original) + return model.eval(), labels + + +def _get_decoder(labels): + return Decoder( + simple_ctc.BeamSearchDecoder( + labels, + cutoff_top_n=40, + cutoff_prob=0.8, + beam_size=100, + num_processes=1, + blank_id=0, + is_nll=True, + ) + ) + + +def _main(): + args = _parse_args() + _init_logging(args.debug) + _LG.info('Loading model: %s', args.model) + model, labels = _get_model(args.model) + _LG.info('Labels: %s', labels) + _LG.info('Building pipeline') + loader = Loader() + encoder = Encoder(model) + decoder = _get_decoder(labels) + _LG.info(encoder) + + if args.quantize: + _LG.info('Quantizing the model') + model.encoder.transformer.pos_conv_embed.__prepare_scriptable__() + encoder = torch.quantization.quantize_dynamic( + encoder, qconfig_spec={torch.nn.Linear}, dtype=torch.qint8) + _LG.info(encoder) + + # test + if args.test_file: + _LG.info('Testing with %s', args.test_file) + waveform = loader(args.test_file) + emission = encoder(waveform) + transcript = decoder(emission) + _LG.info(transcript) + + torch.jit.script(loader).save(os.path.join(args.output_path, 'loader.zip')) + torch.jit.script(encoder).save(os.path.join(args.output_path, 'encoder.zip')) + torch.jit.script(decoder).save(os.path.join(args.output_path, 'decoder.zip')) + + +def _init_logging(debug=False): + level = logging.DEBUG if debug else logging.INFO + format_ = ( + '%(message)s' if not debug else + '%(asctime)s: %(levelname)7s: %(funcName)10s: %(message)s' + ) + logging.basicConfig(level=level, format=format_) + + +if __name__ == '__main__': + _main() diff --git a/examples/libtorchaudio/speech_recognition/parse_librispeech.py b/examples/libtorchaudio/speech_recognition/parse_librispeech.py new file mode 100644 index 0000000000..dcd7aaf938 --- /dev/null +++ b/examples/libtorchaudio/speech_recognition/parse_librispeech.py @@ -0,0 +1,55 @@ +#!/usr/bin/env python3 +"""Parse a directory contains Librispeech dataset. + +Recursively search for "*.trans.txt" file in the given directory and print out + +`\\t\\t` + +example: python parse_librispeech.py LibriSpeech/test-clean + + 1089-134691-0000\t/LibriSpeech/test-clean/1089/134691/1089-134691-0000.flac\tHE COULD WAIT NO LONGER + ... + +Dataset can be obtained from https://www.openslr.org/12 +""" +import argparse +from pathlib import Path + + +def _parse_args(): + parser = argparse.ArgumentParser( + description=__doc__, + formatter_class=argparse.RawTextHelpFormatter, + ) + parser.add_argument( + 'input_dir', + type=Path, + help='Directory where `*.trans.txt` files are searched.' + ) + return parser.parse_args() + + +def _parse_transcript(path): + with open(path) as trans_fileobj: + for line in trans_fileobj: + line = line.strip() + if line: + yield line.split(' ', maxsplit=1) + + +def _parse_directory(root_dir: Path): + for trans_file in root_dir.glob('**/*.trans.txt'): + trans_dir = trans_file.parent + for id_, transcription in _parse_transcript(trans_file): + audio_path = trans_dir / f'{id_}.flac' + yield id_, audio_path, transcription + + +def _main(): + args = _parse_args() + for id_, path, transcription in _parse_directory(args.input_dir): + print(f'{id_}\t{path}\t{transcription}') + + +if __name__ == '__main__': + _main() diff --git a/examples/libtorchaudio/speech_recognition/parse_voxforge.py b/examples/libtorchaudio/speech_recognition/parse_voxforge.py new file mode 100644 index 0000000000..1f5f8991e0 --- /dev/null +++ b/examples/libtorchaudio/speech_recognition/parse_voxforge.py @@ -0,0 +1,67 @@ +#!/usr/bin/env python +"""Parse a directory contains VoxForge dataset. + +Recursively search for "PROMPTS" file in the given directory and print out + +`\\t\\t` + +example: python parse_voxforge.py voxforge/de/Helge-20150608-aku + + de5-001\t/datasets/voxforge/de/guenter-20140214-afn/wav/de5-001.wav\tES SOLL ETWA FรœNFZIGTAUSEND VERSCHIEDENE SORTEN GEBEN + ... + +Dataset can be obtained from http://www.repository.voxforge1.org/downloads/de/Trunk/Audio/Main/16kHz_16bit/ +""" +import os +import argparse +from pathlib import Path + + +def _parse_args(): + parser = argparse.ArgumentParser( + description=__doc__, + formatter_class=argparse.RawTextHelpFormatter, + ) + parser.add_argument( + 'input_dir', + type=Path, + help='Directory where `*.trans.txt` files are searched.' + ) + return parser.parse_args() + + +def _parse_prompts(path): + base_dir = path.parent.parent + with open(path) as trans_fileobj: + for line in trans_fileobj: + line = line.strip() + if not line: + continue + + id_, transcript = line.split(' ', maxsplit=1) + if not transcript: + continue + + transcript = transcript.upper() + filename = id_.split('/')[-1] + audio_path = base_dir / 'wav' / f'{filename}.wav' + if os.path.exists(audio_path): + yield id_, audio_path, transcript + + +def _parse_directory(root_dir: Path): + for prompt_file in root_dir.glob('**/PROMPTS'): + try: + yield from _parse_prompts(prompt_file) + except UnicodeDecodeError: + pass + + +def _main(): + args = _parse_args() + for id_, path, transcription in _parse_directory(args.input_dir): + print(f'{id_}\t{path}\t{transcription}') + + +if __name__ == '__main__': + _main() diff --git a/examples/libtorchaudio/speech_recognition/transcribe.cpp b/examples/libtorchaudio/speech_recognition/transcribe.cpp new file mode 100644 index 0000000000..e6d65b17e4 --- /dev/null +++ b/examples/libtorchaudio/speech_recognition/transcribe.cpp @@ -0,0 +1,38 @@ +#include + +int main(int argc, char* argv[]) { + if (argc != 3) { + std::cerr << "Usage: " << argv[0] << " " << std::endl; + return -1; + } + + torch::jit::script::Module loader, encoder, decoder; + std::cout << "Loading module from: " << argv[1] << std::endl; + try { + loader = torch::jit::load(std::string(argv[1]) + "/loader.zip"); + } catch (const c10::Error &error) { + std::cerr << "Failed to load the module:" << error.what() << std::endl; + return -1; + } + try { + encoder = torch::jit::load(std::string(argv[1]) + "/encoder.zip"); + } catch (const c10::Error &error) { + std::cerr << "Failed to load the module:" << error.what() << std::endl; + return -1; + } + try { + decoder = torch::jit::load(std::string(argv[1]) + "/decoder.zip"); + } catch (const c10::Error &error) { + std::cerr << "Failed to load the module:" << error.what() << std::endl; + return -1; + } + + std::cout << "Loading the audio" << std::endl; + auto waveform = loader.forward({c10::IValue(argv[2])}); + std::cout << "Running inference" << std::endl; + auto emission = encoder.forward({waveform}); + std::cout << "Generating the transcription" << std::endl; + auto result = decoder.forward({emission}); + std::cout << result.toString()->string() << std::endl; + std::cout << "Done." << std::endl; +} diff --git a/examples/libtorchaudio/speech_recognition/transcribe_list.cpp b/examples/libtorchaudio/speech_recognition/transcribe_list.cpp new file mode 100644 index 0000000000..458a98f568 --- /dev/null +++ b/examples/libtorchaudio/speech_recognition/transcribe_list.cpp @@ -0,0 +1,66 @@ +#include +#include + + +int main(int argc, char* argv[]) { + if (argc != 4) { + std::cerr << "Usage: " << argv[0] << " \n" << std::endl; + std::cerr << " is `\t\t`" << std::endl; + return -1; + } + + torch::jit::script::Module loader, encoder, decoder; + std::cout << "Loading module from: " << argv[1] << std::endl; + try { + loader = torch::jit::load(std::string(argv[1]) + "/loader.zip"); + } catch (const c10::Error &error) { + std::cerr << "Failed to load the module:" << error.what() << std::endl; + return -1; + } + try { + encoder = torch::jit::load(std::string(argv[1]) + "/encoder.zip"); + } catch (const c10::Error &error) { + std::cerr << "Failed to load the module:" << error.what() << std::endl; + return -1; + } + try { + decoder = torch::jit::load(std::string(argv[1]) + "/decoder.zip"); + } catch (const c10::Error &error) { + std::cerr << "Failed to load the module:" << error.what() << std::endl; + return -1; + } + + std::ifstream input_file(argv[2]); + std::string output_dir(argv[3]); + std::ofstream output_ref(output_dir + "/ref.trn"); + std::ofstream output_hyp(output_dir + "/hyp.trn"); + std::string line; + std::chrono::milliseconds t_encode(0); + std::chrono::milliseconds t_decode(0); + while(std::getline(input_file, line)) { + std::istringstream iline(line); + std::string id; + std::string path; + std::string reference; + std::getline(iline, id, '\t'); + std::getline(iline, path, '\t'); + std::getline(iline, reference, '\t'); + + auto waveform = loader.forward({c10::IValue(path)}); + std::chrono::steady_clock::time_point t0 = std::chrono::steady_clock::now(); + auto emission = encoder.forward({waveform}); + std::chrono::steady_clock::time_point t1 = std::chrono::steady_clock::now(); + auto result = decoder.forward({emission}); + std::chrono::steady_clock::time_point t2 = std::chrono::steady_clock::now(); + + t_encode += std::chrono::duration_cast(t1 - t0); + t_decode += std::chrono::duration_cast(t2 - t1); + + auto hypothesis = result.toString()->string(); + output_hyp << hypothesis << " (" << id << ")" << std::endl; + output_ref << reference << " (" << id << ")" << std::endl; + std::cout << id << '\t' << hypothesis << std::endl; + } + std::cout << "Time (encode): " << t_encode.count() << " [ms]" << std::endl; + std::cout << "Time (decode): " << t_decode.count() << " [ms]" << std::endl; +} diff --git a/packaging/build_conda.sh b/packaging/build_conda.sh index 161c48ad43..c4a4a009b7 100755 --- a/packaging/build_conda.sh +++ b/packaging/build_conda.sh @@ -6,7 +6,7 @@ script_dir="$( cd "$( dirname "${BASH_SOURCE[0]}" )" >/dev/null 2>&1 && pwd )" export BUILD_TYPE="conda" export NO_CUDA_PACKAGE=1 -setup_env 0.9.0 +setup_env 0.10.0 export SOURCE_ROOT_DIR="$PWD" setup_conda_pytorch_constraint setup_visual_studio_constraint diff --git a/packaging/build_wheel.sh b/packaging/build_wheel.sh index 9b4194afda..24f544d167 100755 --- a/packaging/build_wheel.sh +++ b/packaging/build_wheel.sh @@ -6,7 +6,7 @@ script_dir="$( cd "$( dirname "${BASH_SOURCE[0]}" )" >/dev/null 2>&1 && pwd )" export BUILD_TYPE="wheel" export NO_CUDA_PACKAGE=1 -setup_env 0.9.0 +setup_env 0.10.0 setup_wheel_python pip_install numpy future cmake ninja setup_pip_pytorch_version diff --git a/packaging/pkg_helpers.bash b/packaging/pkg_helpers.bash index 173aa4ca07..1626938863 100644 --- a/packaging/pkg_helpers.bash +++ b/packaging/pkg_helpers.bash @@ -107,6 +107,10 @@ setup_cuda() { export FORCE_CUDA=1 export TORCH_CUDA_ARCH_LIST="3.5;5.0+PTX;6.0;7.0" ;; + rocm*) + export FORCE_CUDA=1 + export USE_ROCM=1 + ;; cpu) ;; *) diff --git a/setup.py b/setup.py index 255ac9894d..36f28f0eb1 100644 --- a/setup.py +++ b/setup.py @@ -12,7 +12,7 @@ # Creating the version file -version = '0.9.0a0' +version = '0.10.0a0' sha = 'Unknown' try: diff --git a/test/torchaudio_unittest/assets/kaldi/resample-16000-1000.ark b/test/torchaudio_unittest/assets/kaldi/resample-16000-1000.ark deleted file mode 100644 index aea8da05ccd7ced2474f42567438e1b4f597a838..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2021 zcmXZce~iy{90%~Pk*tngX6F`hA@M=Xu5vUCA5&dF+%Q>_49($ihYmNpE=-&@YL}WV zPQxuOYkK*(LQQQ`a%c8hwe-uw4 zyOA|tM{(i4D4s@NkK4p|DE%bvxN~3nd1%D8t6t>D}qI^iGf~<^-hUejw+Ph2rbTOMJ^=5`BPtrTo{!7YCy_ z;&T9Bj~@&nR~L93mr7oOv-Fj6hFpQGmn+n{#D5Qr$Cbb{^pJNEl*?Np{}p}@IrkKE zj?8e*f%EK*xB_|-y`B7HpjwW=ci@}poFhjo_TYB{S4B_4@1l>xJwks@%mVTqXvWXL zr_-;JYsuQuD9)ybIgf&|xJ}L-p_1=j?@SVOGPOv!Rx4 z7~fy$&Fn|vE$2JX#P=fE25zt)AuqsXK4B+bXHTJreM+GhlFOV!Psd=pe#0AtojHcT zhD(BE_1nWVwYNBjxBrN}C)tdD14hvQU<*Aavo(^doIezkrdF17>|8>hL!a|m91*!$t|8GRXk7lb!{lng!B!v=2__GvaQ$9W#4LmTJR zy-~cJ{<2;-lPO}0@yp?DIY*M)aBJAklfC4bjN8Y5s&g8?73{``nf^wfKtIlBEg9xF z7}rRK8K06f-1}Wzuw_Ar`yMwypHI=dvvnm;!$C1s=3hxpSF?s+Yxc=(&%$0YtMIMq z8GJgj?_jT?*WhP452asb4?8=ZZ91;$t0>+t?*+C^xMgf%=MTe6|IaJzMHzkxtmE^b zd}rCp@tMwt@VCX6lHr?7Gt2F4v)Go9VYlwV!_dvUP9zijMnDxre7=>lQqC4^*X7E= zwPD*yhB+qmSi}})*ISP2_1+*iir+6#KQD@3U1Fbe_;2;CB>Kb?uXw*(?sLWw+*AMdeKtq&5cN{!XeVy{x+s2;PlbBB7x1-NPpg}>*xQ&>{&sucqECE5+zK%r)EOi$ z71yJ}OlF$_-_`R4olt|;C*3&(eeJ57Sa`Wz|8 z8M7R(r)_FviW%r`8PMJ=cfJ?Jx6Cp{pIK@ZLxb4Jj84}1uXMl0YrY3PR_phsxGLu| zv+OE&i9VO}?@wlk%__9BfBGJ7`#cQkveDO$y==-z3qhp qxX)XZ+O>=Bw%II`=j&Z;@&YqA_cpn`WKBiISu`dnXAE zBn=u>n&-LB_k2J4)sN28dG^|CUDv&ip5J+BpSp;d`D%615h5ZYq8_p$A}gi8!x_u) zX~F{Ltg{w(?+qa&u$|a`(q@M$kK>p80CKj6l8xTV%u~Y?zT3MHTRD>)Z5YoY0t1nH zvI)H{;{3Gk9y(F=C6v!qA-f_=uzgZC{ju#M+&q6FWz-((_}!28&-#XwrJr$Dd=H0>Y<*7YE1 z_f;IoS7n(g@5%g~gD4l@huoLCY{?`swCV}5?ZP57)$v$Rks+M@gn0g14oa^2%*K5q zqCO76>}nCQKc&egL|?%72Ys-Zev{;tE3y@N-iSBs;GR#6cs59|Qpu;#53h&mbkX!f z&JFa)^mz1+FUOKIl2m!|2ihz~F?c^8?(wd4e2Y6R*pY{K`x!ocNu<3sid1z(8KffL zAj`LwT0MN0?w0lsXP<^5(PlKes@=*rbZJMg+g-GNP+$%_t`P_MJ_P7oLd$avMt0|u z%riq!SG7iomOk67J`vwNgt&0r2+qAc_O)_8k|0F$D+y@o>oK2myAYH(h{3PvBwL`y zh9j>)p|S_NZrG81IkHUTj4#gQv_f>=YyRZBqu8ab5!m>w7QLYmxNZDHZKk|K=h+gB zJvWQ4tBIx)uVrH4neSL%aF04S*in_e1vv646|RC$^pbm}Ao@%tUIoSC>XuHLGy1ui z{gXzxEenFoIZ1ZPR-5>|>%`pOURdZnnf*Q)NSwm@v2foh?3<#^=1grMQ#TAFPSp}& zJRbY4I|a*L3nAF5jkmr$wyl}qTFNjCPxX=1T{>+07CT5g4BS5Qwp0>Cr*q8PfXD+aj;v zHh3>Fgyh=KM9Np48P>YM`cN+&!mwYGmZ{9-gfk|x5DPLkfrytWh&f>O%7JDvU zO~e$3QJ1h5vH$d$<@HHe5+#J;2z|_a&to#y%TUlTjP(%V&YKSN$+pGsKLaqai6bVr zrm&BR?znra8?G-c$&?Qh*sqO`@NIMp%Ioa-^$J27HYy4WPX2|(LVtm0*biENEg8i{ zzY)96k}5n4q2_^K5O^UQjt7FMuj2+r)`@)N zhVq!-Z5=%0&R1`XGImVjF|VzwA!j;_+i&Yg_+KrS9B>+Yo%7dVaTKJ;`dmbmk@L3tve>O+3yR8;B-@`FdOO&0IO6H%R*oGNp z_aR&?$M!8fNdm_A;=c41^hv5S$3={EmJC8;=}uU$)?;b^#=zf7h^QCyFxbsw$Dhr_ z(~CklG)rU0upWE2ek-O~58-`J4kMEE%g}Z6oTsWW7yH6F@zrJfE?c&A1svEBH!D@ zBCQXqwvJGIr^)IXOUSswA>3ZS0XF{n>~^m_$YUY=eWxO(gvZ+6EXF2fAu6j!!R>-B zQ^0`5N%1k6Hj4WF?0DkN-gbB6T zKtv}w8#IiER?D%^fyWd^Y2w&hA&jr9VVpIO&CgiDy+6aKFKQv>ceR<6^hxA2_aj&= zgcunsv&wg#IHAS$88fF5QM>UhME@~X>o=iwYJ*w(hi;l4^b#{QtB^V;U+~f|i+(Qp z2oJSiD0{!3y6QckHbLKT+V(Rtk|L=~*#at;UJNRq1m}oiDw?oga8s-nqPw5t{o#>} z^gQ7wu4_g8?FUF5mSGS6+e^k?>w(G_Hzew+v0Hj6y$kkFO~|7XDfZw-0C+=9a5$^aw_VpyZ>hz=W=b^* zPrVmdc7CIikEOtILm_JZZlf2K1E`PnSNJ7lA-?w+t^Q8v{3k`oyZ#=7&cEm$F;79I zbPeo#BXKECgr$!6;9GjPpkekyXa`SZakZPsthR29^1O!N`KruxP6F}J8btEO15nta z%V^R_l#dZ&ddU)0SMXTeQ3Du<2~nh^h@0{HZ28Rf7|}EY?TfJI(~(!;La|_U@evxtP|A*rdx4)ze^0KYk;H%ZBje>^3;m>ao^zDM*|X z;za%|J)hX@`CyI;WK)N^~l9YK^5^o_~Uec@8=+ zds8EJipmH4MB}S8Ecs2T2W=Bv{#pT<@K?B3)I&7@yVSG**Kve5Xa?*GT+qcpK>utJGy~u(DnN48DHIMM~Q!_Fr zZ08rY4AIRuqhO%)7xcnY!GfdtG*#pSE}i`icTFq0yEm8?NoS)>A{)))pHTmIYw0DY z-^lGvhM7e^6_I=@7^U$Smt3O|J~%{uuGsJ+zBXfS(IecooWLwjS`dew-Dp|tfmKVU zu(yh_x;XAT| z`kl}gL@cd?)5>sc^cQ89A5ebShBg?jy$`V{uFohrLxz|1!uPBzHm*@;f1Z9K&pQTj zVcZUkJg>*{^v1z*g`#Ker+2>mkz$(!#A_@_}Hz$VnY13E@AaAM zGDXx!3UP9a0Rn&XSWNp8?2{B?f6PcYuF_>MPaeQ7ok8%&B@i#J_SE0K2G5Re==*OX z7JQjmpq ztFM?lFMw{#*hVY16e7Sb1u{C{Y4VOFK`^fx4dY@^ytkhQzvl5JMm8htasY1qkzyGm z7ZR_`F8t`a4qG!7#%4Vy@-_nyIdv3@hC1xWoF1b3Y8a2@%u#TYtMMjUuu2d@WUVR+ zEO_i~-%5bH1D2m|B95E1nVh9Pl0Ww&EG&pPmQ7}lti0gY(h2j2`ee51<*;4y1`cpR+j-M;hTTvu1F!)TDZcN41)B;fJL$q+ueOe^>9Y4A=5xXmj8jhb! zMW>V?)bAaXCzew2-i?CLt+l8th`{JkqnMj}B>${WD+Y&rQMX5yInS{rZm)ZAezqGL zPOCAMfK+nCZxF{4c4L-Mmrc4p8eU6fp zkcs$7zWmc*!=ldE%-!v-ULM3iL6HRy-@(qe?XWo0%YXT6H0x3e#TSWss879?u3T0} zC1<@s`<61?*v$117D+UzgW^1=&BF#>M#mJ2yw|d(lyYmhVt|>Bwp&KOTcpn~qa>BbMn(T&oA=wo< zgnQAOaBK%x2k*#2+*gRK?rAvI#$!oa7h>FO?!3(t$Ke89HoI;Qf*c3&M)-jktEsWX zZ*DMm>Vd`Py~M9WhSm8!fY;hqWa>ZRTkaakba>QS{Y%|9Tpc~DH>Dks4#u^4Lx z7El}iNUC}2Gvs}~p>5s+ddXow&6)NKW_cf>8=XaMpXLb~^{Sxp=q0SHx~WY@lbNhh z6CSBP#&53o%nq4GB6PZ-`qC55^Of02s}NGz(vN+i=s|wl<0zvh~ue72r1>fp_p~hzityuVouA^Te zW}XGzhvD>3rzuSr7C}VfJ^nQoQlk=Af$Tw!sU3+#>$(w4rpue}o7aM-r+(NhE5j55 zwvj#BJtkdfqu?Khd4ff-Vt1heR8ikFMg&Zqd49Pz{HY;{2<~|XkzfvA; zkMx<DO?K1M5!>GPVd=ix#At~UySvI8<+dHjxH5*kJT`_Ma1ViW zeLYea+)CS=+(^CSU!!$bIgZ6i(ADWFbk_p`W)9}VOx%Skx?QJV269o8%aCW4Ks}t4 zsY&=BnCiYo#^xHD8p+ZF&i{jl&NFU~5N8KUYWY)EwBzHbd)T*5fz8!$BdZ&F@mS|F z$Br~u^rT#3v~vhk=WRuRs6MkEmc}C&A$;%8#O@xh&q$t!)OA99FBk*yb$Tph^G=xm z7{o1UMiz;yvxG@k;5e?A`#dK|%q%%pTzen!g2C`Cu;ZKgt6gdc59|TX}R1FksGIRr&f!_Ro0O( zZl-^W)mS;1#}1EB!TMMs5?yuR9mr!#Uh*N#9mds<1LW8}9p*Uu2;2h)Anz4T2*(g! zRC<8uc4N(XK8g7x%_7hEeE{Ts!}0wF z`qMgyK6TE9rr#G_5QI=N){GYB$>1mapt{441iq*K!mj@X_816hx%5%~{fRA@ zzTy%5ICe5wdo>xp(~ad3?r?oDg-yK@N4l#9pqgk4k3JnXeUAt-+lGx0oj8=(F|!Ys(Sm9}yW$?R|iyhHj0AtnO4bzVBm4SwRp^K*3M!&`LtT@HqL zpO73LNB5TN($~JF@C;6X!Kq5Bo+2x-y;q0I#4xCuh_PhPul$HRZRk(&L4<}pOTX?& z!jAMJtHcEskJMTG6nHg=SLm9 zO~eFueX3~x^aMPp;h0*q7F{G0Pmi$-3@PR!dCE{s!@jYmUZCvq}%8pKZ&WX@*#FI{n#?m0h{M( zvB@7R$c_=iuq(B~iy!)I(OxC^as6PM77y#Qxf#XK6pnqvn0R0WDm8SONBBW>4i3Q1 zH=c-;PhqwC?s%Bo4M~}GL`r8OvnqZF3yT&MZoSA4Qxjo}++HB7S8;F{pH#4{T)cX1~*fkkA+y@@Bx~hIrRINIDw2~HC|keMrz~$ zO%p7;A2ant|tdM#{J#-6f8LAy=74#DdHHoU6mI` za!h=iq&8_iBFVx?5We4RgnDL}+1)vvRN;9nq)%2NprTSB7W9e!{F;iCEd_X_a+KbA zdygJ-`i@4IOk8S8&j^_V1;z&LXu>b}iKEXOmXU5wy# zRfsE+6ERkkV*<0R(P2LXm+AS$oO2T~^DZGwwhzk}UL!l-DzE~tyJ)-64v*LtzP;sW zmJ}U|*~uJJ`xl-rd9#+UWHGXRb_WtZdt+3CA|vZ>5?9|o zICx*cl8c%wE1-ys=N!+%qZ?s&MW3~Pm&4#AAuLl2F{_rxhP@UcU0VnrQ8C1X=`v&O zefYyUB){H1;O_*Rs|k3S=S1oP~C4x1M>@H=}> zprl+xlLC|Aw6Pdb35)3$@#j>c`ZGEVzd^p!kDC47O`Y!jg4gDch|tZZvHn?txQkUt zkba44V|r=1wFKYhLK7C=3xsU7Jx1)480Y+r>4r!Rt?ZC~iZ10ONk z{TEtH_t57_epK7!8!YlZW9qW!bjRGqbn4DxR9#QP^L0hkbn_X(pQIWrt$vQaiV^H+ z*h7ASTr18@^uuK@8RlrblPufNg9PiVu=%0N&a}TL9=ivzrE4#&p6jw7bH&ihffM2)!;46BQoGDObp?|#L z!RtVdo*2oikYI_@PjT{bJ$4O@Nxx^;K$VT-;U->=;kT01a{dPzFHK>4D<6JYu2eM3 zoo4ULgXvC&`IU)ue3&AQ7A-^SlQ#%?#ko7@r|HER|4{ibl&jUFSw>JRKi#z*_KtUP zgL8M=oUW03Dt*`}cL}zU8f@3KeA0Ys2>znhkkrv<7IP*d%w33m+l>&#)%b>?`AA+a zM9^ai?9$d_qdj+FR?;BnsM1O5J2h7F>I&v?=QUZ!j&w6wHp$r+3Ex`bbTp1{=`xB% z?Tz4^M=cWXnG2-pxqB;saU6hw$qN#Go9i>qT?fCT3o>;}$N@`f)*>2!>;=sTK02S@a$$fLJ&1<+v1&vO zycYbh&Y>p;KHzUuA+}xILiwSAbZcuiM6|vj(>|0Aud<-QC_?Vwd#u(jpdrzB1tY%w zMd|hz7&S+PNyJ~`XRL35QSw7{OrOXMgVvGDncX-q>kggfDXhFFo*0V{LgC^;9MRWh z+wYIS0nXi(j5b9C=kAWL;o)|K5U!?5h|1Duz9Q?;!`*Kw_7%j)K#N7ralk~0ept8P zBQHlyV%F1dV^LuT))>eTx_2z=JM{#i=QyS|$8njqMGIXX8;9{S6-b>if=VW)(d&`v za7_OJ`(+oXpvj948suU}Vg~jY$5Se&MR#_VLQ^dPV%b&HqiduK z0{)F}ZSd3g!SGdiX3e`q3uk>a!zZlQ5I(Gw#&sVUK{v<{Vsx zr7gn{%ooAf4jm?5V~b6H25`zGj%3`N!k(tNW6jlW)QnzDCIn7kk8B>HN2~=FK}Yz< zMTGRxxF{Uj{}}?~^&7e; zK45=!F7=9y6liBxW2a~|ev}T$|fzRzKtg|Yb zgoX~_pwtoQKGI>6lm>~~k6|ndl#PvF-085~VtsT{w3WIh?zT305QKZQ~ffFbF?4a6IGJ6|=myb~mzqWdRCJv%}7^xdKE72k2R?-O)gUsCelblO;2f=fP$2xet;*Pq#f zN4>S!k{J&5X`+nplFW~p)P{e*IHtyzV?LfIiK$F4>cp?0XskMmvt>l8a1hl7JF(GH zkL?&W7M+`fX!4$iP|ht(OrMDYCn1u4NW)r0pDjJI6?xl-VE!?O?6K8g{_`$lLTxX4 zbFYx}WeRMh#y#v@(hk$G8vcKu#M$jR&k%X?A5O@9PM0yMp-pq&;?=`Hh*eObQc?-@ zY6XLNLoP<7T&JtPU#5pg|A5z30h~Hg==*sRwD?Fl)`h;tzMq`C(>R_M+f$EuXG37- zG=^QYgZ%nsSVnerYlZ%2rWNdQ8@pw%(TCS9A=H}kEMH_I)PoKq%Q$Rwn z5SdO>q5g}<>M|FjNLC2Rf>F@p++FwT{SY@D#M6cENYW)$)-8SwK`K4StlLWVh{>?k zNq+G8(t?1n+x!)aM=(RDNOb&H1JluNg2}H6X|>9G?C37S!*k21`|fZmw=oN=62Ib8 z;3I0Fw}U?J{e_026zq-uN(Zl`3zB|R;mxfWEHdk(wjD}* z+?~11irOqRhIy9U z`TDs6MvlX97ilFPf!ge!;Yp66^&(YKW!k)-*Ht4;gq*)b33p73v|-2EAvWs&srl?Bw6 zb9d7uldw6Vn7Y~Q6J$%)!pQnLPMjXeS~rF8A6vIV?&<>!a_$cGdr7N%4?cWwL!O=* zv)q+J5}XEc_1zw*mg=%ChsAMkt`Lp}3lYJ&g;RRdQOxCzv1Y!=K0-B>lW1Gd^_(Z#j48bWwy1ZIWQw!B0`Qp34XwUY%|~@Q?b1 z#B+0H86}zV%Mm8P9B=8C@!5yqJ9~&)M#HBV%6RtZu~!L zI?g3MOTHeTr9%-~JDL^V>*H@rZO7DqcktLik$wN=LC%@?A>sE$TJQ#%Ll2lT;UyW5R zcf*{QJurwqNJ_WJvWb!pAa=7Ag%QvB)g2?5Z({`fR@S0*!4^SWK?z;+>>c-5-&(qPG+ZugGgphKW3@gqtaTN<;Lr?j}k)I!yiXQB1HNz^o$9-5IN}5a}CGN$W!OY7=6U zEyb#R0#MM-F|`3*{vL~d8apKhD<*S&M#p=BU&S}7=8%H?RfR}jw4ItY`_mkouecYJ zg)-qY+J2SL+Gj-==kgv=4}MX>{TqVGDmD067YVZr5f)qH!FTs*ftA5SxJ7b(#@fx~ zY+pADov+~>UzOFYP9Rd8ySuUc047`NvWFQQXIJI8ZtfChPwX{`+80GYX5m$tmuQ)ojc@1s1n-%F!wcv-;~2hQH<)Fq*7mP0lshhfy_*2I;7!A6Yl0>*hhE zt@uQ?5_P6}(-o6AcbC2X4B7TvjwM*#hniIzdXEVBmOi4)b#pk!Tqi?NTQF>pC&7`6hmS=6J^FhoozFKN6pxLHsK%j^ox4BhKB8 zv|EFf58@a^; z_qTLo$M@xA{h|qMu=x?rr*rPkU>m>f+Ynv)APRo6e=(mID)=OoPjg3qK=p~=xH!{_ z&Z`Zku1eWx==%b>AHh`j(OSCW>Tg_WONRJ9&fQ%J5p2=ryq`l9^2ZF*q@4fw`QMtc z`}-rDS}}p;CtHx!d%E#?fd_u9n!+}$izN>-2Cy;z5WaoaVTPB6iDtzxoc5ZbD2d1H zs&z3pMu?*iC&Np~`QxW+ut;whi}h>Bicl@)S91nA*8SLV&5!JhpTtH;-hz)g=iX(N zN$;U?ta*PhU}@q-qcq#=ZpdMTU?4MN{KL1sh|#zwFDw7>%dzQ4yg~K?1ls5ujky|8gd_pKgh9J z3(pdxExnMkb;a|Q>TL6mPsFry5LdeX!xGNjh0GfVk^h9K*)kVB+&fs%GYfM#cjw?I zg*9b*Ov!&6v`x93+L3SMw5A4=`FV+bjn>~+R%q$ zqw^d~(qt~D%ZO|95RQnf$FwwkHbfLL|EUmx<_1_;%wsKMmO@5Mh*3c!(Rxmo9lCY^ zQfh--KJYDhIa`%UJ-UWjP2I@YxQU$M+}(6M#EOrwD7TL9eAgqhT3Yn6UaQb|8R`ys(Y#+g*sV9Vy71@tw*TBnbqZyE7Au zLAgsmRnIoyPZ`+^pK}2Ss+VF9=Pe{ZzINeE^L5N$t-?~*J|||o2hhIrD12w=u#+o# z$lcgsXo;93(woO#TWNuEJY&pURiw}7v7Pd(V9nhD(q>IWd!05Lv&$ZKS^fCt7DNVr zPG)u6yr9_7iOhZax<)22x-pw!zIn+gq^$a5cw9teNUs9+`||A zUjJ6CY4L^q5m^>-&6fO1=z)Tv8;)O8W2&E0$ZsR(H_%>RhIj`#I!if;E*zp5{g%rgZ@Wg9FLa}e z7v{stjv}<>J=H9grj;pWxEC6ai`Ab9bvY-@%$I zifpuwCmB4^hw*Vvn7c@m*&Z(>SGYXWX`fA4%(=Ub&t%cS<*H*ErXh~&<5Q0>eZb=kj%#Q|}&>aqdp9c_$SN1VGW zKl2=82Wwy(eNYf~u9z;+=a^btF}7_pp^Gj?(s2%-QR?*#8?7JEl%@N*T;4BqvX6-T znMJLIxdKI_Dp=iqiTv7bniPH>_S1x9P)OX6q~NiF}2tx#1_l*A4~Sp(cv-3O0R-l zjX<#YzpwOVX9^N)eql}V4*J&o5xt!A6&7Y$2!0<o61zrzg>aL>2OO;i;eMh{^2hkw69~&?0 zGR1MC2v-ntdH%)NU&v!&NmH?sn^E?BmPbaQK0ADV19szcemFkO*OEQ>L$NN+_rL@?vzU^I;|JU!|g1Foc#$j49av?^dG2AdJDgcHPlL9ke==G56-I3P*)?) z>Q2}3RXKOpK7z{#ZC7AZm%0(Pwq8)>%h+>TgB{`L63bmf$kW)0og?+xEZGTI?abxW zTxUXub9b}8&%>>?T(6rk2FX@>Eavb|gyj!Hxr&k{U0hC0>k9fu_rf6d1ToZ?V~$<- z@n9_HP2MN*myQ=@>DA$Aso~~|3-biWPM1-?xJ3N-r39y2r&F7`FX=(;OkB?W4#CE| z^n~$onl4rVhnZ>E>6$?Y&;1iT;Z@?2>?>$b>!2rMZvaRv$EESt0AVrV}?p9SjEl!mbN-Dd&*-I ziuuU@%H?Q+28foI4x49r1ZM*VaP3?)i78iMds;lOm~(edJU-dwl9VU8c`uOV%P$mdkHM zRgu|;wOH1~a~Pi9k6}$;a?E-X8y9v9Es~uOxurmER*hxdZNWI4#`U_V`jCVGf7F@R$InE+br9Vy zHfSu?W7%^gp=7~%l1gJdGc{l{hGs*a^T*RBjfZ9j*Jt=`N3PfqcDQ^Ynv*q{n7Ip< z9PfpV(M2NqTAr=c^})v{Z7@#B>u-QxpripxssyO@G;Ie=E55%~IBhmldX&`}x0^3Hft`gjUEw%#3;CEaicSw{+s zCosMKhj_cc1zzfx`Mo!VG&bf1KK%X*5zD&*^}|1@sYx=vuPK6ou?4+y?dP2USD-aWtG34^XQsrhKo1%@7?OfHZB+-KClm zb&YNucf1a%gDNa*S`@K(%FTjycBs?SVa5yli9Xk-cZ&o18+j}~QyXSqx%0JV3eN1} z?ys?ym^gD7p{whO{d#TYv-TA3UFt{CqW}_+Fqs|7@xtMIooM{6NhSnKvK@1RAb*Z? zcPaj6UE!Uy**g{rYbtTs<*%SrIg{>4B1SccJBo9{a#KgcAlrEOnZXxH$$)X|oZo9uQ(t^aM2R)MrVft?_v6 z5aQhPNM4-=+dbwIEZcjr!|f`mZ&6^u=kMawwsuSyY~*LUjAlwVLs9weAIkHC(uYRY z(v4+rFk?a)4%jQw?J|k<_+5tS_IXH&aHnfVxYFVDd=$%4+!y~qt;UX{|1Btoj7dCd z4H~FvPeGd6w|Xp;eToC`Bv^#xX!3ev2NqU%<7~7dbCtYBP9*hV`o{}6wOEsp)y3p^ zqp=&OWZ`0w0DtmO9CY(HfSQV&(Zxh@7pPkU+O8ZrK` zO%v>G1Mz2p6stTulYB7k!rzV?P|sIpn)5=5{Xjn&9go9TR)?KZYA3gj4&$ks1**B7 zj4;mGjl3_!=k4m~i{P>LqZTmZet*TWjYNs+u(sUeILtA%MYo=kMajynQ^6D4W^_T$ z%!rgvmSQYf|TF*h?9#n%}@1JAw^pWhov>%`Jw;<@>15ExY z!=B#UL5xj$u+HczoVYBOqyKxd*=!IYTKgb*R+qhT69eJCm(071V99+?gG;AjU7`@@ zIrl2IP@k=C+=ySLTvjr!h!}HB%|^iqL$CTE$GO`*cNCeM#2v&g?|}9PF)}GYf~}kX z6yp=QJiMAP&7z{79@`y{Y}Il!i%HV0zR48E6q}yq!_d~12I#oc`kP!H-k#y4Ln2*s zSb_Q(mSM#EH+a6LmX>dLn7**_AA~PMk<1&-j+=DwkA}A+|L$F!y{f=c)!m7aNgpCi zE+OfZ2GcYAL98BdnYww_kZsjtkyj_8lDn@?T{6Ohcpm$+d;x0q3sLcfJ9kC8tiF5~ zc5#f`U?828>``MHaaW)o&z;w!|9-;FF?cZ_~Bg&E&{L+UiSIv9Bn!F4)pX7dO{X$bLXrYW?p z^H@Z)bP^~qz|wZJDZy59iPocqhDeZoNv?ApXX?n>Q5XTPQy7- zO0$dl1?_vdtW@tS46bUUm+MBDjZA2O(~DrN;*VqNzbO#I{thm$e+w_(b9s1EUvf~T zAAj7>Vqt<7GcB$nPx`nF-byaBrO#s_T!yRAQ;5g@dI+Crz#d&*22mv;Hg6Jvc!Uo7 zZ`L8~=^KEfPaHY8dFt? zWjqr6?#`!6$$)E*8_I%R9N247$RT;P*`vTm0P$h za@rvI+d2&2&wO;-@|e;HT@-&4Vwt20ObYbbe8Fl|{x^&{f9uHJ5G`gn>J0b~`oWv! zPloa*v8bmvVe^o4cP8rOPv|(-KQb6H_ME%B>0!3+LI?e%@(L?jD`2^{NwDlj292DS zhOIe2ackftUAgxz9g+7P*43XNq904M#b?mV`B0kyoz^Vg%8JVe~!VmdE6e* z(s}5eYrrx*XQI-E^T}tVG0#k&eO$N|vrL9CI5meH4b)&v{W26j^`hSJ3JJTYz?{e2 zgRycuE{j+5KZ%WID(cU$Va-3ZUd>Ox99l!ysl7#~{U0P+PoZlrC(z{23^ptmy~l3Q z?x`+RqK&Kf{|PYP?IT?}c?=b~Uk>%RuQ7Ozb9et~r%5O_pqk5;?ld36L@tga4R<>r zu=IxV1SO`h$D7cqJ{Y?@;*FCgOZresn)|sd$-WI(en6j{+@XM`6z(pLn~H#kJZ^?x zf*-TF+R--(UyOB`=q#5k#O8iQ<1%jk|7=5tH45>( zH3f^-e5LUpJ_phSCtkdA?m=LO3YFt*F$C4vfKz!>k6r@|o zqHJwuKk_6@zVsu-_zCelsLX7mJs}wCMEbL-r1{Z!<}>9n!o->o>|bUkE89cG@4dw1 z_DZx)D-bNG&Y};qKB8-&047rp(nSXz(2X3Y$)Eojb!T7D$aN<4SVS?LD&OIhO$im< za!_!lt%jR{pL2WUBbh^eFh71lE0i}sz={>JOrXD)ygJeYp^qEVkEk(au@n-@WrQ>i z?t#K2J$7oLILu^)kp5)?Bd*t-F=9Hmi!X%SSXo@*9BfY%w|D2laovT#h{--p_C3i7 z>Kpo?#PO`L3l&-G<2%?qwgW~>M-cV#5=@&u#jImoMric1^vAdV(ekQzOwB4oK#Mfp zE%BZvMpN`H%Ez=BZZv8CRhrY2hdPe4)d}CxS!ZPEL60)LpZ^Avo^pG4FOQ|mFRI5x z%}^{$7|rS~5AwaM+qoS79aMBEaQpe!$(2KW*eT_Vrg#lz@t}a1ae1ccJ)4oq)%Y=~ zGDzWaG;>zWKu$EblX24o2RLuy%k2Ot#pyCBInG}u4&wKVRFcbi&2)P=#AI@gk&{n9(z2I*R9mxu1p5yZVT9hkq6d0p~e)`5`gr=1sD{~GF-Ts0WHfLhq zk8kjw;Y*ud9HPx}1(>Luim1-d^sq&-z&WWBE9+iDYHm06zW>S0KEDxF7azlP*?1;u zuTSg?I&o6g3z{>O*{ml)ZOPGqZ4DF(NYYiU!a5iOE?p0<%THDwZ& znl@1xm1!}lND5KeicE%NNfHs|-gDAoDbYkEYbwdEEZ2M9zu^9I?)g6Fc|Ol`*bSe} z2cTh`NLG94vLxR1=!)t=xQ-RcRaRra9FNB9vaisCfhZ`gpSCKeVpL}Xl#nl3yS$X9 zb3a-}_!cfZH&cr>(X@mVBj1mAPNM&%H8!A&&R0SIw_LbQc}o)p&PyaR&FFcY1n<$Z zY@WTJDDp4PB6o))J7X*>D*26^7~hAV!_Gpgz&o}w*+heTYQ_6^qD{ky?H9`7f!Qzw zoz|Eb%KgE2QxPKO-z#%X^d2=~$HLd5Qi1bNt7?gLk^$?^JBkMB4{VaTM4HxXv7(kB zRAzHeZIvo%yROWvr^Uf!DfcrrzgSeU@hdHJ&Okuf2RwC>r$Zr+XtF@~`^Ww30vI5&6tQUpP>_ld2 zC}QqSV5NSiNEzoTu08R={7yXk}Vb} zJ~|Bh%PJ^JF=h@Uw&3oIK`6yNAx^$}Oz+QAxTyXe3PXp;&T0*2y5cfyg&kRLbuKJq`v+YSaqrZ zwLy%^Kj@Ua&91{1_jD-5cGB!iustr@$~&yF*!^-8oA_X?P|jXw;2>4i9S3DMZA&i3$5+`}7f-0O7^&7C(y8*-8{at81B z-;0y{eXfk&o}CBNbCvM$T}5N;W9cQEBG_qjR;@Ue)~>OqDk+sHQsFxkGCaGJjg`c% zY(i9MGPL7|=%n~~D&MP+Oht(_2Bh{d!ULt3Sr630P{+9isSg00}C4kbg`Ov8PyvNcBfC=L@koXv!JD+beC=OgpH;hjg9|*TM5dhh(Y>r8~bA zAS9szGTw*il6yh)`^lFu;km2k^ESFX%v#_GPT;*I*lh|0Jox@3?Do3jbWyW5?VINo>U+Y~q~ojdN=I)JMT+F+X!7 zE#Sblu1&c)TpflHzEBmO8oVR#>4;>#A!vw;$we1^cJYA^1QFliTH-?vs83|KB16$p z)q!Q3--(9Z6_~-Tcnl7<;DcL_c$a+>RfxThmWl7-W35j^-(^xeo`XBBe+6m~NN0{b zNnfrn=h=W5eTD_}ZI3+FOaB1#&bzps#j`tl?vbkD7pUdmz*0LEwo6Wx(DPkz^bW$w zek~SR971-z;Qo2#5oD4nOv$O1)bfo9sc0 z=!WcX{Ei>!Bi^s22$;467uIs7_2v|)R}5qGj!D=)@c&-WuNd@|;z{gR@?O=DJ;^wT z#74ez@;!#kkk?_IBoLNQdG~XoF_DfR!^~5zgJiX0bzQD)Lq!i=t#JqPG4*iKdN1+b z`-}#N9wR;U4fJaE&^fm+)5QZNIKrNyP$h*1AF`k~M^&SB#{=}{)zDPs-y}}>h$#t) z=vXJm!VQu{_Q%?Bid{i>`gr!d@(=PoybtSSPopu1zuDa%lajv&(K&l7h{%{tKdgu_ z!7%iqt>DVFuETsY1iJIwq{d9y*gu*uK8;aLM9#hx$x7a-GpB zo{ve~vwpBr0VV!MEWv&|)?Vg*#`JumRxycv8+it;5nSu0ZzsCZ*gxjxiSZHp7Bkmb5^vl;}-3_@eC(8&y~}Eh1w~)(!SsS z!{xe1xa0hsYGjs5rmk&3Z(^}8U41F+*8{y^E$E!=iyb&$U&tZSe-nNqyQZz zQH&!WEBkRc%meM!hHP`qH`2CI3N7p9NDVP%{eF|Nnd=NcUwv3`ujc8xrSSPnig9UO zWQB#0{h72MXE;x9QxZ@9n#6tLK;FCC-UEO4IpkxIDmyaf8e%VStsSKdNi*&j^r6_yKOtvi*;gigbIU*3t|HUUO%CQS5d9l-njeofV6tD6Bk{mmP@ z-|#bdEr{H0)np@lg7N7%KNmI1L`6%PjmwF{ufyC^J8`r?WmGH8Y07}*5#GBqSE8rY z^Jz4dKyOSrRz z<~d}2;%qF-FlG7EEMdw2Uv;0A(V%S1mghL5kuyT33mLg{e=>Wz#ux2|-{G+006AMf zo(Tn4ATaH~^sZddl2kdS%CkGs!;kQ>T_8zqtfdR0vSAZnjXh4YXym_XbhGMH=%$n+ ztl<(JeZzy=xASh7VgVkj6;i_|pCu(~^~h+u1MA{08vNz7tjJDjwV7}zk_>O}$1ELB^v*V95os;Nk8?6!@9eOIX9*siIw%eqhVBF*40(?s zCsTx+6e%KG`pN!6A*<5gi~o)epr|mJMC%CH;c|bt%Jy;&bTQHIQDc@nqM*I84L0M5 z$V737)+?kyH=+?5GHH@LtungDEf0fDZ!v4ydiwZE3_a{o#69R2SbqE;dLY4$+Lcwp zXX!(Z;__)h5Jnp4qWpO0^Dnit??#L2*+gG%l#K)g|^sKbvn%WcuM}X8~L8 Ym_bhV3?MOJHwu>;Gb#7flIyK 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�?8tmYg0pci!EG*mj2gKNubomR|ESGX} zy0;O}GZJwv#*(^P$}zJkN8r!vYt-^HSX3v)s^~82vh)Q4xxQQ8DupynuJ;7X$tC?? zm{ZE@t5SrWxw#hGyJ-?Smh?dE8;HEiNmNywPMy{6;LP-1gw2=Qaz-I+hUJD=7}ak+9q-wnnU8eFZO#WAzqmp*tsgUCtLThRFHu?1 zjFsK3VFfJCZXun%CM zdd?`$4Pc|Z2)#bzHQdEbaFwnm@+$=_vDu9b*jkBgFL;ikUr1``J583b+ZJ;U^`cD8 zANyTC(utJkD17dtXJ`*J$4tQ4*IKN>{*Rs8<1a`&R*tp*Eg(uCjoBv7DE!v8!fsa_ z6xJM|{i%eeZ$AqZNU%!k5H6U?vx2m7G$JAi7q2v8ih2pr;EY21$Q6>*@&}eTGI>_c zKD|FJ!;5cOx z`8~>**$Cwk?a&7Eif7Ppa-#=JJ8Axs^KeR(pk8YaN?r_R3H4f3UHL86uWZ05Q7$<( zQpl>M{K&u)f04a80|y(Ai5;rc*oMOkad~4OEIFfy4f{?F3?t}(mJlrGelthi7&4K% ztmDWvkyGF|T$L-u)jwKfla&$MKV~SF+qXkzO*C#8U!+6gn(5q$o;Y@00)Nx(poWTU zTk&A3xFZEe2G!%UYZ}qy40vz&Ln2ej-}s1hIE4m_^{Z4_w##xP@EnCzq&F(v%Vx>t`KY-N^t z&f%BgwL${tDH}2WloInPY7h@d6eA?Q7Kegglkr@??pqU0iq_ZQVjV-w#|&|3oC>>q zYz>a9O0f0IRV0l6LvwTdX{t>G)~a{%jMhj<85=OArW?(M0h<_%Y|eW--bP1nGisW6K}AH>NrX>eawgIje^Njg8nVZ}sZ zlTwTApkz$5;BL}G?J@SkMb2MShhof1`k(cb{n?yd4L3+qdd{r+)O7Hd(xEs(fGQs z9obEa=tqoLLcBKd&?rUwm2Y_3bX8>JtIPObf^~cs6iPx+vnhgZaQsdU{cfUz^RIqb zh$-EiQOr6b4&phA&pZFZDZrOpQWLUgPjZRWx(0mcN=AjhHZ|ZmilYnmpd(p=Cd>1P zknN(CR&MlM*E8H%(S{H8a>&%b^Ur@xcTM?7jm-U#wyziYR<^^6PyQ(gm+kr3(6D*8nCkIDrM64_rt&g?-;-*q!Y4G^8gUk8E1-rlFH(KTKEx z*-G>{qj-7tGnQN}w;eTjG@qMK#q8)FBqRkO=s^l~`Yoo-O?Q#~s|S}%r(?V?XB1b@ z+I0QQL3(Tj%EmYn0X1Q#cD0eB>Slz!e2EoH?CH74eoVX16{+zdo7U_3Ru7t7m`u(8=9O^s1I77`Vu3V$(EUjH|~YjpgX8k`ar{xMD?P0 z&zaMMU1KKUpC!-qU5c?g+?I$L>FBnA}aHm%GD}=O`5P_QB)lAhvXlA&uaS;w)zrCKK|BP$FPb%0A>*R~5>% zKSE{nI`O<4BUtW<`6wONhhckt(7ogv9i1LU7pR56qqz$f!vt`!&}A)4&WN5j=i^2| zDKzI8k?LzktjTH!tmN7eGC2mjD?F%oOe>u??E(@4C0HQbiR%tSn75${eG~EyB}eK} zxiNzr;W>&$Z|{??2mZgPIpEse<9M^>t zgY|Lz3fIsdqC`bi1z7aC7k^XoNDww< zGg|0SX5rZ@&g)1;KixVo=VX$}Gq^&YqbTK!!aObwvg*m=!+VCY94C7WZ|y@o^8$Z- z)a_OPZQA%4n>KY~gw$w0SJP)@js+sq>_U9&`T>POEu#Dj27Df^fx()@=W!h}ci#cHz|Js@Qy-qA80SN`NJZi4yQ-jwZ1EyysL$V`_uytf1a^%xR`S$v( zO{9&3&p4~z5{}g9`_$F7oW^~=hNN$txnL#EPE}>^em)g{KK~xmH~hm%`7q)(Pspq) zQpt+YI<#q~Vu9HJN=p=3*p996;W>(8g^RGuXrzl%FVpy&PjUD`I}-jX;UJ%{YHm;` z`<+YRZczZ?r2vtpvK||>&=8YdyWpAp2rE;=Xk7FUS`l&sLI3r^0*fKspvKZeJjC89 zAF#3VFW9cTB;G*CGDEY8V@o|m^et4}G-xts6rt;OqmAb%OwBxC-P=wTOwZ8}{b%rg z(uSU@LHN!YMerqa^3A3UYSZ%((y>LP6syD5uQi1QXB7Pv9%9aeXqx^#j~;Qj1vkw; zbWWKI-G%DR?3tC=uKpwRwpT&%!!^=XAYiHfg(R5gDB`xifxo30O|6n=mh%t5Dwk() zMdvWKe;*+PTN;$h7h#i+_&vT7se1BvTMW#li6ADfF! z%eL8l2^q~Sk4!<{xgNL#--C?cEj3$~MsLd8g^Y49-!Yhhh6rNWTFlWnBD!wJl7O4FP*GdVbKD%Ja0a>Q5u$1aWCP3;e&$Cr? zM$u=&7TrBeJeU23)o9Kre7~mrs2#~vkIp~`&uv^Uzk~0W(x~fazUz^E59*vzWRB6m{d4;W$*y(q_BVl||;u^WaqV6R`^jDS2ef_L=lY_={GU-h7S^&c|qJ zaxWdZ^&G0xB`{Jrfb%kg*sZ&!Jm>TVX(o+u8(v5vesB$K<4u~5RY9BQDCkZbafz)u zTj4$zikwkwTX73-y7MUYj;3y+hj8cjG*HD9;jeU`W!`-;+rNGi6Iio0ki?qsm#7xO1H#zgGExAkL z+WundW1gcp>?vLVHFodhVl?r0m~;LHTB?80J3GSYxPnKZhr5uWUASAHNKl>O^J4aYpg(zo+=9b%h$=ZKUaAE+X@U1Q`}v(a^2PRF3th?d9Y0tR%Ff$}HV^9rl4yb#5i_6$pVn79vP-jkBVZs}==Df|b$UlGK6t&q)^B$I&_b*L;$MeJgU z_-OP{W^`gR#0R-2?Y@YUZ|bQ*fET^^>IpVCwqt*r3f|r`WLd3BWKu;jv_2Ogq%K0V z$xV+H&(VkDv@R?P3PqsOBbrfOOxGt~#|8gB+?=r#X2HYR-u*t}1%p1|`mSp9%)C#= zOcb&=G=pfJug9p%?@;+oh5F1M!eShEBAMqXbTuy^ufCO5@*G9joETK~v|;vyA;=0f zVw$In35hC2ba6f!icg8k4Ru-Vasl7*=)$DthbUEfLa+D#MptCtz=5^GWE(21J=9Lv4T&jbVe>(bfBq_+ElYOLurG_R!t# zE>!nxECjM`*xfLI=Pr2`IeG@ka{P(9iaZo_3PfJ9+RSFnSZGCb!vGJUFY|(SHhiLI zmit1E=TR5T0K&aBn2q%Saod(G#5nwckFqDpxGP}OyvoUVsV3Y>OT_BWmQ;O$95b># zf^c3}HZ3}XaSc-J$h}>Zt$2a|I$LnPO$rOR-iuhZg6z`yg_VUoNAdo#-EDm>_G!l? z1TF8uwX1>XACyGLMW<8Kk#}HW#dBjbXTss+NLKdEHr3DT6ON02L*Lw)m>COL^65IV z%eWaTYhK~J{(M?|wm%zZ=!_7qp}(fPqWyh8Hvir#+WYw>!poX5uBMelWbvHZ&^^TR zV+AgJ=8U3h(o74UqZoB~I!;yep#1Y)*cnl3v@V6l{s_Pao}=&-PDO^nXjV2@+HTRk z&j=S(pmfm|BI3Iq_nf;(58w6ZDUZkM%NyuI2GgU=6O;oAu{o5dN$ z+a@G5{3X8Y1Z=w884|j=5`t&hC>#GMHSdik+kem&$=o+=8sd-3S3Xjc=dU<(yU()_ zJ(#CE0U59Ou7~GeyM%}@IDV=eA>Q+e(obXdc~U<_a7H1!Jq|-o9H94-B-CLKXB0da zKCq6HXR}Vuw<77V9z_a<#n( zop&29vAOhO(=)nuelVtUMv*#v40cS{VcuWoirgc<;=ubdXemr0aazV~+C;wVvAGSy z%bww+ryC8=>!i6W&*Q>t3D&6Y!Mm4(S>}5!`eE2xEMM9Hx$(JV({LfXrR+zH{`-rT zZ5f=$9~alvt1-Q^3vrwKNE_FiaCrHhy7Z5r>D?g+kM4rsP-D&mbeUQDHBtKgZ&)ZP zLDv&4vSKp#sn$awS=|nYmC;DEyhx=UH&Zgz6YkvK%II!KsIek*c`=wK?MlJ%0rjZa zokrHr6|#|`56R}1YV0&i=Q{-t#V?Cgnf96Gkbc8CNtic^+{&njbTEAv9EOr=o==d` zMQoEEQ<#t_n#>u6`?6vj708j2v3$;FIUF6cJK&WZ1)b#Ubk~+zewQypXSoDJ$8JRI z1tsQ}-XNyQVwl9%LiWaMV#*otT*qjVyQv1lY8cFPKZ>tDQ(^C2*I1mx3IoVNZ$ zH@)+xog@NF_#Q`Fk0yp#a2`=zDY82B1EFhwASt~hO2Pcj!4gF1hQmG&#qt{OeI zY>6%^nmXZoDhzV=!L)E<8STvUMowZMq^B*%q<^ZcZ0Q5>G0rG9az3Qq8ca;I`K(d% zJ=vyOj|EFp5b#QYN|Y7ZvmM)E!Lu;8R6KF6wwbQZ@T6xCM`I=5^+>K##3nlt_~fdn-d~q(T4IdSgf6sw=Q*`Q5maU4cbXS)6EXa5RZL!p@_{3mh5KRg zW#0ZCV%wxkI6!E(}bkce3SM8!_M)RzY zOe}o(uE*diITQ*xr<*dFy#CI!Mc!YrTOFc9lXY0q)-gDApc}Df!5BF&mX_|$rG7ha zqoAr6!pXC7p;eu^jn);HhG$}WB3R$|}e+<++ET z&bi~Vd1ukyEuoJC_tTN*;;?6aD^CBB!GmAM>|O8zvhH>{THL?D>2aamklR|!W$grb zsP|yn@%yOJeofQOK2pI1e|*{7i<#qXLBH}n-hKB{v$C?`y`&OLcDa$C3j}P{scNE; z)dUTL*JvZ4)jI|-dBYQE;ri9+)hUcAm0=UFt*4u1Ut%E7Q9Lj1By(<=u-IK&iIYtQ zR5_!_(JHphRv67z9i58#eAnam%K+R7Org_1iK$2PT^ua!L7?7rZ1U%fLhNI+x-thN z;wqro-;ucSy*&HVZDbqIQGC1n5)~I$(;3zM*o`z-v}Qd5kB`5R$J~%wZAcv72C{&hF&kG75O8=>jSMxO`;*!1EFrh z_xXNKM7}f6sYN`tJHvaEacwy=v5W+5HDMQfq)=4Zf^QlxVE(|7Rwzodh9zg<#FZ#(^=SbMNz!uod)~Pd#ZgCDm7PzCMHGELIRq_=-B>YSfV0gy%;Ld0(Q7qcUlU4k#L$?W zn`6YboE?HL({`NY^Ow|L=jk)cR(fXB1)O@zy@bO~>=F)Pi+hx);fHrvcB>vv@fqX> z?=vG71(BzBtD!RV1J7Fch+F3kXCKm+LWS4YdC#w-{CzP^m=Qw1l!s!;k}g>DjO(C9 ze3x!?v`B04cl=jdjHQ2-$mcbN%;5Ae*lF;(l6UM2hOLs4|)OjpA9ksz|axf%AgwG<+DJB%W+Kj15b*hqMaU-eq3M++IN) z3vWW%aG9g1%NDc0p#**?!eCH)3p5&U>;?jJIrl3FK&4-m) z-pmbf(cybb>@uoUYN$$-4|OV!MDUId#Kx-O+BicdGgq2eTq{CG+jo?IWunu!^x5m- z+VJ%0#7^6A93C4)ul*~h{o}9UbwVHddRJh?c~y2WAx8Xb|9kAW{0Fc9LdlaGLYBQR zl`Obihp4U;_-z?T)76Kv(|kUfzJc$B{`Exa+9q0Rd4-lbJ;f8ZcB}|gLf1GWcH3hF ziCtHMM+yaqnRiEYVYMEM9AOBBbzKnqKZ4fsa9UtiM1_}bVBY#Z)b}nzVxSre*y<@h zarXoCIHQ;%8$fjUeF#|kiToMffFmVu;c`u#E;ChNUmotpmMjU9W_v)}tDQazJWG$x zd4|K8ZJ3}v7;1sM#y=ZN8n%`pXH`B54(t$>?9pMvLrigJRX4g#9>QR1G|e8BN1Oa^ z!PBe{Po3wYOI@AGKAs{j7?Fvn(^UwV>rIaE8C!lB?-RJ z1i#^leBNkHd*lZ)k@GR!my((lam0;hQ>2+i`DUuHGM;D4T5!gzk2raou*{^j1UG)6 zcqreOPFiaBr+73wYBdF~xA0ne@*WO6eM?8bNuyUP?%-@g4;q@RFlr{RuNq%dUTNka zWYlk{o;pZ=OcgMN#zt~we>2*4CP3%#GHU#ZGl?=6JmlVd(N!0$?~rAN5lgAh#N3eLnItFDd0G)R)l5WOK}PH2`&Ue8`CX;vwENlIzbB$Y~1 zDTPo;gOU)UP)d?Kdz(@uQxuXAGF9f`+uwh1{BWQ9toypwJ@rdse^ULUH)z&SG{z-$qx!i5 z%*)hSo7x{iL3;&~1IyvPv`A1mFqPeuQi8#%9=NDHLaWCeY9#%GzRLE6d;TEmTQ?y0 zoeXoEkS2_OoQYpAo3PO`n#kSe-c4W{v661VKxzhNW{J?s#&OJ@^L<0BhVY{JBK%C- z=&n(I^!=^J@O<9|`#5Qy#b~e+wedtX<0~E~mcg_uQgDN3NHhJXqK?nk{cj@B5D`uz z9KO=j@~ilgG>9JWID$5PoP60 zJfleDu1CfYyk}j2sn1_}{J=RX>-+@gCwC!OXDrM&X|mX3+GO~rD(DWCz`BNvA+>vlPO+bOE*3;`<2k3c zq?C+mXv3?eX~FSNmwq=3~^OD*Cp!s3-WoZwdkRKfIjpqH*qPsyj7@vca1$ zc2|Lm98XJ$z)(zxr<>W0Rg zA?TlUN3Hk>Hu2a-I_h~clrw%~xAkArBBR6Z%yuRwF||Cm=NX03nRKgUMP@y30aA1N zxleElzA2QReEF816W#{(?Z?q?Mlf*T^L1j~zlwbCz9h~W4E?P{B1fC~N%WFvoj<5g zdyapj|D%6IhBK)Tr{Kw-q2{J5{4>Q^$U@NT+9|NT)q#%=KZz@UN3QYoAcvRM;l1w% z7;bx<;VUtjjraT)yST$RM)M}dNx!3^Dle(ri%?9|Ha^&pdK9L@<54@V z9OfMP1s&F=aD`lzZ@`$CJUoe26&}5#z-CjPQE*Pu-TpcbppYuqJ*BSu!!Yh_AKX_= zN9`~bX8+GhfkZ(uB|G@~VeT8a?`;FZ3d!9sI!q%Xn4Ajv3FXtdXz)2Gtc{q+&gQN_jys>P{N}B= z{4@2u@QChLe2Bx@y)ftee$swb7PTZmV8BY@rd)+)k13?HOM{hP9LFsj`I6qNA)aj|UPU-M8{ zFC)ham#)L(`-2#E-XGf1-{`@uVRY%GNH}HnAoisSp3k4klHy+qxIcg~6TTvM`6%+` zIQMqN;B_@@_44=-XSar6JmAXFH8|lA;yuq z>`Fr%G5xn0#*85<<-Kt2FKMPhHlg(oXLsYSV0>~tT|GU7wrfYjt-Bk!3I9NJFQ2cv zKLi=;D`03`fq>mLg66I2Y}V+>xG=JZcSuCz!=n(Iva_CED!+oozXma>#u|g;WSEEa zJK=&x27SY3*vyL~3emdk0Zk#vQNM8exDalde}s0tp}^YR4#A#$wn_LPV8$<+U*b<6 zi9SZERX6-Kl?UW5E(I$A_dO)s>;r%2RvdB`SR(#p@7V4>E=)J75%szQL zwBxvw$-NziGry_IDsL(Xjz_|tE@Wzr!vaz6Dp#ryH{&VSa-o0zCyZ)ukdp;EjDsuWKTqy@ zjC%v+Hf1Wlehk|gu^XM-vlz5Ehq$O7`gQDS>Zh83HkVGMX^zJGYE5RiY91LHtVVHM zF(TJ56XZ5eVQn$f@%m~XJ}wP|@8|?trtpcHue**|I)J4u<``qdT{#|gq>bxW;<$?ncm!45O(&V!jgMqH&W<_JMUq0^yeAH>zzbOg71Jzoy4T@H@q$s2#(Yqa)d|#mlJdt(UM{@EcQCwGh2}ZKmLOf_M)7K(2Q_vcIj$ z_(yg!Ysg)ULPwqrDTJW;ZZ?&8@rp*5+=YQtKa4icK~x{V^EIcK87qClM4j(greQ^< zRcf(g=S88W`4{p$Z~t?5Cr$DfVWBtAU^@SnaMwG8UL|q%J83QzNTx!6YzG!P)Q}P< z9o9JgBC)+*4=1Ph*gRQGxSId2H)jI7zYoBh`;g*L-Z%>I;sQ_jcf7UMoT|FjopN;x};y|7A{H+lw@zHm1AsK8o+B1x}w!pm(?m&LcF4o=}rnNREX>QzxW`J;DCE^E6DWlgesb zzzz?7pDEdaj>xghZAh9{d#A&2HSg?-$|1eS_eJFn%Z6Wq$ujQq{jf*>sPRnKW=MFqCIewZJP)XSO`7iLvYOE`#O6a2 z%DgiXV4W^J{Xm9Yve<~BqCt4x_JyzO4|=QjHg#S02;C+~lgNyFm1tT~hV1yt=tI)!nl8L;@L%C-0-9;);#4IT_?N`OJL3fEvEQpItkUP#vSPrs5EX7 zcy_2T1N~`mkn6*o+Axe=@`Q>Q7Slw|*f;Y#i+Sr(TnBLEFXN2?N96Q?crG>^-_nqsnwCZ<$S&tryyXvDYf?+#iAs59|ixG=r!vC;uR0{s7Sl(`GKCY)AypC;}w;osX_ETmD&zSz{i&`5ZGob_drJ-q6N} znKY;=1YzC%=+0b-G)dk^VdVXGi&X)ZZvKJr^#{p;WNlU<`kNFd{>I3#7x0f+O^>e{ z!Dj9{fwqw%<|e~Wpy0>|W_W%TZOeaw=V8D3jjDrazU7^6^@qrkV?XfJxBwn+)82~5 zO=g{J5n7A};NQ*rDCT9-GqcmERnr}q-RZ}e4fBxguEg4$&zcQ$Da7n&-|;8RhAdUo zX0tj6iF^JZv~j0pTZaR+Iwi^q?|C4Z&sTrtBX~Gt6myVUL}g80VZfE&`Bv5uUn3os z;B=12OVwlKplWa~C9rhR54c7FK_S)Nh6OF2v@%^aYCm(SwgmLa4p*pJAMJi|Jz zOO+nK#v_w<+}8h0I;6R`)aplW{MUfI#CJ%yhp_*s0t?-;3@Kd$*rs=l_d*p@V_`gX zQ+R-dl6`Pa*Tv-#s!Y;vo8ZOV5>$v+^LzncM1B zP~j}H@0I|}@%%!)K15RK^oLlusuyyv)p5~Djn!7&7G&v_VZ-7|6v<5_iBmM0qxb|2 z`gCE_nmDNDT&Aw#9dwX8U{m;=s=deoyB3dQ&*a2ttV#y19%zAU`df0qkNdH@ktA+) z6AUe~;J7GJxW}Gn6t?T(mokV$m;9iy_B)LZ52ex0QLsJNgSvQSB!y39jx(|aH~uS! z8Rx|8#||S0Z}Oe?vOMyh^FE567}y%}%=Tg<9h`L;LHrri9k)Pt`~+sY=$kMto}y?o z=Y9vDlaEt%Sy@FQnby?|6LZcYrq5)SxtSJ~zfLayGX9tyS8MamD7+`V40 zeSmqNqenaJ;M!nt`dq)~~x%298Kd^ZRshFf)6)$Uv(*xia^hje%< z%F@UaW7(}mPOv`1cj%V$XuZ-&&F#?7}|+E?DoI~^Y2`pd_(cxNeHbSMZJ{2Q^X)&jQe^6bS}8=;)~J6L2k;8$A! ziJqa$)NFWXW;E~29Fc}HXi?TD!SeL>LMmbiSH^llJ*b~(>XrDfeOT^Ne;l7SQ91Zs17>|5mOc*jvdt ziVkt%BhITDEv!f7o(sgkNQcdvRYNZQXvfjJudr)^F;zbz&NAf=;bQs_Y}L;oo@W#f z_wJ%A0t6M;nw_#;ZAaaFEYe?gsDT{H^?i zY?@#ef;XEuE4O(u?DTnO=4#^%^|*W()%`$0(J@j|sm%h^TgeAY-Zkv<60;pG=xn2r zOv&vSTEs-mw{U0KJ8(Gj+OwV}^duvC;5Rlc?Ihh-wAq-Adx%kME%w#(jH1KJRDF&j z+x>O{E{z#LR^2Uh<-Rm_rsj`y`5>`tlUo-GsCoxctdI-BC(BlEayMZ zls;m$=MTzz`JSH3x#ttZn5Xq=NR1FNKR@9p>Q{*|$C(1UcTWl;N;;stzLBg^FSL)W%w7iBnc17UFa4`5$+CnBIqU02O?ZxcWgB4-aC_u zUrUAS_ICWY?JJ2D)n$@8m&xyn|L@Rwh$_<&8puv!b=FIuS}=eQldt3ChEKHGF@c87 z4#REq!H4M~*GGjvgSkL2pcuWks!^XhizsZ=V#mcsqtLt))yYp`p?!u9n)Xry({r#7 z<~ek_Go*(}vKO425AI6?(Qkva??;l#JvO6fH^>w_&Vd@|!m#3mP-Ln+%UHJpi6(;x zS`mnBQcg1uM^nw}a6UVGk(#Ipglv!Zc%jDBCDR1r$)91!83H?% z(WLjUItvMw!?Nw&P%e$dX1l92GOwBLCqDS(%6&9jJO0f!p52?)BE0rP2#x$-XlYL& z(gxfw81;mBUTnrm-VsrqnIk;nD9zTr--N6=Lzvxo1upOF=seY%biv+e9G=^QU^U*0 z`FASIe*05!=0*jw4p%@Qb%LJHQ(3~*$p|&;L4*lsE>dpNL$-A^T$yufGlrmOvk6lI zrJ3pLOkt5;Cbai7qgykcT;vR{OW7;pQqO(q=R)jMY8Ot`H;9{m{R8@kb^B!_9kHJD_D1nE2U6&5_BFg}|ikh`nK;saD6m&1FJw?ty!$Om-C z&1!n_Iq%HmoZ61swU9ECWB01Ugj)@>IkVLWgG*uL%sE{a7Mw|D_P4-V>n-O^$I^Bp z#pF!4!|UJ>>{>3s^V%PpHSHpuWfPAB{HD9{niPbmG?}{i6ynlX$=%gbYlY&aao#?X&>pQ+x3K(x&t#H(sc*TVoA<( zh<184E;|<^J=#>z<)p$|7EVX$O5RB<8iwGW1bX;mAziZOI@V?lK&{#wQ|9x%s&J|> zI4}=y(&}+_sSmk3T$dFsuOyZp?U3D<%H7e~^!#IS=IM6;WBPc9s+}i-BZjDr!(O^6 zJ_#bb{~|_iIGlMuxsm!x5}90s{_szb6sI{12nQsFeT! diff --git a/test/torchaudio_unittest/assets/kaldi/resample-16000-13000.ark b/test/torchaudio_unittest/assets/kaldi/resample-16000-13000.ark deleted file mode 100644 index 18ca3480246d26d29fcd1b4aee2f94e046a75d5d..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 26021 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 IdC-gh1N{4qEdT%j diff --git a/test/torchaudio_unittest/assets/kaldi/resample-16000-14000.ark b/test/torchaudio_unittest/assets/kaldi/resample-16000-14000.ark deleted file mode 100644 index 1b350217fb552dcb99ad226630f0c3e6522892c5..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 28021 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 =NobWF#0{YnuIt^U)4ep=-^bs{>a-k8 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 diff --git a/test/torchaudio_unittest/assets/kaldi/resample-16000-16000.ark b/test/torchaudio_unittest/assets/kaldi/resample-16000-16000.ark deleted file mode 100644 index 20b1a932ef919f3bd2f5e85716d2d74cc88edf81..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 32021 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 PT|b%uvBW4)SD?lJrvn)} diff --git a/test/torchaudio_unittest/assets/kaldi/resample-16000-19000.ark b/test/torchaudio_unittest/assets/kaldi/resample-16000-19000.ark deleted file mode 100644 index 1a78221a066ae7a7b622571ff480d32aa07feed9..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 38021 zcmWifhdlzw$jwrpcJ7fm87U7Bnd@AIL|{#WM-4B ztnBTa-{dcVfT?XIpgAiX5 zhOKGNWa}|GCi_#CUHov1blQjEME4*rx|gA(6cDd>qP)jER(O9Im3Y4$Lak~9x%T6o z%?ktu&LzLx$Fu39hO=Y+@5!yRo$mxDc*pM zay=-V>4ReE&yaSmA_U)W1~%A2+5UNK?#gYh@}{4~k!2bO+qLC}oru)elc&~sj&jq{JEYTBxBdYJ{)LJ?%gB*I6tn7nw?MlV2(nO!dA zkGFh`qnCORVEGrtohPu{O(^*8X~e?K{pnEf41~88!2gO6rt>~vOJg{R)t6xFB*wD? z)0dG&#xLRL){m;_Ke%GJ4P8gg=*Z7JwtM7N>guur8{5lJ-am-`^fzd>y-tGNCExSn$wYezIdy|WvQy^k=aM!>I} ztjGKeC+&fwhqfdj-p7#bu6P(DqdO6l$BFkbXx{>`?-y&UQ z2&K`bs2buUXrVKGS-@k(oeSvG#+?{&tj1>9et7ynNA=$6Mz{8Cxi+=8oooJL?KavnV(W*m1jW4&kKZjRX=wAt->*_El|~2MO)f= ztXgz|_7<(gw#((nIXj4qfl%lix<-!rj%NEJWY|k%4{|K(EnE$UaQ0Ox9LDppRq+;G zn?OxRHL8Q4~t39QQ2!uhTWOKw!a?6&iclXzXmbrpD4oRllhRlG8uP| zzM@^_hHQWNZ$W?L8KfpR;7d?9CKf-0vq=npk*hkpwV|1=`ud0b(M-bXY!N<2|3KX1 z2{1aGLL)?aY^SP{V4=S=PCfXC{#Wf#33Er`A`{bB`Z`SJQ!d?GISM*EzT&`mF|&i| z3|}XUpV$IXDBc$Ff8 zYkNGFTILbG$W9u)Ta}rYH}Tyc`{H7M58}M*ku~xdHm#AQR+&cZ(EcaXj-+lP%9e}46M&x?l1m0< zeg2PVPs~2iiA7P(=-%Uqp)1aUVI~GlzbuBnSfq)$RX-7UR)p!V<54Md~}yIDcx%GVL> zzf}>!?XIkM(!h(-kLIVKFK&^U@%e_k`fZ{0l@~ zehizTAj5Q=J;`A~I7ZtILG619MrfG8d9^Do59cvUgBkS0k3Cqltp=z4`jBEBfbc(h z#Lz*B9sVrFj{o{hK75bC++MC0wd7%cEf2-Fg6Z^EhOAsKSKzzy9NJ|Y(RjNXaT*U{ zr2Cp5+QikOUk!And>ygQO~OnWF|%lmADF*Y5gR=yJ$*!vb;XJa7TmcB3DZ_=U)heG z?rzxqh?>Y8(qU)ya;Sf`6pa7-h8(VrZ78Hj9zH~N$yHGKK`rK;KcAnj;)S<6I-!5J z8UH3YqT!f_!0Vg=Q|SLdrP?&%IU*Ymo`}$WES~E{KgpIgJ@ki%3bQjG;D2BK1c|GA zk-DcIH}sCe=f)V?6>P-Z(tN0u&RiT0D@4u_A&x3X;n&nx#IAb;YuGrBQQ5Uba(5p|Yz22~!546&8XfwX;P0;}{m?D$QDI?-BQ& zaHJj>!p7JVm@Zn5rWtP3(vinv+@{c-Ha3X#sX;_sAAbDthw^4^68%hx85)YQkTD6w z-y#;%Ek!VO%|k?p5$e~4&_51_Z2pogLFl>j_|DrO*Z{#f~&1l6K`F4EcyJ7kK(I#uZ>98B_ zKWXYOX~fxm!^_cPW>cdm!UX*!es3kUzNE!u(g~m1cp)LS6XmYWsJL_uFSd9Kep(u^ z1AWod=8G2g+{=bvxCnJWKg0Y(CaDeTq1z9uu;Jpvh;#K5EVA##vg$gx%sPURzGLb3 zJ|njE;Uj8)WFF?$6k@WX5EEG>luKTcpP?gJk>og*Ze~R!1h4R9<^UALsu1tA5$hgo zqTl*?Y}Kq|bhFKWkoBm*p>>1Ux+?_7mYyVf-D4PSm0~P5O1B0YvS)YG1O>M)pzu;7Ubb{`S@-}ycRb<8Bxta({CcXpv60lCPR6K45zM_Z zpcATq9G^7$L|TvCTf$OquD=DBtF1V%)Q(BXx1lw?J!wsd4$I!3Mbl5pz_aHYrgC#p z*i?!mPkTv5b0uB3PKzCtUc;Xvb`R70I^m++jQM}AVu6j1;6R`OD>sU!LWN0?ugZqo zJ`pT!Kg0C!57IQUj|$hQFu~msc0e?TKA&PU$3 zA`Dw9#Bzs7?7R7#J!sf19_zI;q)Vdq zA!K4L&MxUgao02OR;Uv5?aC~@Sx6Tmko4SJC3t zT1;Wa9{#%X_b{fq6Y1qmFxheyvkUzN4%G(ivrQx&**Xa+1KH5HAj0gWpV27yom|oF zr(&rSnQEjYNx9(%-{@Xczpg{o&co2ZtxOm78?kHWys3H9e6-y!!cQ|HvWnm1sk1*h zydDbhqakq^_vM{Ne$uKM)L! z1xJW0m1p`prI@*?4>`X$0@hE4V3=PF^*u{qVtAJd*7KOyQ(d~;W%lJZu> z?Q6rsW>-uPZ%eMU(q&Bi2Nm~|gNA!Lq(_OF72Ovgc}W*Z3;shhGBw$R(qsIFgnQUB zy$hSGnozam3aY=o7U(A!Fy%$>>ESmz`09{@k=`Qwjg3Qb=2vp=L_gKIH<6|7lOd~( zpF&vK3$N*QI6@9VdXEa#z(%RA>8$h(CksHbhrWw+O>;Z zoA4U-Tpp-t|Au7rdc^7NrZeS@+1=0k>6wLV@nCNy%Gw8Ds22?V2M0*6_E@&(i6ndS z@G)_|7lEACAzXZ1i~!zZWH@@#Oer3_6+VgPtU7?rIkgZN^|96X@enpej z=GD+b{Wh}CH3e(ixgG7?cO0o01Iey*I`~kRwU!@B`4i-VF2y#iz0$^g-WB`W7N$t< z(q+-_zSHtmqv14|jw>2sX8Xqr5MI|#T$feT0545uC~=-|xbZ$ruXkbPg(gf~rKaJT17~<;OwfnMOvvAD}iTCbD0#V~FjOr?@ES#gn#L{0uvY z1M@VfDfb><3%uxD-Xi?0DuQp%5O%D3k5D;3vTv^>8*z0kYoBXF4sUx6ubcr4jr@&* z)9Wx|?q2G}cuf1&URo}-4rcY0c+oL{_cvaneZYpC!dMo4Opz*9Iif(P1D9vN<-+0nD z1&eTTe=$T7Lc}CQU`57bB6C5KWzHVU($DQDwUWV@DK?0lo0X8WU5iuM`{?vGZoXW! zhiYtHj~6<>xmq@WGb*nk;kcXZsu;_nR3w>L@l(=$;ys>}4WS{c2$`M>QD}6ZR`Pkw zX}>BJpKu7pigl3r)r%F@PoaBKmR$Fq$g&>vQ!~4-B*ilhd#{Kf^)v_9dvtJCCRDEJf?wG^TunK_PxRAdlk5M`GtQla-V|U7H`|cbSbMKL(``9SypIIq-j4xjEvbadk2Q$&JVg5xjhXbO9dyd%4VX6XHx~L1 zV6Zd@eofoRv*ilR;MgeUx!s@SeSD98eIZsv6rsv|0bU*Ormf9JOtMOuR&*c2O^-V4 z$?k4IhH#8T%oV(y4Ad2|joPuD?Q-FqrlYrt+;z7S{_U4`4< zCj6-FBt-|hq@h^^oo=&(<*zKte|om zJnuHRbA9>VI2VZZhou~;)MeI}zf$S{#=^b%J2F+cUZR|W1>>5D@A5j@UZlYqEWP-> z;ois}){UT&MkK7d2m{?O0ukSkN%(W~LYM&>e&^!sED@9xK0!1#g)F!rr1g%Co z%#Kt(4@QIRAgrcU;#8_7%rlPASMfY{E@3PEShE3l-f%VQFu3}oOur}l^git z+q77g@^6Z%y`)2iVg*;zmrhE@hcp?Sx5=Wjx%qSV-zmv?_iv*}vK{wcwLP!xt==ZYOr)qAHL&~2k@=$g4&rzB)-3Z zb*fBIA7IEVN4=p@$%e4#=6V-5%e}ASb{qX9(o!U%y+S3XtD-^tH2p!2^}$}f7CJ?H zky6g13I}*B;Xik};{H;6SXF{bHUv}mcPM-4O=_E^SVP$u)>?F&e3>1Bxb1_Gd|!bR z{{P`>o*ms^&11)cH`CR|8*yHu3LSi|C+EIGyxT@HCQE@mD;>#lEMAg*v5}ZQMhJ)6 zLPQ15gLA_}>MO@%Y0ng>s`3%+`CNxBcD)cA;Rn}|;$-7-6*j)NhwgO9B+mYyvEjK0 zqUdZSP0&XB_h>qJ-hjo{dJBfuUc(K$W@Hq1VywFtghyBKuWiy|(bp?!ida8c?L*Nv zQOxW=mv5NVDvjF{f6^_HI_z5Gw&jsLH_Xv&$Hlp=NSt^JBj**SEOpjnDF;&N@@wOu z=9d9lB7)+7$uQGsAn~PtY4BkU=4AYwKVs?a7vB zt*GA!Yv`#}VTbMjZoYbjjKk|l>cMfWKw%^c`VdG~i$@`x%LB)pLJZuT3kB*!g-%9n z;I=${T7CrOTk3IbS1%47e}Y2!A^z7}Doku@56!5|BAF)fkc$+dUoRUW##&H_|3Fg@ z8n78V?g}1vUc;7W%~)mI2?cF09DTopKQT{>)w@*Cpu2-)YYs)hkO;Y!-%!t&#`Z7S z^rM#!o4+a4#P5_F8VuW^Kd%*T$v3flMt{n&yLxQPdrH^JE8_1!1_~s_%svh!A^ce# z$;fJ;sYU9nW%Mh)MC$`gz0?imd5!q<lRVp_5&C+^(C4OgRziJ7Q4P z_?bvv5M!xa3<9s}l1b(Pi1zJ+^3fW+|Fs9E&!^Fxl=e$Am)T>OhtqjtQxSqW)`R%CxdIW@tB|wao<5A@v5|S}sAar0%1>8e@~QzS z$-hFX%75e;7lXU$Bbb9_5IN=^h0)GJY%njx_G5EkdEhb4`(VWSKFQIA3U-KatH-~A z9-Qy@Ma9}4e$YP^_AR)Z8gI@aSuf+!XD32p%}=Q9)x_Z97&^GcfbGh@C5YYbh_fEe zIB~oa#(AEo9zB_VeYiI3pIT05EEbaTVGJKQAEtKPH;6SzqRl;ry7G0Hslsqmr(!p3 z^=ZdfjaK}SxCzCU5rTmYdTjkHO67FML-{(VF^P+r-8z|s+R7Rdx3iIs5~;Jjbz%I~ zw;tla)o#u^Xu!AcXCdqGOJLq;$Tl5*O=pK1!)hQ8*UE+192Emgr#K>MHHjtp>T5zDo5{u*09-hwiAzCUhhH^pPRr(sT4n5hmd9yj=ryV2$Pdx(WRr= zwmZs?2P0& zV+C%tdTdlr3SGEw0&cwhfzv-k*r}C-oO{(|ePWvz_piR9+0!TE__};p$#Xr-ItGffVu^0lFy?AIf!R9oi1lCq7HalmyI2jr z*6u=Z>RkGMHIMxlev5wkV2X~AQk*s(!ohEEF(bl*=-!ZFy5XbQ>|b0$nd_%!*A{)8ekpFfFM#`rUxoN}gPcy&ju;dT^2Fi<*WyzU3KJ_D;5w4(`t<3v3e5 zT_nQp89y<}LLFAVpXk`%`fSJOi-MIKosho11@p=}5R-iu^^W8Cj}B_HqnAqQCdFY0 z9+`@79U`Qx`id%(QSfTWqcz==*zVg$OwGI9vCpp^p@IL?OdOa5HlT2SO zQ^H@-4~TV&u&?n8ruY0N!GD{n59be+=*02wEqDY6&bw3dY(U|6d;D2jBXId)$V^)U z=|YPsh|9}I!GI6}i68Oz=|?j6-!S&Wbpi{mn@YrPKZii0AEEBmxUannI=|=BO#-eb zCp*)&Z+z%Sl_Gl75X61nVt=L^>6;|WW@?UREl(WD58fMidJV$Np&SCKm5^+Apj{t$ zOx=1VZTh$c#Z&&^VsAgL6ud;nFB9@`pCbEpM}kez4I@&oqj5Pwi0sq9;Js}o+U1|p zvA#y^f{X;cn0_29m;J@xcRg6^{utInfB2#*Rkrz42c59DkTeJqaE;S}?-XVs!b=Tb z%i`$%fBGzR{vm-xq7wqpf=15MiobjpJ8OpX^O!a>|5Qx#YKI}rI2GO##LQ}>zhb4% zNcfr;&=W@|vEsXTOzW0-V5U+BK3@Na)`S~~YM3GLDbi!r7n7*CNC_!UnXu>=VV3n5 zBn?!Mve_;4+I&tIcSz>jmpnqnAg593Hh^Dp8Y7SW6OS%e?+9KSigs_Jw#7Fz9uwbx>LHJit3Qm@lT<^-0KWeAuv zgbu^ESd{8Y3Or>Q3zlQKO4o_`qc;fZ8N?Lrau~<2fcd>Ebn{CdGaR>q&i}d<-(LTL zZE!ytm%PN%v}MGDDzaBAC0H6Soa~$Y0TCWT+!!o?Z_W$|A3me{FO1l{D`K?h_X%uU z^cOo%^&n#BW4JCX;j37vF=pCMueTSGYc&bjnT4_R<^Qbp44cuM^B*}AP;1z*Lk zLnESv(}+7Tt@;l3DKwb|m1r~dup(;YB94>ssj%dUnWdabL!H?Olu7=giR&jZ1<9AD ztkMID8#_?e+k*1VH(+4DSg>z~KC?adh2Bw{h?&1Kfkz@78utZxlPie0R4aYiq{hzJ zrSoO=eBkr{7z}GbocU>7+S@MJU}3~OzdfgYGp6Ctv;ufk3ZZ2D5mL`1$yA{@Q+YO? z?H8X*=FNBkOUHh^HLpf`*LG;sEv1e3c+6etIz4(42t8kh^{PX-?h%G26&Et_MwU%F zEyt!yJCo_gVK`Sah!5UnC^B4u(zI)IDc28n2k`0Q%x%yT{6VU9Kh{gXgzoso#Qx-X zW`2J-YaJg!f^9#*#Z`#;odvL{nvTqX0O~o*hzWfL1d%Q$5q|40j9hzgtKJ7%vDy3t zWi@ulwvCQDR6xZpN7SoW7Vg9jc!TAe$#d@{v%RdbO9Ne_W~0g`f;J; z4`vT-LqzX#`jGR4KcqTRw=6Tr+$@7r=^*yc3WH1FO)|7zj;ZtH*m(b2X4R!6Ugah3oa)CSj!)@6yA5jFK%0tq z?BVchw0_SDEM#RMZG-6Ue1n1R>!kj!92g?T^e>7@k1@Yy5!SOdDlqY2(>YXxt zHzm=^d_ATcHCu3P-whmC@(=oE9q4=DfxLA-ra$*jV&Vr2sGZXYL?ooa&PdFx;!G-( zXNp62YB3G@tj#37yG*^O-GxLI*ALFN;8H%c4rDx&9D^BzI zo&aByA~L$5oxaspV`57y`2SsbjD=@<@P5``WVoL|*?MuB;cvvUQ=ih$GBaUk{0n(c zgg7|z1IU!Ogm+$oi8&}TWsBuxs^d!-e(lFamp>S7u@%eX%_;v9kDc9hg@*1kNAQ|* z+{+onSGzaZGuDYH25^kf0a|yw#M+-T!lpxi92!J zwHmD>`k@g191>A8i1)z>?DGb3mQeSBB;Wmrr2-+$oAa??!c>&+4Wv_)jhL=po#5Jh zd#IuT;SxPq?fVG2(Fy!5^VHd*)@FJ-sglG$`hqIX0~kp%G0s^DiRDRD@uwd1S};Yh zPTCnk&;Q|iT{}*W^T3j*>!x{kCb6c*eA*O068GnQ#TW@OGt+UYSb2UJURsvW1M%7{ z?6?d+H1aOSf9`;tWedLCcESSxV*+2HJ{#B&M^og~@wXrgvzZ9JPZF@9vVeFOcF=|K zs*IOi%ikXJ7zZ?<<^I!NFCPd27Xe2IvLpE`< ziHp4=J5j?Y?Mi`&ZSBVqVHMt(Zb7HH1>I80`3KgQ=!N?$vFBzvqAw0YPx=iSny-;v zhek8^8X5K}&Yet-e2Z9_A@qlr;^0m`c7@%fy90S_y2CtLb8;7MzpaJ`*Y8!d>aW1m0P{Lm`f*o6=$i(GV65}m_ z$SUoJUn<9^L~lm1f+e*U^4MViS(>h6fwm9j_~$%`hLliD_r6SyRF7u0<7L<->OqDp zgu`bq=Lw%Eh0J_Y1Wa|Is>VFF=F1!!p|=~U%W7aQ-VfWT0Hkynk%|u!*oPa#*em5v z#LqnjS|daphnbJG9%HOt6+}0P8?p1NN(FI_XYnPW0msgCbDZNtj64^~@2^p3mV26L z;I0~SU||wux&0tD;0OAv#^cjd0daf0YcU&W^IKd!(arHGN3)v|>gtHn@y>$w9(}fR zXDprmTLW3uKXK-q2%d5A(4CY^GWU1UxmK#|R82eIs?`^6-+K^wzaEz_+aY7F47Fh# zpK{-qI_u0qqD&#ze}st5ih@MgYm&l7FniB&>_pEhBKbZL5?TYO`do#+J)01(ypC#q zr(i*{2LNDwxz0? zLbP{?6uc;>cgAS5)Yw`4DbikeX48q!92;?Cnjq61esiB32Jzrezhb&bP*cZR_b)abwmzc#57pwi@}{ zD{#qt5GkBKH|oMG4ltUye-Hnjh-i`S12XOrHf?qdAgKfOgK<|as6NS0S*e(ML?a*!E z_>}TTN$1>jSl_Up)bNZ9P8EDZnmXqJ9HbB*+eeQ7uB5LmwU~X*D!z557nC?YB@oTn zBXRKR4-Aey^_;n`+K%8SRa^R-g!^pOXo^4mKs zOyYd`NhJu@UWzCOcdF^iV?K+F=+#5}a7m>WVY~Zq^Y1fkR#PV_OO)BV6cH_+o=m>? z#p0cu2*H1IQM}I(4i#@`{&hpv>69#Z`S$|8`!vF6pbNYKZ$x)^^ZT+i*x9H$I@_d) z9R89FcdiyKU6X-L-^ZfO=qnX`(`DZ_#-|j<-Qsuvj!*gB21TpeAi<8w52JM0N0lu4 z)Jhf$)~7>`^D>WD2r$aJhn#c&O;z@4vFg;Ve3?`CP?Xb&>pz8g<^?e-_D=8aE<$Ha6QVg^O4ZUE0>``j?k)`$S5r%$i<(KPMG8)h6EpL8 z{T*M`$Ks;VH|m+E%WNn3r_`==!T8Qr=*tYxMGtFPZhCJzO{-eG{_h=1c_%6gpnxRVZ!HD>E{57PeG zYf+6#$Z|2TpTqf<%?C-vn6Ye19mhsoeoQ9pkAQ5&5b`35vFrR|xKHw=kEZk3#aEN4 z#Gn26{k9fb=6%R8d?SQFsxfpP4#N4L)xO~Kwzi^i(i$N_t64gp}b9_nyx3B)^@EvyZ<j&>wHPO^n1)!5~5kD80A5Wz<2hdYJZK`Qble0Z1O=&9b1Rf$-UT6 z_!POp@?^$eWmXe3NNv`ol3iQk;K0qM@1$~(mZgW>;&(LD(2&(X3Kxh)IDnZo!TMkq zCcM3mW;I8?$7@Zt(50HTh_{oBUn$tb)glM;?+ET4jirp^f9C44>C3HBYUNy^%rRPK z8{4>9fMX+OZcmY0smm14ey6RPV{l;GcN`ciX0|#p1x-n94r!w+={H8X?#>$B-p$ct^uu=)r;GQ+{xaW$UCkBrQoLZl4EfsMJKZ*g}Ck zPJarW+Fn$(*J6410aPv3rt5Tg?CxJr>h^RIE-xrX9OvC`ZjC_VR$pSuF+P80j%5)U z`-oA}Yly@LaVD-3bFQt$qq4p9STm1_=j@@bL+hZ-@mr%m4IpORYlOewLwq1CZr?z;ohQzZ5OVq-N(nv$N4F% zHCdruH9bF}lX&kEAb_hy$VVegrq4W? za;HX@dF)H4MNaalJNzAC93xb|B?SfXtz_ScS{iMy$qH;e_*Gf=p~=O47n)#RdI=)~ zV+AfohRiJQEzR7jkGYF;;bbSm0rm-369lAS?htJbQfAT%#uLj$&+uy{$7TlA;?&#y zFq^1D?YJ16Z@Ehshb~55d@;guh7hwM0;cMZ$%TKCY`)A`W)gdd2v-K9U<`s^yX@VKYMtD8HhZD~Z@&_9<*`bAhXq!fD zd9?_BSJOFeN)CVHeo%`kx~%XmO>XA+6z>CVsQTNA6VqL=d*jQL>=IpO*8i1m=lGPG z_umoA-Ej;qOyPXRW+EwFM>h}CWODnx_+*b@q(KNxft9GqgSUI zU}1JHa`uWKHtrKb^SPepDx}l*b9_pmGEq-^hV*@Xkd&^4ztE3D+%>X0MEDr0FoOCf331N-v!E`C*7~vqLk-Y5nMid|=4kxvG`Y? zMDDy0QH^EFtTs!XNQn8PW@{g06>4F-Vjm848qw`8JoazCJ6&bE6it&$P@FIX_k?$l z)qX&(iKLkA_c5%0_c0Q!5Q4MZ?CJNb0vnqC!^{cCsQYam;}3437fY<5JNO$9EC(=p zco4o$*hqYiDX62nN)PF1jt?X1igewSBiQRxhr5@! z+Xitz9EciDENoSn_s3qkCpwe(9{7x9+>D_Vn~gh{v|+U+nkL5>u#DCB1&@SRL3cL; zL!CHu#S7j%3;zD)TI@kXC5^b*M<$)3$ki4z>reOw;RqSLanGVEi8@To&J z)DGUZRurn-!dk7&lxhn-rqz&28~EJ4K|lt!Rfu3?m5k{D4dkx#U%L5`22&RE=a1O^ zfZL6`aFSz$c1*f}V6pFlNba^IusVdAnHb^Gv^;n&7C|jA7AYGO$xRh879Xm_4&`c+ zQ5XG@^}Y|~|7ze_V*~pGlc^EMjJgH8(WX<&@a=gCtey`cZo)fE_PtLI&y!|rvd6H^ zGftC^+aai1JBUX+D&VC3A2u}{ryZPLlwY=ys+DiVAB8HM8#92tF|QDOWj%>lHI7wU zjbw{91(Gcdk=V-Z9ZuYh!p4fZ_-W%q9YTzlKyfTJe|H4w!a5Y5?L}S46I|CF;t#G@ zVF#0Y=Tzl4IHQXM_%0F6(3Byv7X%i`v0tTT$9^6IK7( zQk+8cSnEqlUx$u^R!;`9>Nu@%MlzP!){|oSMk*Pt&dhqA^EE0T;K$l-Xl!fbZeGqK zU}ByiPR)=x+z6p}s1aTi=3&B25u!vfobMk`d@hPH`P)kDppg!FqZNQtDSgP?UjzTC zHi$2oN^>~f#@FUHZHiouSLr3#YB_|r72!zy=S3pFOEY8JF)TIW99fbTg65^17O}Yk z*A}eC9sko*^qa>5`0MGIo7Nb)whB@!2e5QG#|SO5Br=D`vGv?N)DU|`&TNk2?r??N zT~{GAqUNA)-ecX?MchqdJ4twuUGL7gRE4dL7FdI-&cZnUxnv`#yRVw+!rbMFmVp71qw zBF1o1%!g_kcOUsH27!rjWTw}rsJJ(%7wlP*2WV-`}Na}9^`hPz~5nKXMceGJQaeu=26hC(B75GQpiP#R+abq{-LG~AfY zzOsgT9^HgNS_PYV1CTfoh_JBLM8b9)>&qO$1}6oRHPulVxkHFwVue^)J{w>7zBIJb zh~;KUQ?YD2Y`$ENf!{q?DDZ{S%yxb|r!nrm+(jq;$|WoFQ@QF)z9otu_2D6Y-{{6*a04FNo<-=rG69h{VvWtO=z#QOsT=k{6Q zTP!`~LH4M~u!}{b+0U6*h+=*yu5o^wa?K{qm5a8(0^3Ab~9wZR-w4D zAG?+W!jGAgyH<)!XflGmdJ#&@TBFd(X@N-@zd(#;gG%|)69q=>rR+$mqjC(UmGz(v zJy6@>%iS6_@W~rhHvMr2U2-&!#H>ufN$$5WUH=n{W7H9m^@*N@?y(#y_hDAy1qj?-t)?K>_~Lc_kSysqYY1a?B@QPwDb-iQ$CkMgY#M}1K*-|jXP=oC&Q8~ zxm)37js%)-(0h6iSFV+FcWf(Rm3WCB%HpvzY8G_Ra|=u*{@`RsKb{P}#62FLC>>E` zqeCQ^Q}!G3^msHze-L8*<6n?}HxtVX{ive55wpE0L5FQTjzP{-s?O*^)yv1Yytal9 zrpmekI;gzXFS0Z&0j;Sb7^P+5+K?Jr9>>whE`3%nVJE2bal(3=78G*c?)Z@ZQFI>u zSa*LIM};IsvdNyM`Lw6|Tx}ZKQ+rE$se~k>B&3ogNhMK8QsF*FlocUD_6pg1{Lb$m zczRy<*Z029`CRYo{kaYLM?w&uti`^z6wn*DMPWK62^ZQ2F_%AsZO-DT_%D~5^IU%N zQhT$~S?=&F`;&9qGe81c_;dNSV?P(@n2ouI56t zEjSwyJ(Ag{*prL{ui#nShk+%Is3ShFnkD?nGd3%Ucp6fqgwx;BQTTEYN439TT5U1G#DDbT7bxgI%_@LiJZ{9~7WE3fbx&Z~#agf{o#+~UAEFUI1$kC#%yLFE z9UEFeo?Cpzk$;0&cq{`hPgF2e;uDqHqtD*|TQ8J4?*KLKKiTcwij7xpLCN#CnP#&V z6FZSlMXwFP`QcxoB`>nr+VCq@hYf{6Mjo|2sm*GlKAYX2b_=P3R)iNdVy?O)ekeh> z{f<5p)A>vfrzoSlJRN=S2SKVnqg1hoO#9PBj~`cKU1e#4w}*XknX?>gyJ|7Y<|O8( zbP5kh^Y?o36Pi{t5$oJ?xkF(9{a>TdP#I1-yTw?y-&j^~ekSpH8i+Z!xL2UB94-3W zaIkm*JzQ+eCjMtnZO$x4)~N3x(w zd%ReT$z$#5+%{uoG;JZBK5iQpx0fU0Xb(mu1tL~-7AX{tWs6(ISpC~@qWdWdSCR(M z@gf%;@{=HX{|N>E{^WfIq49>3sHm#Nwk4gI>+Xwy)2RaI|1&~!o2gS-AxW$Fj8vWh zBo5Dj|21VSKk|uYzSd{+>z4>s^c~TY+KBSqt?-xPoYsPGW*5(EvoXtm(dnH-@k8V* zdU&6yw=4<5ydk)uoKG!RYcn5{IRp#>nN*-O8*$N@Z1N37l?J~%94fqw8eW?_@& z(|c0eaeYe#PF~{AKt2#AG5?Xt>0_BSe+TnFyd@#?qY=_L0GrXdI52S{G?xU@JYysF z&AM4Q{Lm>()8PDTQ3ooFebKimSumzfjWve`z2I*qy;z$K(aNJc9EPF(>{re#iY%V+HVH>Jieb2C zK2`74Vn1iKnKicD!p+~UNPgLfgdBTRxo#G^W$3flzdzE7N2=HxodJvNL411u2}HMm zod4cJtu@tHoko#BxaB@(`gLORs9NOzv%yDzac(K|u&zo4n8S8cKqGXqOj4W&=V0d`G&MI}7^M=h6*lcVM(f1)j?F zU`jM+gz~14p#Kz@v8x!9-W5f*+>AyQ|4p{3%)yi0rckPRO5bpg(8}Z*p_$Zatn;s|AA@Wrbp2_ia+&9j4DoheK?HS$!M-I+?k z4Db869@~kiiM5CgIgVk+htl_3l^Vd>G2!o5-^# zbIgck%Tqk)>p`+yIRf5n#wyR{bT-ekZ1ZfX(|^mL=35K}e)j2_^a=`9cI1t?46|33 zW`*6Z#83Dd2W$DPBDoNuX9Vc4yiSXGhd`xsCe88QiG4N|_&T!(qxU_*ADEJF#}pVf z5M$P!@5!EkXatWLMBB$4h>K0Y7Kb1zH_eEhTU#phk30<@&pId>c0xhn9;C}-1cRJW zw)oIMKW-``1-)Nj-_7%o$}}7+Re`^y*JYl*u8I`fXJHfGV@yT`Q28`2a@;I-y%tgLA8_ zdEP8e9q)4vd6plw&Yp@56?s^Ag?H%0BGGi~CGnIW#?~&CXF(oI$oMru&?xW0yiaBL z*SHCG+UB%D)P$L;pQm+0m*dXUV)!2G!}RKxxafC<{K}DGTW618^G~~z=Pj?XVqrfb zeG5_KYKDrY8}ui?Ta@0MPRHw8p=MYmR;u(MxFrCayo`wcQ3ZB6MwA78iXpT2y~k;u zN1CqAfp&!n2D!uLovIO&vMCmp3eF-ast)(~z4Ne#4>pl#!G=HT%p<#=&QPf&XXN8? znL7)%JEq|hXZz327t(QEdhE$=Y2nkm*U`@Tl>4_ir*+v4O_%k}Ja_7_?8jO3V!8xa zY%-*HpGp26gH6OB*(Os=BmFg*n~jRV^_T~)>}(~eKu4WL+{FK zU|V4({P?*@7#)XIS=^s8y`9eFcgI@RB)FaQ03}VG@H$XAuB~A`3&-!>jRqB zG7WpX^Dx(9fIC>;;o*f4vN&iMixrMx`HNQ&bDtm_9?}bs^fFA(*obAGtLe~h#>{ck z89FtQcQg8mVaxBrp=)0v{=`KRTPwqKnx)uQz1w8^g)pez?#DgpLd?9n2*y6n^wSYz zcG_VoRa>wNVS6i4%5(X7Cj*f8#ehs0smPM%h_cD4u|y>8J(@Y6a*sP~B6gbKKilUt zy2Ow<$ma>AbkAWVXM|?D^Y5ZVK6n}MO7LHUIy1ifm*(EDB4@1PA;;(VE~nD?JVGA! zLn)mZsK<0FhX}(JoZzp|`4s*P{)=;kZQj5l*>yThFgJ@@hz*B}K?=6&iY#uctMm@56%WPQ6Q2u757K;?QHI(a8;|CVbwefOqt?Ro=tMEpISbafo!NBuzS>OuH$ zhfQ+o53(?`gU(Ch?v8>E!O=+%;au5?c#j%57aj%mmZ2dIMr>!)eR`()Kb)BT3)?*g z(0chDb~`>J&i2FDtG8p=oK_2>CjAT==Dj%UP=;{}HXtx;H7!*)VUCigXpP89h*dAz{gkLz*2aWQ@&_6%{MZ(ka-buJTW=H%Vj z&Sy}ePr5PJBmleHbjXZ*ip+|4sZKb@k=)MrSfIdNPU%0fca<@INxYy>IG?iC|A+8f z)H$&Ee<5?B10F@**d!h#Sk|r1K0mFan?!1ew0r{mIOp@WDiz+PWB8nyQb`v*R@l~- zSdr}n_jyea({F*!R_?HgdAuk+M2Bg5{h&$vrC_us1@_`R1Bj;Bu&$5v75t&b1)5B1 z%_6}C?K_ZmXv4W{4LDh0hr^pagj1ain7VEh-7-#-v$#J{^@4vFO^rjXFoPTo>7-V3 zRM_$DeFERx50QPS3yCH*xWSIV*-VzkUoc`WA-?p+$LVM)|AiwnI2+OV7Pedf*FQ>} z{n|T*6?Cm3c^{v_TCEq_s%5BozaAp)>!^&X33Cgxp_`YQqkQonMDzJ{=7kr?v^h;Q zIUAvSQi`n|>qW8}!;sHss*Ya2u{C@F#vkH*%42>uH8P1$=Y6KX@Zfxk%WZG; z#QF*Ji3W3wtEFj4wZ!jP0!;V}+0i)_`wxu4mPbj{&PtD27iT7_8{fdPB~92b%{wt_ zuDn+iwczUy9oGIWgO-gRfl}WTEaW}mxi=}4K6jIzk0tczdQFzMe3`(^{|-V++fZ_# z0aA19uzseG@YE3l=JGm{CeGJ_E&YK~KR!40{s?pRbP}oGMJ>3)rtX0ld7$D4H=8aD z<7~w2p2HZNJBB7n8?(?1A38sA2FCUNLX5}&g2K5!B`=U9Hi|Q)NICW>Y&{v@@(ibE z^}H{{0^$?dU_5?h7=E9w%!H`Fqefob`?HCdT*P zAmBT9n&CJ6x6ViHWH&m=iF4Od#&lrFUTo2+!r;knIClHv&=L)@d4>{edNxRRImVOa zx^Hqn;Y#hxq#80O77=42W&%*AhQan@ZB&#Az=%9}#3vJyf=vwWGt$A(S$=HB-3$7v~##eZ%i@Th> z-%;l{ZM+cvK$^=SmK%P=_&=#+@8)j$`mqZ0ah4!v`}i~1*M;R#)p($L7}}P z;om3jN9d<43xv-p!8qRKw!RsH=e9@5!mXp(;pfBIbkTdHLpL0IpY~(l&jPfi%!5(2 zJKgQhdpMc;boQ8iIHg&|-B#Urm+g<>Z^|UVU5VW|HbB!|6Uil>=~)Q|ah7L%Pc9oE zCOwo&SQ@h0$T*?Zx{FBt_ZRbeIH%y`1&7lfg7N$r=+;-!VA4Q(3=*Ni|CaaVeTVie zS=bjR(_o^4^wh>#uujOwl-UEg z>lguxw~t8!lVCT*P&vzeFx$9CXr(^V++NcjEkmZ@`9Wy)<`Tr_ z)&mc@!=d{wyi8mLYE#Csl~1dvxmXiPa!kZXK6fiW|D8X-(a0J8jppX)GJ73|M6+AY zXsK`F3`sML<8Q(-M=^1SwJw{pGL^bEjD$q^H&pZA^F~`C4o+wzN^>iy-{o;^dWwx8 zQ|vAtTed?csUF#Bmys*=N;vtU0qd9&K|hVxMSN5i4qh6>+ncfIX#Gm6uJ+J^AY~Tu z-$-I}>=B|eyWpr)jXTK)(7#QU`foF4spX!uBX2f-r{qJetshwy5vXI2NX;}!X7Wpx zNqpKxPD?*W`rBUkik8A<$y$88xQj}unXugl_s|-P)euCKAc!+Usb$Y$JbfQ2IVH=I z$4fHTxcfw-JRG^h2XMoZ=l&&gaDMw88p3&D{fXMNs&GHH^;E&}Zx`zSJwnPxS@QmY z67Qw=^Nfv=H49@gL3I$3%GpTUqK9(FFlubhJwgxO3Qa^Wqe!A2mOkx>cyyQNJB|Vs z+i~p5gG#DNw_RbVV@#-d#L!Zb$LbdiZ7A za>rhn@ROV&GyV03=I_%(2j^34Ck!HeLM+tMlgL$`kd)6 z>-T&_E6+gz@uW4&jM>m+b!tivV3>S0q=UQQ<^KqcxiVz+Wo34AZ7=^W`bwHk#A5wa z-ckLV1+P$D%x&N-6wicBPlgIp?JpzsNIf3ewWAPsacj&e!N&FDnB~0+8s*zcg0zHK z#JSHMo!?MXJrXO=eWwrHbXoXwgG6z=o5U-WS-!RkkQUWojhGu?D35T8H@%_ zedqlEk;UWIC*u0nW+Gu;Mcqz}W64r3f-cUdJP&Ng+HRgl9<;^K$I(LJX+x%T=rx`2 zNss$nvQfzM$o-uk@a+X9xy}7FdKu?a66MI{S^j9#>_)}MDn#$x4?j&kdQR1t37cntAC80#_eoKlB%3=%mbK10KrAMQAfU4sRhvt&MrAd^NA9N~qfD6W z&7E}R@3nYpSPEC}dV1UyjL*3{NWP35bNMB~!lM0&z?HvOoDnKc&PS~3Y&@^LOGAx} z+0r6qdT{SSTozRGY_to7N{?WfCq>8$Wu`f$hvrMCkbrE?2zhbt?06Ogw{$QyB7%PR zGGJ52KNp5wy@I7p^+-@@$KqH|h&3M)RELja>cQnS{&qVV8ztnt^&nbZzCnHONKlhB z+O(VdQ$i~fZj5q);r3?kvS`9n&Mrni_eqRx(q*UCrO+xvS(JNyM>c;3w^k)$xKAT# z98pc3700n}OFaa>`d;``)Q*Yr{P&>zB8J}oD9q)2N|kLWjZW5wcvLn@thqyqeBg6N zAyHp5Kplt@)2UJ*KH>f_J>HEQ{2T)7eejXer^=?By%ph(u@m!fxxE0*+(oIoCLBrb z_ejr*;cQOeXg2NVVd54L0*B~cys;`l=&V&}S#p@lq;Y3~`gR&pXo>JirFazEi=e<@ z#2(p9?E7TdD1Ql-78F1x?=3z5$AFbI`U^AMufp_iJydeq zkbJ-sv~Y)@&{C7l9a%=#x^$9n*+N(k4kBXQxWif1gDwgw(u}T4FBXsLYM!5|&7U5RZus76L~ z_``f%H|!;igUB#%a;RfCyOTSLX|rQw zV@(K7j_H{AcQHP1q2FBAVQoPv8qf72KqnaOZ`YIX8FK96QVAB_ z`Gmyyy~SZI-j^SjkAkonV28YE$HpSWIsh zy*E3ZEM5N*$2~ba9sPrQZ8;l0Ka#%8F<@(gyoBRpuOf3<1NIiRA*1dNR!&+im=&VQ zp7i{o$+Nk`W*5aOZSK?hnF6oi5spfg>u6n#I_~CbHrZ~EmlkIBQ@BA+kS%Jb>4W_-VR&qzgW5c0-ic2 z3!C_PdE=^=bd8!3wvPD;UlY#FC&u7$|7SwfL|A~3^C_psk&d;G5#-JNDMPDJyl@ZZ z4syrjMq}2T#lzcEKj=Au>w_1*f;EFsp)2$_{3bpr0Qx{nH?Z zy8gg}lbSHEjHL3n4A>9bJHmaAcDQq=f&V|Zfla)FX*U)N%7vONMXZFbQtl}kQk=8?LD#*~VWZ#AU-V&-E0kun;ONjM=qTKPpK)zs8NWl{TF0pR-7zRA zO@%KV#Det+xGP#q0wU|^Lp}#_tOyXeQ*YR*bnqhZ_LH=1Ovgf(lWcI(uSQ_4qzwatB^ZPDznUAL`34Hb$ zblRQ`7%(ow+PS@mwRr}YjjPC(3u9PT=`gnQ_%mW<{0^g!4q)h$Ul`r-ADTwrr}a0D zSj7BMG<)??6dtNUl%NZyQy=2^wr;_d>niN!gih+%mPraP#36|P9y}HMfrPi?c$Y1j z>R#ro+<+@*Wv}7P?FNK!K4p2k2k(W=6sSpRF;CGywDDd)Y2dEhF`RdcFipW?;c%>7 zmqm|W&|%Y_)-AGka)si~7Hl+a!uzvM-1{dg^t-ReF0~4&w52?*&rO5U|9=lY#A8u= z6}f%nFKvxdXJeF}3y#h3!AYMEw6*ZL`Ra4mgLX-x!NIpK>#u=T3p| z5i9oNa)J2#eu4RW`mlNIA1oiT0^&o@Qc=!MN1t3n5B}KzM~^Z% zsr16@X%I#qUO~#5#xS+4VQgA>FbNLee9FE7H1fGD8Jvcorw?c?cWbVZ8A%lvA4AjC z8on2y6ZPqQrud>+5VKpAt=ZW@z1_3OjaPBFx`;b8IG$5CAwP7+qsyUKNuj7$1vTdWjT~4pQVQajM*II5X3ghpg~v2-AH?8|{tQg4^P>@qjhTlWNc^*@eTe9^iLs zgP>)ODw~?oN-wtjBry7f(6T`+d!30mDGlzkh@mbQ^;xdSWnr|kJ$yIteGKMpxTNO+ zpXsWC`TV=6Fs_hBycEF{u_QQikI*;gWS%5SVA#@ZdgiY-6Y<+@cC5w?`{P?6MgL(c zpJT6EKSpSksK=K5NT7>M6%mt`hAEtlNaKul4^FdNY2cDgm6A3G6#V(2H~Xl9yN+Fr1!HZThu+4cZ|oAnB7khu%!oE zepMj%&rUSXnn9;2^7(U+6OBGCfJ#*%F6s88zveZ3OWnxtH6xhh8X0CQag7W$e}%m# z`VbUbj3c4T&}MOgDui+ml>c(-Qn49>m1X$NyO+6>gOKe5a#~KF9f%&vrk@BUrDl;B zoj-t+S$sA=dnzh39@1f6d{#JY2<;oRM(na$EEwK}l9KyK-&H608>q?*qgv>IcP<%x z`w8dyXAxSO0W&{!?63YnuWUD9UW#Xgp-1iU!IbkU&s(v}{x%fWO9{*>wAe~PA?;ft zii8FR4W6Z_OC;lBpg2M&<~DB2OHiAZM@}g@Ou%M(lvgvpH0k z-*w~GT&If30&L@qP+n;t+_t|)2wX@r&x4(tMly$M*GME@A>6qSqn8&$(sC(2_+OtaS6)t+v^Vl{RN%iQ@hIMfI&&sMCPb{n>3EoMfR+RVEppDyqbMcu9>r15^_;pneO zygv+|lJe-(1>D`S$-%7foI4Jxv|@waKXf=b!sW{XVQQHk3!0NagVre_^HDn1@tM!I zsbBcNTTG^hH&W-D>a52)QSe>P7gqxL*;KU-*Z4DN^8G7xlQLqt2LoyS?1?yOz;k(? zdB|Uk#s`l`^7)w<-xD#GskZ+|6ov%i9d|n%^{L=<_#Mz3Igd^{YRq0Y*i(&ef&j}R zgmPA{X4q@KE952_FOX)3CXZx8M>!HF(NI|MT>f7#cdWcyf)C4L5NTr?j1Y`PUH z)#Vs@mwy+TJ;jlx`9vdHo)x7HVV=Qnh|{?!%)dPV8Ra~L2Tw+6g+KKb7_t2m`-IKz zC*ZTI77Br#+!uKt61(yRE#0b2i~CbvZu(88>3@bie-D)2W$=-wDwh8HNRxMSK1FFk;VI$e}%-#VF)qLqgmYD zF*7sPEN$W~WVy8BOnDj9ry@(*D zc4BM>e+Dy;%_6(626EQ`XXVVfUtsSxC>)POR3&ZoS0 zCeDr0OhbGmGmLj4&z6Vcf=NI2oGikQjZ5H}YDcZDOjuU58O>_gir+!y__ewReIEmH zKroA>ejm%u`3zwft-^`Z{wVzAyoPjWE{w)bLXgK3D!J8&%?j@kl1C@-H>eg%Ejtn7 z=!=YfX#(#HYAp0zGu<8Xn`qzrj1#Fm%dAgF$YW)gXMCdbbM)Df1*?S%GaVqE*$C|^ zt(ZRQ799U2o1OL0X0J!))B5Q{vA8!0#chKK$Vr0TzabcRIiD_b)n=6bFuTK_!9nv@ zT!?Fgai{}6?_4LWs@7*=%RW*1M;Q?+8Ay)f*~6*Nn4}?J%;j{!?6O+F>qGedrLpX|{cN(b zH4qDD^&t0cIaGFSh1M|v{XE@-g*>@N2W6MQWM>f`{pf?ozgKuKf1OlCjAY-YjAWy= zok{)7P_%XMF8zuk3_k{FTRG4UQxoR(YCi2W+lCeT6*z6x196Q&Oj|sijGL;!=Hzfb zX<-DZ5RJx~BJTJao{NBu6A{)PNatxAF|XmB!bLw%;*S*1<>NYFGs73Q!;=KZQq`DV zdK1l!Dk2ezUvO~KAgnXfQ5&y>i-*2YyW9Hg?OP%&Kj?^$0gW)2*$Pi1{vI3&Guy&h zxYI{-sjAg5$Xxr1r>$xb5*D38@>)L=TIxrHCTWT%$2|fOETl zbI><-B3i|s(ooJC2TRomTL(^YUaAhC8#=hJ-WS=9R4`!#cS!~|P&%Z9ytCt8w`$Jn zd`d^x86_wlil<8t>9IEwQ-p@qj(l&|Kgh3ag}JLc0v5WNC8ujK>+QL8oV7Ug$0lQs zp~zwnha|WriDJf%e5#eI#aix(3rsnmB39mtHGYkV^tb1Ifo(z;&In1eSgO{mhJL8-_6 za9tx0x{vs7nUF}t2fQLk9?JYek2*g za47~h6hpx5ybvD1Efy(BU5R1q!2;(z@nu0W}9>&ir%8B&t zaD6tc-$eM!=sIrQ|A!1`zFX#(8+;`;o0aryvq`^msMa5GT%Dbad%{5|G;)8+R}pw$ zEu^dYGZ0sl7W_%QjV!NL{F>SbiJA8BoN`IH)X;z#U5cfPR;puXUIt$C`}qUQPY9RF zA-OBs=%FT6rdnMssL#01J%yccZ06mEMb>z5RGeOrGG;Ls{P<@w6Sy}X5TQD&pGChNTjt42jOnx`Yk$kI zJX1Yd2cA>FV$L7P4Wcs(B@f+kxv@>yvJg=u8@9tuE+Ks>P@VyzmDJYn{f7X3yP)O z5cE*XYzXI5ESLYFMqecH-6#d-%Xog!N^zdgF20{Are3qPm~E%7;L0-(EZ)+F+s+M0 zntTl+_nn1P>DBh~D#Y7$cTNW~Fw}f(@!{@0T{g(y9k|%sP30 zvIgqyM`0~0LoG(|zV4U@RB7RVn8y1mU$^lF{iSzUCKF8R#l%_J_c83i%avqyLJ(YZ zda?3U8NOfLfC+oo(yuxuY)a=PFq^A5qiB%ugM!bNE}4;{$hM@5FpJF} z2`l9up@aeK`1upBY>Y8@?ggF1`#*n<<_eFTJO^4_hdk>JOltP#9fv@H?>}``7WS9k zT3$`^-^F8?h{)pel4+=XF$Tr=D813F$Cfq?CVJXCAyT~wR*PC7KG79zHqndLRq>w2 zJkAJ}4~Mf(3Lf)3vg;CsTXr9LBUeIiOy+wJrRE5dNI4#BRy4>3`-3-Xg{Fuwf=Cft*w z_BKYWy7WHXwq!b5ynZ2d>Hx;dzeBjyQ$l_ZWBTc1m^N0Csj1HpxV0A@Gs<{Vcmu2r zENPa|n91+3p=IjkkaYTk!{)rZ7xe-i(Pv4h%P2Ntp%g1gxJwK*-{1%LMvP7V4fSmc zAz$Z0O?Vde<(3I$k-PCclg~f0yP@0k7*5Sv^U=-wyvalzDC1vU?F1D7Am|92VoDwkD%5#{k zR2+RU24i+G>M>uBeNM?uR9tlfL(G~mbwLZ3%y-4=Co>lH*y*rMvY9l>W(0QIrC@;( zzaPBkj8JzE8NnH$z599Z&v}(V?cyECwsV(LU;|Vx+d(?}j?iYK0kcehN98*;p_;}S zA-;PuHsvGdATr4EKb>@GlQJ8fCQ8y3{U9IKg$F;Xq3VAG*QUzR+-pWGs?diPN6moE z^n9p@^Sy^%Z~0ERr$pXboc(zv#~c^0CzV>k7&4Bta&ybjbcQoRrW>i7oiRJEZcRsy zx8VCb{=oW1ALI_cfRpSAB4Rs=#fwX^pjY1H%KkTKsP9Ma?ccckVLpaxyVBWbj2YYw zX+YQ>Y@SsGUEUcCRe6lOTurh}hUfAn12jx8o@{T7!8%*+=PS&H?>QsL-+M{>WsI10 z=vQIj?hAN$=r0z>x1&{_yX7bO3N%G{S9^FZO;`9!ZtqEe6XX8%!>O=XD2G?elIerF zdd%)?YGTxy8|bp)9pScSRNdih#JR%>7Wq2tN>v7}w;h4)#VNSX`IH?p6cx^$Bx-Fb zl?~Kn>&~wd9Phq^5S}{-2I|qa{wfY@JP-~UD@HhMTHgZ7)C~F`N4Qw7uKJx#^L3MF?+Zo{d&@v`91Nb^2IaoS3V#0gZ=op`7Op~ z1&}TGB$&f4&ZpF@CmW4|;kBn1A$(_mOqV6LrEa4a_`E@>;uu|OVS(oZf3SZ@ABuuQ zU^@B;k)J%84bhik2Wz~^%;q;(c%65^YYOn|*gPm7cc*g;IKSR)NWBvGVnSmjH0N~V zZ6IeOqEra|qQo{h3{vlg1mZ(uAZ9d(JO0^-i!%Ui38hsPhHUAI&q8~z3z(Pum(NVw z;q}N1R&(wMwj3MBJR7GPM;6iOXwmKqR*b z%TG3Ax~U67ueK%xO>MG|E{DsD02Fx!xg6^}@fvFzPuldYeZP`aWTKt`?jP0h1SC!d08!6)W z-Vc!lU3mSW8dk>+p{`Mp_P#e_<38S{7gx-}L6*c3$E1CR1Ur!<%j!h7 zk&xzK)MWR!OHSp2;4(3ZQ>CU<2sr-_ee6c zYG2}N7mk_1{itm&!1sOgpjmN?-sv@B1+R5z)IYx4!>S6_=ezOpxj$qI6-dbxC3f|2 zKRvBT$(kDP5b->_+bcR&(^P+rzfmhqgqY0@}0c;vX?q1IhUPHxBRp$)J&a|Ndd zLWJvd`AnQUE$-~lh1$a`ScebdUs)_HER#vrwr)E99_Lejk0g?t9`SQ{7ecM8k==U$ ziCdNEe4Yu@08ctvI2+A>^5Hy>?_F3OftVGK$&MP%2*t~?KW)2+)9B||Ue}AuVx?I9 zZ!IiEchY(GCakn&A3eu&`Wnj;NPh3dmX_z(KWZQGJ1@(=e&vi1&-br6h9mPwKjMxQ zK>q6-9G`xND$h1%&nD|ow~704{X-R!C3r@c`v`JxWyvb;PtkeTPfOw{F>e2WvPpyZ z)|7?JvwG-%A4U_oAE0(vv~c<=TYQzQ$F6PdaQC~5w>6G}^C^56)v_w8IIEfLIGo6P zxPzFu=sRL>jY6UOcRHz_?^s&0FLA)x8AQ4n=a=*6FzqJn?wTk1B=Q|gk>BYhfa@R>sCv$**OnLq;dpgL{7t?=* zQAyT(FJf1~^BMq%y~zTbyuI6DIq zF@CU_G*7Ce-{+Vb<|Tj2>=L#9>!n&#;1W33>ONvOLrTWHlyMcyZq_xycsxx;6WvD}X|Ll?80BWSOT0gKxfBAjG< z1-`BI@ZH)DC;7W5Uv^YrBh49-@8z`PT00?$LTK~9<$ZbIu+Cv5bfUh~#HHMyVqcr^ zP0s~VHqEHlYKGAUXB^DEkXXW5MxQGwoSBiud57;{+&PiAJrSwOO(cIw6%EoD$6jQ5 z3T}&gVMu>F7Mj*W^wA}hOnNUAa6V<3?<;!NTOX%aWOFC@AS(Cpbp3WBv79vtF#C@pzphvY1aQ}1DZMs5a9^^k4;G|tYUa5p5H1-}jyM8!Z zXDG{LtPc^79sC)D_2QO63Bs|8=VFJb`(hLJY2FUHWV$7ihnIq0?L~fIFr-&)A)yz! z!zMw3Wt@9VR{2H1e(V4=?D7$iHWOEyz36!E5sDgAqTci%=G#>x{dE_<9QVUA4M}p$ zNQK>++C!!PrI3yCAK`F$5OXqqU|x|n%J@RgeE!~-eS9h`>9_(>?oZhi&<1a7Puz0Y zCWzgm$u4%3(JdQ0NclI;X}#vXq7C1$(pDPn8X2@ni+jr^q$Olebm0yRzHcw12@1tG zxOX`&F`VzY+Oj%@&N?j%ov+`~#GjvLV*(EF@~F0THC?=M9Bba}DQLIzLR@t_HhlYw zjqVrtp1jY(pd3S1cPo@;-7rAymu$4m7{togG2G{wKx~2rY13UL_T5;8%>LjHyVZQR z-KRds$D}jFS;ws>WRd$@ z)a)6+m__;MUp5n&nO?Lu*N7>IjiswUA4W%MHFi69fh^@rtC<8j-KWf?zjV=KpVG)9 z_m7Zq=PvWwAE>p{M$wgbG=S&wLx=hZ8;9D#U}^(u`r0r+JRvfEgTN4)?7^%Oy6>JOi5@ zeW=a{BNn1BM_mh#KslxwiJ@IM-~SK;+r&uSa257Iyo){=l}Uy@{RrJ6&gyV3|DUK9 zYTDn?1Kg*zJMxxLXPq51UNqoRZySCbxx<~=s|EKTYcgGBzBl*`-(4F^A-j|_qey{- zyA&RN%cQAY++id6d_k(ZD}GAy{j1_lD5!PfyMZbbOG5P6(T_>=%*HWDf1HXl!TfAv zlz^iKwZ!;-9o6#GV6TQf7JNOypFu-AR&4zX)xGDD6qG5{;dl2mxtDYpzr$$E_zAc1 zgV<*tgZ4XdM0%|Vd-zY0nYwC{&ogMhqS%>A9&mnwPzHq9AA)Ar$f||M;<8#SR?B=uH65a#)Y86XP z1dFhLs){W3gC1FVE&%C#^6PiH5_5;_=B(938g$N>)ob6Rbl)O)SNz5pC(ft*3`54X zJ47s2idl({VrMU0BtJx6!uJ+;d++^&`j!>Qy?ly_@}6)_(JDGoY$Fc7DMREz{+q1$ z3?i-OA?bUi^o|J@;waM!rkntTdf@<{0+`aS!&; zE-X}jh{oy;!TqNy%&x7SipXV?wH0wVa)o!~q<=tq-#Cc(MAOC*2JEZxbz#{P?oWB% z!1)sHH2dWNo3|4LLqBUWiQFQ3ZQ~$0Xu$AyI`8J`rl7Au5{u-s=xuc!)>5fw_Nvzv zr@yvvX9f4YiaQ}OPfTdQca3c*O{5lE$AW~XL7FqaZ&$}-!OtoZ_3SUTzNpTYetIK# z_uL1KsU0}>x(?!t&S8DyFX7Ta&MRIIreZ%$(7H7T-@gx_r|La=Y+^~go+!I^OM$iJ z8Ireu0(f_-8&}*aVW71OspI(EvdxHnwsNK?_nG0Fej%JAxr_2*7>-`QMfA^0G1ei& zqD-%larQ4^l+uSIdYlomT#n+XQ`ED=n3Wwhr;%$nVOe7t%$N4!;o2a0ikg$lL*?0? z3By?G&le=UaRsumV%}HX?l;0r+{tSA@h+2Gks<#c|{m%X3uw{HNw`l6*tmvLv5FY;NV5xhtDdc=LtLy%c1`eaQHel_iG77sUCYC98VwL zR>T(hbX?*tu9}uF*e72`F0F2$!7bcbAo4}9cE>&JRqcfRi#ps$I?cUg|7++>9BRz| zFy1;fREVy$Fw$IYlC{Xvbk9@P>`J0$#?mxK5$1=Gwuu%d%P5o<46;N~DbhVh_GQ#n zX+euh3tdU6{Jwv~`=0kb=X^iU=c$qF=39t|%2b~8?-=;0Dxhul4cgh)p*HLW+g7P6 z7LS&Qp3Qdb)YW7hn%|9$G34%8<&EG%2R?!B-BziE^A=ME-OdW^)$fIV)T~THi!U8v4!1z-==sHn_ydP#`;n5%-OXn=Lh*{j+*%S41YM?gsD^4_~LQ?w^ zdra$K=qe3y&H5tqc%F%riavaaeu)!H#^dtV6Fm2Smg0(|8XrD601ayz@wT`VVw_O2WcG3`r=}%BjIq&VUx8dVg%}ge?aC2Kzp|U~9f{l*ht!gJ` zu5E%mE)Y&%>*Ve>mg1Q*h1*UTi_ zg_Y#iUs|I;;+%147@x#_DcgL|PL+>+7l4exjqvg8#G>Kx==-Hqwld5_%)HUgO?1lH zt|D><(A`TsF+x)Z8e=oLH6ALZq9Djqu3Z}fcDfacb4r@)#p2S48s`-*X2L76j63+L zq4n}zl+jsN!=VWC+BIPNeJO7xkC090N$2y=Vlc~93AH<|xMm-Q`HPv{$6G3*@89O; zJ%;2vegdWMH$47)3(>Ka4C_DeGkWw4%8Fz*F2@j)@fq6WPch5djH6i{@|>S7Md-B@ zekf`z4l7HroZdN|t}My}XRr=6b>TWuBF^dBGi{X=uz+r8Sk|J~)eBekX7Zxx)`I1Q z@Pqas=Uye62K6GyCLOkVkt|?=t~j$%S3J5M#uoHX#}Z`^_S(~2-ozDQS|NNEF{7%l zWc>RrD^dNb24U*m$nHx)Udt3#UuZymDC%P9%*$;5fh_#sLjQv|3RwJR2m4dWym_#t zDE0X!Z+N(gIshBdN_@&W-FR%Qc`ozqH5NXxANWIq3YL(33obh3RPuZZ+hs;LelU;M z(RVxDcCLJCMJU{cwIS$`5}Q`WBHXOnx%d-x$80F&Q#>?~>{x^%;uZUb79r-E24n`M zyvx8${I|W-Id^R=Mg=L!aoCDEhGAGz7B{v5hJu*buV|D?FyeHVzB!6qQWj6 zTFMAkMEy#`%XGxOqmk_LI&#>I>ZJ@`B{ulG;H_~8x6iZ^UL&XTF;QMv;aUsNIAULt zQs8&nf#qZw2+3+S;re$5duetZ`r5?XgeXutzz()AlDWz*3t^JiA@4H`gqcGVE|2O& zRn#%meD_cmr*0zJ{m9$nR>kUnB9{{N`&=}93J1?&SVlcmx(lV^H@BJcxTr83C~d`? zeZ;(}$HJrQj&q^ZOf28`lAphSrd}L;9SXV`9-v ze2TQA73S`txcYH{{51V%oHTCoydEQ1xIe`^n!|kR&d0L5W$ew0b{^nGjL^$s+2&#K zxVW_w6UH^-{ha_z@>Jm#sg@$$_!O_lIJC7W;5x4l3yrhLA$5rb*=vaTD-6UQ@9FH; zh*Y?t8~5XCXpiTK5QPi(?6VSje!+bI9`dIUr!`g4LwWcMs2>o@^o6b{DbW%7f*7Im z>EI)Kv1W87Myz4zYYOFZEoW^(vcrulz?XeVZr?tu5*9RheP!raj_>7d#{~-QSp-hL^%s*zd@$y$y zY|A*}1w&|`e)0((I2od#yMPxCk_y`fNBR5xVK7u{!bDrKn4c>nokB7N!?=VQYUU~Hxm#ammE8V~~Wn?CY5j21g; zZt`P#Cg@6dijqvq6Ryvv?x8YfU999E+{xuM@3rizOFTONraq$A)T!Yafa#hV{EM!Y z=-POa|9xm2!d+it$9{m@t<= zSY#zCZG-vJ-LtTDS{3!Vk-K9JF+!VyneG`~F|w||m}4Hr3XWgIdAi5=wY~xmB#hig zVO)_wcXmgnaB~N5RFbRi!o+Tro=?WzJ>yyKIEe_+QxmM`I`g`69k-NysHZ+a&xy8Z z7?8%Z-&=@+jJNVTL0hnKXA=evB|p`ff8a9bw#?1QRFqTS=J@${|CapK~%3U;ImWu&EYu1MeY?dX+rP(JqjFGnBp zwAR97RW}knlTmrYhHdC45jhG~@v~|Ud-C-}=+9#?`WWjkl=>fM%HykCC~7yoWi3T*W~u>ikUQ zK0)Ca5Y>hSzqLbgJQ~gY9Gvw6Mv3Sx#r$iO7I``;J5WuI#9IQ{V^oloUC9qGA~qt? zK=wj;0J}aYvBtC&U(5HxJSkNExK}C$C+6_%OjD#Td4@z<2a8qmu`TQcdzSTy557aJ z+`A@OGW)s@Ev-Bd)rM!0;hA(V&arDuHoOE=a|M>O`*17 zh=?qn#nwzqLp<%_XN0|l-D(e*URc1xmsyL2nt$?L^|R5FS%vr&J(!Vj9<3jDvY6!q zgpq_imvdqmB$VxNCWnm^t%K^H;5=y`-|l85B=073JAWU9ji|%>M|2mJathZ=q|A_tX~2@TWiW|pW(5-mcr(KrMx<68+?PBU>id2RF|XZGRlxe zP982C)mnJ$gF1Go<2Ib>-U9Tkq+5*y&3 z`Ufno_T#(Hkw-fwp68vN1b_2Vw8r+KM{y1Qug)^FJ(^-NxjWLwxUuz$G_VD9ul9ht zoBiFft7`%8IAtX~1_bi)-g9xqqZ*TL^uXHWJf1(?!P4sWL>lpmew&h*!L&2@P^RgU IH0?hA4?_nH+yDRo diff --git a/test/torchaudio_unittest/assets/kaldi/resample-16000-2000.ark b/test/torchaudio_unittest/assets/kaldi/resample-16000-2000.ark deleted file mode 100644 index 669b7b35788151f9cd2f2b6553d75917e23e0e92..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 4021 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 X1}x)yYizJ?>2o~yQgOVh`3V05d;D|e diff --git a/test/torchaudio_unittest/assets/kaldi/resample-16000-22000.ark b/test/torchaudio_unittest/assets/kaldi/resample-16000-22000.ark deleted file mode 100644 index 7c96057cec09c0e54d17b8885f6546926ec0b8c3..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 44021 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�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 UhQ3;hKJ!0d>YF}R-K(SUe`^^_z5oCK diff --git a/test/torchaudio_unittest/assets/kaldi/resample-16000-23000.ark b/test/torchaudio_unittest/assets/kaldi/resample-16000-23000.ark deleted file mode 100644 index 0991b3d5ba0e9bfc90cbde1accc3baba110f78f0..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 46021 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

!Nxx+DfLrx`U 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 X!P0n=>~;e$uGPb9?g(?GCwK9G^PC9k diff --git a/test/torchaudio_unittest/assets/kaldi/resample-16000-25000.ark b/test/torchaudio_unittest/assets/kaldi/resample-16000-25000.ark deleted file mode 100644 index 81d096eb4c641b2784b05b2a7a0f7d633d90e6b2..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 50021 zcmWifcRZEv8^;wPNytjb9;c=G)lxb4M_bz3+DltYDoLUwq=k?qNm5j@l5^h@g^+}h z?7g>he$VfJub0<(p69;q>w16Q*U<|*5AD?!v#?yHEip_?OiUu*R7`AZf)J`rT_~P+ z7S^ZD3EwlD4h)~nCVz~hYD00vX3Qg)q7G?VBE;TAdL!`8tR0b82XJ(}0MiuB;e6g*An&ij_Ak|78@webv6_gaJqfU!)`#WI9Z#NRHXIw=J^ywHEX0GVscN2*SZ81cp8VP5eV%KMSB{0mjVnc^{R% zCQo+!=YSTwLMRLqvt0P@AO5)B!O}-}2;U-`9+aQRrY`+XrSp79D!g#Wyb^Z5MKJC8 zg#$a!qaa9zh~FHbZ>)`3h`k>*n){cy?FfO_o@S)%9fI%742YJj!8b>b&oj4;VO~x; ztnlta8riCf1^F>>XzapZXD{56<1xX@1RJA9QoAAz=3lSOOk*wysw);E7?{80M`uU)Rg=)EpJi;Tt zI>^h3;8>7@(}yjtT{u4bElzz`LQvUqdRbMM+4ALB?Y`j_l_%HZ z*zHV=2^&Jj?I!f~1mod^BC_L6AiYpy%r?I2p~XvqGlj$rEc zPx#Gq4`D=NF3xI*VC-KDr+p7lQuKz1d&JXcn|W-DWCh(BvzIg!-9VLn8MKteET1g> zgTXH@SgyL9=$F+}JqsQ)*L_1ZS0xjlWItGssE1mu5at_l(Ce}rGmZD~gUzMcL~#RV z>S0g$R1zK*kq{|#V1Iu<9DaSqvDmqIe=%4f`%ab7edF1Fg?7R32UB2GnTV7#eP~|O zh0|x>AZyZCe3G=LR}Sj3NRQDh_S;U269yacd;B+C_&bFAqnlv0A{cHr3y5o8Fx@%R zgpJGUqEqxWNKxV?`0W0TrQG}4Qe1(-?Aus=*`551%A;4xc&t6_E4}gW5jhy^js07y zP;pO$xy=PwrFsUKJIKHCOGx)i7_(N7d(`k*4LLjb6gKV6NMAmLaT)1|SFwU=*7ekP z59C?x4{fH=Fq5{B@wmM39X3AdM$@uhq$ka|tu!G)F{Gr6dShP0}MH58WJ+&5E&+cRMp(t|7 zC6R7$;IUo8GJ5{rVRAmf4Ow|*_&Y(&vLvzBM5?1^7;ebpRcxlntbw~kmx*Monr7qJ>l4Z8Wk1dY3 zZo<-_Z@8%^#A}~M#QO%}re+>lqxF>L?loaUGM#jAtu8sV_6j}@{6@E=nB})~6>zEd zz)J^LaxUj59r>EaYCnIWTPz-vtLJ<$scGPW=jUuL)9vGEYLPff@2%`4&5{3capu>!jeZML#%DjlVuiSv2y@V=)TYubCT zv^fr`+WN?@R-^G(wOD-FSXNv)PoO&ysJ+CHwP6tardHGzKgae9eT1*(PF-IZvTcdt z>}^Q`f6F>Myco>GzBwY?ep!S29rxfj6hZ79lIi?-9y^o#hsr!XK{A8gVPsK`CL=LR z>nSC;W_%5QcP}8ij~nTjMiVwMCz9sQW5j7j05GBf?6eS`YqF8pvjg^Sv-q=rj%587 z`YfsEFddpDgJUtTurRm-67TwvXOn`Rf&bz7r8t4!O*LlatIn?Y7YPo=PebX>WDFJe zp*^}2Hrml}_8EhjH#gJC8}*oN?VDioUF22vJ z#;8CM#6o@|ckC&2y!y+Zo-4+trWvsxhrMWjUK8mLdWKW?TF}}#2<0bVP~o{8@}wm7 z!DvM${(b`UkeEoNtF*A>*n1SM=>ZAp!HwB*xOPPs$y>DO;9o5^v|}vu{iG+D@ZAzI zi_@@h&mdMsv_ebeIqpsACRzTs=-l6itaxxZJLmC*pC)|_KCb!D+$Vz8gc@YeyN9s# z&q@5A6uPj4$3BG>(-)yd#q7U$Y&pff{_7%Q7rYsK>H4@1t9Oj)Jsv6n+(Uz~ym2b_ace z#?UO}kD`KOisP7yf;y{=%occUpMe&!Pf(rG4?e#W=~rLF=GSPvk=#L7AMx&Tl zbf?ARds}fm`a6an7vjQ?1{icaMo8f|B3|>H-nwYQ?ntyz<>;y8;KZx=u%H-q4I;=s z{fprBw{W@U3fU0$mxmwc-6AXtQ;!F((@cLI_$pWo*(jIDGx zVydG&>ASgY#BXC5+6POje3m_Q1b5q z???}lPkzApW^L5Y(WkYuC$P6a6`A288G*dzQm!9K!-dO(__?7Kv75rsncGg3t8UYk z(~a2Y;lr6QJddxObR3h1@-aI|1gCq|7@2%Qb6hkJks0jUn`Jsc{{n3JVkN zqho6_JP%AqrO9uBu9Z4__(_dTuZ&^Vx{2EUo=?_&cE)g00t*>2 z%h*fh_)+YRB`T-LKAk_*kn&jCn`GMZ=><_Qx(8-mgFDV5v^L~%XUq;BPD%WTo#JfE zUqg1t-<`fY)=L(>c#gSstw@?Yh_XtCKmzPgn>6lbCh#b2XEFbm^*7q97q}4uj zdV>)&HWp(pGWGnTRj2Wx|0iDjT~GYi7EJB?^J5n^%dH%xqQ1D|D2 zEKaYJWmz-z*to?T=(7-cxTQzqU|c88mGpt7C*hN`DXN7Pg3e}jHf5R`i#QN1P--;8 z)8rJ`NerNDeg_;^y+T-;G}gx+rSo3sGruV#*{BS{U%t{7>F=|#>ADbW^XoC}l0RG~ z3rKH$6phX|VHFP>XjX#-(F(YRa;{f$9WQ2?UQ~weaqc+%>Iiu!T}IWp_w{#wB2ATk zMYMzN!{bK{E^ig#{DnNY%{YSNGvD%$ER|rb=M34y{Ws{+o&i$7EgZ2++Mqjp5YBTM zwxsg0@#1oUor4lvET+ZYM=H|==MCU%`w^dXdZF>R8xv-{LxijbO3%)u`n$DRv8)2K z+3B8YvwIZ`)6$_~GK4$AW=vWeigS{+SR6@G`Nw7bGMORR{^^suBIpd#><*Zu#eRu@flq-ooB*E z`#qrpKYo&la>0nGX~aq`Atp(F{!4<}zJ2^OQB!+M|fhQ*TgY(uJ*8 z`!Iic5=yeBpyE}NK<)B)X6B*FcH}-26nM`?_36(DG9Ey*s2#_gBXMSq6lVLLrl(8w znc*dA7NEbAUsSaVjazacdL+c69rcjT@WT?nPeidgnvRy|vAmEvs_nIuxVpGt?Swx# zWhiFpx3LU|E#0tr$3F6{shoyH@Ywpt@$}u6XyU)_0j6!L#R+{8wsq$s?7$(I#D(#x z)(G}%njyR1>_YXAi^v6)7bv~ohRtmQNIgj*J;MTu{<{T{qm-HKD@_(-JBH3zGeX+< zc&~kMwa+^cPiRm!Y8S?Dl(gmrC+N;sN=_`g^9KtQ{W(aRRg=2ap z@hrGcb2k~YM{|d$@Y67I;m%pin)D0p??vE^sKP-_Z$v~rAf_8LX-6E7U3bl;@_HU* zg{3E6ZTyEPl_K2L|BWRl9U+&cO3ajdsDq>l`(zqKv&DXs$ckX3Old-I+Yr>QW};td z1N3DTEXu!)W}e%1*|qW&)MJ$rj!3?R`qeI+UC@WV8;O`8GZ}@Iy@JNt@oc!PDoY)B zB)r-o{rwIbd7u49h>AJlO@?%#i2T3bBM<} zL*wXz(ioDW@DT2`wP@=QV#=vpC>9=oFY&ecPD4w1OnN~M^9%Vb?CKygoLAUL^?B;9^J^zhWD#zeB64H zG|Ls8>ZQoh5VJIPD#g8Pt~h&sGm)5CMWq(;n97Iu)X?DrIhXQ~V-|JTRw2Z}^dES# za6gvqyUkB?lVlRifIa%}3RTJ(4#(ICuK#LBYWx6RjuxP(+8k%^xCshPRM?7V8ti6) z1PyoMq4{tE#7Fj_EujnN*2ZA)jS4bn@#(g59ab48$DD??r+5Xgg_cJKn&XEM-`<38 zWlyl=ZYfb2^ru__pUO=fLx|r6Y~-H5PqGNoDwQbkyaT5kFS5fhn;KU0m|$EM zb+Gm!Pb9ryIJOdLT)$D@@Czp=UO=b#D01#ZKfU+>nz41utG(qSmDQX(1!QAvz z*wVRI1&wPLVriHFwbutQUypk(DoRc=`~lcfTVhrXMJ-aNHvI9}V5Tm8cK7LO;F~OGk@YF4ic8-^=TWpSX@#a!f62 zBzIT8jHPNn;>lQ_M=(#WgMFb89=bnp;^SU4Xk6hxQ2}3r_1Qq0_0pK7J?N!31C&X<)sT?jSz`PbKp2- z4;rNo@N<7jG2QhBtT5l6ijR;)_tHpYeriX++yT_peTL2Ad9bK^ELh>C%4X~v&)So^ z1oup*U|T>UP6hR0xMml&RJ?)5wz1f(XGL=ybeZAJ(d^Fj|16djZ@|;OOw9j0gz$Au z__8V(sbdSt{!hVl)Nf-JT+>Z2Ul~t&Ivmk{_%{}D=cc!<0vmNaks)#?=c96|kK9D2 z7yFf-y77?kqrIWiQwgVEB24HiK#KPnq;D4Sk1i6@siTcq_?r84Nq;pt5b+exN420* zeF(NwzT&c_6;h{dPaXeMp6yA~W)%UmX=jr<?!EYQ`6IY#5AUBVQUxDP z7Tcr5>>sZeh>|TZrI_OU*g^POwBhSeILb7KNZ;w}biBVI8@Ww_xjcTsHwr$Cn}fNC z*dW4k-CCG7--qeM*W|)b0?p&@rO`g+)NJ%2!awT`Pm3Rv>5Of-~a!&PyA$(=|yiIo7-AS z=MNqy_Ve74zo{G&(qfiMjwP66a}Dw57m}VCjnr3y>m%)6(Y30SOp*`4$K-mXrwXCI zFdOfacS81}8Gp&4k?gOFKD+qj2pxNSBp%*>g@gAxP;|c^lj2fPmhvC`F2x8QhN&^T z?dmLhQn}#ogK0P{k&NcLK4c|yLV86s-c6H7g#2dO(5K6y_sX&q=@bh`_015PeaFMW zA>m{|B$JU9|TV4wuXWnDMs2)tI>_IEyU}LI>E#Ech zf($M8-?g!9-9w(>+&)W;=w>+MJ;<^9R(PL%j$YSpV&HL;c1attT;Xu0-kHiTNjeJm z_4(*rCPMPj8rTw!silMy!}Te&;3AJ*$}gdYeP@WG`c3GhmLpd|%+jZ%7@c>Vk#*aQ zguZQ}h1~fvoAZ)xJpF~-EDpdWtp;p-EJX5`EM#YFhn$ff--9Q^PEOTllhhATci&M+ zB~e(?-hto){g^9}0u}AqFw*}du$wrJbxNo+SGPRDXoDHJmY9rAxqd8n>4cHXYe+qm zgI4QyN>6b7z<(4|PinEqkJ^IrPv0?pr4V)14Nx)*#6E}b#Gm(^CcZV{ICCpqB{!LL zt6#gf)7g-nN#Ql))r+* zWm_g7S?vR4YeDJIN2Kb*!UW{{l^9^*x11BPuB zV#lH^WR2T~yURxLiP|VO^MxMkTDzOt8IH!!_9(2M*NI6B`*CCGC#?6K3AO8)g6~e_ z*xD!K*nO{bfqv3Vq&j^<>ZE>Ha({cbEDD#N$-+8yH@%pu$KuLmSmTe;{P4HiFlJ5` ztWF7`ai#$;E@vP%;tI~?HPY@Qxiud^#(mamj-QW4mn})Nj4Mr?!l?T1@w1b2c zhe6k@6<4D;25O%M#UD$McurL?s6Cdw6>71tt2$KfsScu&K49;c9^5hD7|rMp7#lW$ zXTGuy$uFNs75cjbX%=-WtZl@Q1Hi ze1c;~Ke6DX2sckwBPRPUTE0Iae}n?+UC3jRw+pG#h^s`q_!c~z|Dsz<%(C=*5%!lk zVgIs8WZRB5`r@_;TU#1NcQ|H|=y`!Sq|=BCE6H5HG=t-U1%jdeact&`reo0MxOjvGO z6K!^#OOzfv!&|Nd_FT^-6qKX1%pDf<&XC**e`x$o9@8%QME9J0L52?BL%^XLNZNDX zuu?u$0*=B$J%xX{XE-~dW5gn>-03Ze9wHy{9HYEiVd}_n=1z{$lmq!XlLTFCEYrTF z#X7Sz==O(P?X!-1nh~ z#AD-B3#fVbHRAco0|puu@Q~;7HWl^*4ezX)|P{r9km(KlW_xz*?_Y*vT7-xnu08H`Qmh<43aK{CRvWBU|{a z&xY_b_rAEhb4`{%rdJAxnMxF`C^TV}T8*^OYB90edJXShmY`rr1aW>jBz4`v_dG^4 zhL_RP-1(Bbltka3jwCZJ@1x>#4N6Xnu=z+HwvV)f`^Ol5U6DAGDllYMj@+Q)i~EWE zj&NAXwBd;EAku9a1~m!hc322XuPL##-{O-QP`rR6E z88d?(GuLL{Cn~TFPyABV+g4)l=X8Lpt>?G4V9nN01kI@`KJ4^hCBbPt&q$aY2)_fYEa)YeAbQ`xGSD<20gfm=^B6Xqv(?&<8>F z^ze-(BxRZl3TFL5yGVrSxH2r*=Z1#X{p6uTIsJ5p$DEEQ(1W*LlNmD~VBE-BR38*! zK}Rm`>m7zh`g8uWixMpDrXjmzbDd6`FC=k2;V3!ShT-i4a809lKg$BsXKfTXXeu*9 zj;Wo=RG^MyjBqaWBj#W2MGBXb`#q0ET&6l|uKq{eZfLWhPR8r;ZmRpC_Kh%H{%?w}|kej$<@ez0uVCfCNv^ zpp)BqtSKy)W`4a%?5296W8y#DEfm4$=x-eMaD?YRbrNRXLp?H$*^U#zG}5<_6gvdt z-r6P<6?1+;R3^qnZ$P=+1Pj59(aa)1mkkE2q=`Xektz2U&4yk0>fQ(Ydx=O5n~aA6 z-GYcW<5`%sDl2##AP7&N2fd2VIBPqAp%?9VtsIGwStIZ&;0%@DVZdgTOEJT`V|+sP z;AB7!B(j8vA72kcbw7lqCy{`}w=`Lw$0RP*(&pn<-}UY1Ytg{0fJiL)dw=8HK$eh(!fazW$J=xEQnFy#rKP zNs{nYJg!RRR z7~bdr(-TT0yrh@TNi}9K!X8t5K{0t~@dT~GP1v75gv{0qxaqBjY4FX(e^<(}EylXc ze9RKsVx$a}gtv$f>VoxzKKS${KumlRrU}HTXtM@$KdizA@B0Yq_b-6JKNT}?4Pg4J zc6{9N5*N%R5IfV625d86Q?#Yn@`cX)()zuqIPwDxF+vnQsDr=VBb-_kPhuNmsqI`I zdwRQ?4yvpt5yjVWP^lCj^~EgLTq?!%YFGHo-9p%mO8WQ#HYI_Nb84(2pwJr zg|Q+;HvT~5z5Se%QSHX9r7>`EQ000u3p(ST4ja@N!^)LkrKr}f!TNI< z=;pkqQMFBwT^@p5@iJ1R?oVa7=X-E;KUEwWMP9pJz@`a>cvLKcP`eTze%ygqjW;o> z%%XS0xXe{On@V_llZ3cC*#BQ8PP`Lg(aW;~t{!@p~fs`#n8#oMUBYDyiMK&E(8yS8TpoiZ47d%Ywl_C{lEV zZOb~6w78lot>>}k=do0B<40n7>Jh}e>k#on2=Bu`(9yCNFV(K|15Blu`D%_?=Q+}z z*%J89dx_`g+wuMA06b$-!R{`=tkvFv{g+kP+5H;q`RHL(CT}8kh!T+8-;3;TU66=* ziy23hkz~7sZtc-wZdc`)eAm^*xgG1k8Z%H(ID}IFCU_ouf)Ad>q+R|ob?!1|b4z>a z=!;{CTaN>ho)uzSqX^2G|1i496GaktNLWe^4Q}Q!`}S|NbpJh~dC3d(UL|~TMYtdI z3$mT(AoP+Xt?>iY%GsDL7d)hUhE~J;)xjc$~o2$uE&nUB=ZhL_}TZEnc0w{7!7}agK z|Lz66hQ#1A<{EwYn`2uaMld>S7AP~{rm-2i7Go@ zGM@Ddx&-oMG9HH{V(@4mG?#RtS>i1c+QxF0=1S`DNtdzk(aa@ayv0|)4Y0hK341Xi zvgSA8esD07xcg<;*C2YJ&X_%z)>=sj;0@!hN;s5?;4)YMpDkyxeT5jgK7WYH+8Q%*?LIBLP(_5%Px13r zGp4N=f~L(^oO*19*k*oe;dOcT;VZ|~^3148k~)U@#v(MN8$WjSBC_lw{CW-1TqRE} z-e|JBO3G}_mMwxv3k$4xO<`6yfPT+5Sk#AebBU1XZN5&I?&Y%23<>5X9?stye+WHd zc`)G^%}k|QSX({7*1xZb+vo)P=pBzauP&#FHT#I|5jRlpGH$jKvn=Mayiyw%TxCnh zN9TH~!Fe=pKceaW=_zDslOOgw*F*7!5aqLS5G=MEUnDp4HSbC@%OQQXB;q8Uyi*E~ zK1E_gM>{NMa*TE**B8y33;7w(1r{Gw+2iHo+1163g1%`}v0!ErcE|SNeQPHqcD;e| zFh%^=Wlf8lI8UubmYw+ToW&o@P55BS^=G4n_|e*ke>4c5K|e{3WeDx$GB=OFE-H6c zo7fLs!v4D7U^QIEz$##9cN>lBT*m5~PtCaVwPi^^O?;@|??yuULJ{@2 z1ZE4e_M`IZ6butErDu?Ga^sT zBP&Xps3GU7s98qR)RAAv+#3NXo6vxehe8zOWug4m4me!W=PSM)$u3{iXRo6U&?Sj7 zs4|bjaE^i2ME1jVQVPhq+4!cKAec0$#ts;$v!du)Kz~^xeXtV^_(+ONDe$dLp~wBcRc4Pss4hyU;eTMqa20pU(b- zvcyTuYWTyK+&hekZ#QBcjdy6Cb}MoI_zW%5tq?vP#MRRr1O2!R%6+Y=^6M0tG{@95 zY>jE&jR`1gcn^!IJ=j~+gWb^|U^7ye)}l_n*GHwE;p|6D+bNKirlHQ$PeEZ+MQ^^qK~|w7y7@Fg)1LJ_Id-X zZwn#N%7VT4cHEDY1IJWW6cY)^hnegL%LgU7Ml#J~}DDO3n&K?bEo85HTEj_lYScX|28Oe_?*b0Y* zS=eJHgf8b57G8Y}zYUqBs5hJ*eq_Sz`&;OU4bw@|ldIT5is8$-$8_9Z%-6bw9fcQ( z{*)rh|Horp>Z$ZeRw$X|;S04)jxTaE|4hy+yuRc(4A1h(c<6sYY55?mvRiO|aTvN%TZv1YC(XZP#K?(ZY(iuK zf5W>In7!mDx;duS&vDw{19wq2@+m1app<`+$7VnIO)uPbBKg;ELFf5jZUz#;PmS|H z^{ztFZZi3p(MnVNP1t?6=XBPV?3U{83f@#TqS|ZKm6^CTl_*1(4{XW~dJ~|5$c0#OQ*#Ohu0eDgTh2-eHr0Gp2 zY+h>+Lb|Aj7`J&YnE8Kd!nF% zKbB4Sr^R+$)1=8&x+vWghna7BU^A}=h3C1mW}$_Cm5KD;zX`0dL4o<`|4J1bzXF?l zzTm0s5PE|+w{#tsU)VR1h&V6Won^$F>%W4$;}qn-{lwY3BB*dRV5!Il7ovlR zR|TU3kv!&e>=(U|aE&Zj?turg75FMAW@)>p2(H_mP;=Xe6!^DOH8&IH)fGzZHs=sw zdmtt)Z$yx(5Yu$Oc2)}GX6`_&Yf#{x867ojAv3d0Zh;N+$Na{l)h+Vq=qOSb%^+mc+#)&Fke$B_zjtB6@X zFZs>&)>n`;U5Ci5>7?;HO;~t(EM>iqh>qCndeX^`0 zU6=JMuBVf76mYXJ8po8o(2&rF6Wf!ZG}088`fCMe700tNQ`MNRPPjmA`W)=H{EY09 ze!N}Uf$4>j5MLmTa*hiC$|g6m0Vul7&s-xTMzxml=bI6;KGI`6&Ck zL9jbTiOGN0WEx6iY3C6`9KZPyRSvy4cBUJdaEReDJgq9ob9uhC z&Lgrm<10PR-NCInxpdk?cj6}Q3H#~_m~s6)f8}rB@FjFOj3-O{yQw6{K*ghi>1nfH zByMXkZY*!Yv+yA-Rr&_I)(tRQLoBMEk7h-Sb=jW%t0~<#7G?rZFsnj7#;cU5&K#uke|~<;F41*fH`c3d8?#yze1R9%0Ow z3^)6&8bRC_pTm3mU$Et7$iq>UINa_9*}3-!waKJD<0i6Yi+<1}`nQQeg(u3n-L+yV zG0X0zLhN305s@NgLPqw|XBEb5i(4T5c&wOwZRGrqs3si$Fa&d(OsrL3kE83G7W<5m zW9^f4*{ie5Xn2PbWE|eYf%AaQ?e4>f_5{SmOu|ZeF>2i~o@Gj_vd%mo!R(Lo5$m0b z)cpg9KhchX2QQ&>O#)vMFHk{%0edbh#pKHz`Eqaf!m=|5h9V(Cg6r_%^&=>j$CLTX zW9dgl9=mE@LvNg1OTPPG$9&FH+sb+I?e(S5?RCYGquYqASS2;E;hcv2543yNJF?UH zA=(OSamq}DIrTr#XMF$*o4om`gj#Ky+DJh$4OINX&x##uTWd856+U^2zH3Uk9<`~-(Ex$eRP=QsWEI(Tvy7S zwQIokWnj1c5cDmYad}<{>{&UvpX5jLLycLUcRyWeJBlQII1gLlFTCY;ohJ7GgR7bs zgqwZHqzB*Wa@mP&Mn@J+Uh74khTOrPhJX0Qc{En13Ss~80xF}&klW~|G8c?l$FTrv zc)FAbQ=Y&_x*4n8hHyPL0|6h_Lah2o^41JFww&|mZszi7ySEB%E{Q?Y^DdCdeNg3? z+Tbr9igiZN-S!&HWWNgAzRyh{6=n`o6#@Dq2Oy=~4!hzAKCUUTqYtQE&;77eHeVz z1vSB2ELg4rtw>Ay_md8D%9dl=Mq3sqj9G_j@l1HTbFBYY6Jmp(VBVV&vO^F+*JpD~ zO|FkN$SaUpNe;Mvun-GJidm*T|A)2}ci=ni4%tYvsi>F7WaoUR@x^zEz}gEn7b@|a z^AB~~eqp85dAx2INp>_3P>cPXSDN#P$|w9KPEH}1v$GkCx&M2)`YWbST?5-av7gm1 zjbU$Z>o9dObNX0L4eA3iP*m!MWM(gB#l_?9R1;{;m7!-QYO=_y%ItlLqaYQFV4fhr z&zb?~KjU_F^&+r@48zWO&eU1lkk!8)!R=z)=ev|0z`6~&*vENglD(X#Htr!34P%LJ zZX9hK$79i-{?YRqJIQD38z}26g%syyI0`rhdi*-X&Rdbt_G+5L`J$6|#n9EI3B=Xh z4|!2_nAIYL&7T~Y#r~3sRdXsT(XCi)C_Mz}z7tDsg#lBlg*jTiJ22SL>Cn-7R*r#Bj z`+hy_A7*kr$q?t-H(_L3Ftm65CgsXO)O(x>+b!y*Q@*GW(KbgYN^ssZcfP(X`iIi< zp3qnFAlX*A^i&Lw$sft2Ln9s#vvJ(+C+A^5;^u0PeZLUxbr!!54=1A4L-d%YF`E+h zfF|Tt64}#FQFOf-hmQ|IwEHV8Y*r(>-6FNLXbcPG80f-RbGRN%9i9(jF?~%p%y0GL zkWoAw)QwUmT46VqFS6xpU6p2n zulj8MJbT)1AO-P*k>F``pia~er>CD0#d-Yi&x8v4ZmY6=C&x3>4=sWVpQd23K@xO# z_F=)AE@T~fgR&q+WIVT~tFP!X*L|az?XNu+fuA;_Uhx}bnul=hdn5MD4TfILPm;Ln z3ALMP!d$m?Q59oNvZwhHmOc87lx`6mDl1_8;5Iksx|0`c^QlxYkDayqO0W3(k?%jf z(SEWD`~5{64=TWr&>jvFy?obnA@x<~Jo|cIYEe`}E-ea$Pc2t}IR-j0J{^~1Rv~Bd ztyIYjc_!nf&9rT1(yFBK*uMB3Hhu5L`w6{p;k-hNTL$RyQle_wTFm{R5}PKp66iBN z1QHB$Ck#S@V`>_w!{Ih}kTjdzpc$LFIq0wiQ$6;E-!c3M6kYRBIZ1>|(zUo6a3B5F zuZWXZB0V0?>>9KaEr{#r20EzDWBvc4=+=Z( z65{BOjOcoV_zTgWosG-pwm5IRf^RryB&&|rXQyr)qZY-|m^S7Ww(RV{n67?wu@uCQ zorA{ED8ZtcYRt1&oqbHE#?cIcKb2ONb$kKFI7n3c0b!D72y2Q)9@9q=Z8=c<@Xpd z@pK=W6q`m0_i?)Q=_&ku)?+4EbiV^>X5AokHmLSR_#HG zklRg*jKi55RuHYXaCppqP2R{s@(T|&feGlT-Tli z6x|f~y0#4kZPiG3zmF;Q&CGlDX>Q%!SeSdri|m{4BsWtWp;Gx7sjE9t;Z_Q*{L63^ zp-i$qmcL9h6Xu7%^NR;|vxB*(QH%ntA@Aolt8dtucO2ox6PcoJCC~X}Djxp`<6EXA zu!)xbAchmacXbf6n+Ct|HPBl&LSj(dUDU5P5OEW>bKPA^`1dayYUgU9NZ#sj{W!=i zAB)`bm(p$_>cYlNQ#6HUOAY&sg1kd4yyS>IJX{A|ok;vt>w|`#EBHmyXud`F5J9FN zt?P!Y0L(w4abXAYM*czBi2!)|r?G}%!90e%)vL&>ThVO@yXNACu#8;1sqDnf_CjoH z@<#m4t56Q7EvZ686SRDF# zo{w2q#k#+_hr1vCqU>!ORs<*Fz))Kp*jE%EK>olb_Jc(KcV@hd4MNtHr}(g<5y63t zi0=6un>Oh|f4?q2_e4kB-`r1RZWtu()?kCM;|Zvn+6IlFYFKr-5C87@)H96nWF+OQEcC8G9Uq*@6G*6{Nd6J*&nPV zW=$~=`${(O1sOdsEi3|A6}4D*xrH?Nw`j~9gKnxqy5JBoY9Sh8Qm<60%Z<_KqD~Ck z4&t7wY7u(y5!|o!LaOdM{_d;3NPMm&@@wj?H>R${h;FHPIi&;FGApn!`zHPy_JQr{ z7s}20nhIa?>N>Fz%yR27jNh6E`DE&sT?^rO#2XjfkFdr1x%^d@nYiy9&#%3@%M_OQ z!sk*6R)%-tc5WsvjM;^1>1WB4LRm3n8TtBNpXF6@HOy^$FwRV=hVH>OEa{U7i`6qQ zesMRcdA*A8R~#g^k2T~T4Z851{S2$mH6n&IwFHZ25NW!ok1^z>T7!fp>2I%W6r}6j zW3zjQhuu70+?a&BkI0mlelnWlFRb?t(4pe36lz`14;0%IEuH z$=SQ?-oJQW^O>HPUk;zXT@*@)uP&7A>{7lE7cy9!Y@9~f4EHx#)EQBW| zeqh&=Z^EIn0z2tl-}dDrt_Q5dhVlmMK-nImCSPCpmapONe!XBsOlKtNnkQGbz=FKG z^}(ajs+%Sa_@W`^*boa^D3#909fQ1+Z;8nyo%C}p9tB6h{#6fL{l1Z>SQv<32bDy# zsix%o^3}*WnTlbgsfC@bz^ae_IPd(PUHkrkAAM{p4&_(zB@JWQ2ifCz@ih;bRO4E{ zE`XPp7u2iwGhRYo-M?nyn@Su%5gW{Ghg?QVp5ER z;(c!(Gryj7>fDFr!)lBg*@g*+5@4NS1GYwAs2L{eVc>L@^;`j;`v0zzY{ONaMDzNb$?>#G>1#S#Lbe})4U)=!*i;oDYUyjt%iPj4D zdx%XQ`XVN8IgeS;2ks*x5%OOh%H>;Ny)qX4K8-}TX*ts8uA0Q|s0*KyFQo4;kHsAG zID~#`L6%o7UVaZp zG+u`J(NYW{?&)sBXS~_th(qzOCENVu#j1zo)m?d-E6!+Uqn_VKwEREVO`vZgT!7jS zI9iRB4pLAh&zX)`y;Or2DjQ%#+H;syG(uCY5%SU}XgZ*co&!ekfrh%GaCcu3b3HOX zp>h`Nkp%gH?I^eS3;Vht%r7lxm*Xz-N6p5frLL1NbFYv%-rS2|x>I$7$(Q=>7cShs zh^%EdncCw-KK~5OwT5SL?amYIRPh-UoGHT19GZVk$VKz=qiFl1#{z0<`6u!UjE}#| zH|u|9%RO$v)9DXd$Xnh2_6M9AxD3y={H)U!^%M%D^u;{w#eCJAz6eZ+#G7w*xFc=G zqL***Sat;7bq_@>F>nLK9RRt zue+%FF;{ZlW*y|dry+qj(A|FJSVNlHgD>$c%;pi-wIUt&P&rrDldy^09o5O-kV$j? z>fj#;>vkHJIrgkVyMRCSG!sevU-Pq8;jHsDc>|2gkV`%3Dc8@~+1CM)k_buq$u2^< zj}hsvCwcYaHg+L01Z5-t!H>MU+XoBuz9pgg&=RR7RK=Cs+TvMeKmPf=A<{3u!1Xar z*!;2qvkabK_rrnsU2DNR9_fk$JQ067ehwDAPeQO=JNkaD!s}r{Sm(#++k2gyWnC?SUViuNAEflxy7fi$jG|cy7$szA~Q@EMPH_POvn@_Wy_s_zm zt_a=fJY04>2Zu8bV^X>noAR!n=T0CFv?GwK>SnQ_L}kpa{Db)J9f<7qf!@<4NUvUH z?YOa**mqn{_-fhl|Gv|l+xaoJ%&o`tHO(+rB@Xn0IeceSOSAS56k+ZI#ANlm((JhL zuzLIsf8|@TPPrBf=Y=7%wJTyzIP*``8}!-PP0VfDAhDHfz>H1l*zl|aJ;s#7Tu~3liJffZ)KF-VrZ!Ny4X&mf zqx)MUw{DAc>G=L4_@uU|t?b29CKzLy#Y<%SG(mHA0}gn{U|+cghT4qhCSwN+`;iQlXJK8bOr3yX{cTw+L%tj5k#{Vdri1#Y(eCSg-X7|Ab0sFsVv|A^h z%l^XPJ{NFy+Z8tILJGGbb}PdvgO_eO!?xc$hg0KzqNKGG?n=Z3Xu3l8A!%x<4LokJ zsn|T^7C+S|m&wTAhST^;@ZY4Volilm?ILWtp=|v?j(XeedZOD`Tb@&|ikzm$q_x*0 zaRq%}rmvw|F%g)JJiP)n?+dT`Av|GmqJyJAo-r zzJn3l-_e+lY|WGC`DG0&xc!qGFEta_JfHIy4KZw_<~7Wg`Heqvov@sk0gJ$`C>B>F z%d!rMo0D#pzTJ{anEiOHP%$YW%NP@k5@YaGur z*`>s(#r?z<%4w*Yn~iT*521LYGP}5?nR`An5uOhIe0k`;Ff6eiS&Gd_y7db2YllE_Ul(3Wo=LwzH4zx$ zE&Zb~8FGW9_%^MTd|x$4Xnug3)8%p2^)T-|Zz!sMcNHa*Pf2WKx4?e>CkO-L*cblB zl3~}Wj(EmOYGZiEF*9M8_=`u*T*~y}38QKG@KUEdHP3uJ8s>>r&db>Xk6--9PBY=4 z`jlsHea^}U;Y1$bZpK@Xk?bwm^Q5cLAT4iAjw{#vB!{S94`4i@hCENL z`2IJZ7>UWaGQ~?86RIYPjI@OB(Jnk7&I}12uMjY)8Oh`&e`gzw{1a+0JOR#A28-SY z$*a2{_ic3f0t_fhMyNwOcxNR(=G{i|%kNCP)1SZ8G7$xuEqvvY-fZRbgLrx^8=H#A zUzhe1FHfFFl(G+NT9U?xY7G%rmw)6xk6&b!^c)+^ilNle3F(io$jCTA9$_VR%Dk0Z z>@X4IcKPwM7Yo>yb$5`mtO_gUw&VG#WHi~%Cr)w6JIh0T#HhuCMS18{9@;nn$|2E| zZP0)})lJY%dWqO1Qxy4h=O12bi5g*P6Va{Md-qY*X)( zct)C97HQUnee+S{d4jm-`ApZbln?J?CN7MQ;k}JtG5>_?n0fytB+_b*hOgEdz!6`3|Xb z<4_dTy~4FU&2T(ikMiYFIQ&i(Uq;R3e?T1bxZc9Lux*;k%0)2Ql7eoJN!uchwl+5q z>dJX+VrBquBJcXEhDKhqM~&?{@E^V?zW`HSjAYS?Hqz9phwsO(&0U!J>ULgPZY-|tzQz^fell~DyIAsuyt-QL*!aI0 z$GdshJ#1)v?vFm=bCs^RT04R7x~%~_%3QeIuK{D|8V?5DD2jCvWTz8`9*spF=~~9D2ur*8NPly@opKgS=MEXFMlrqk7u<{P;8nUsJaFD-_Vdn3MC|&3QLvin@GgmuA`FC@}5LQ}) z-^#7nT>OsmBgez|eSkFf@c?1GbfD16u9c4WGsno7*QmVQj5AjCczoqCMq2cPPg(b6d|MWES;ODS!M6f{7i?LICJ7XZ)4Zlf!7xhIrJAsQJ?1CoP}7keYmoz zL*kv-!2?^3#p<7z`T0ksYi53H4yv6)=?4IAY>kZ?u9{w^u!i~5=gThB+ljq>l3C<~@w26;b=DQhA( z4d!X&;4&pdI^I@YlxqzX zeWOdHaYIJn@zOVVPhQ=Ue)VX79EpL6eQ|EsBCf1RzNv3Lg@way>+YMEqAB_V?)E2t zu>T(vpS^`#<4o3b%U%9vx2YI$y_V0KIhg&DJBnUCa`9e8#%9a3BJ7xU7AN<6vR5r% z_ywvrj=LrDYhC==mHB)jY! z@w((Q6zM$F`B;iO6_=5F=phs5W4ZisGvQ&A&wGXLVlI16!(v$h>NRC-eogp>Zr1M5 z&z{8AF8RaPDG`HG5XS4SlUH|wKi1}#W3OKa##yIfvGrP%Ew_}EMRyldCmM*_c@EsN zs}lBxhQl?g7OEFp$o~_EiC4xVQ|Fm9@2a}ca?li3{l7~~`ACEy7R%o^qi13rdKyRK z<;Oml9=Du-kk=Onh%2;vkYL^BvmDn)e#EBX9k7`72Zdh(uq!K#jV=x1sTYZPOsL`8 z&YG~Tq^ZqZm5Z0Hte~#s;ddPLx;gjohgh9W4LR6SamxtKEd{hE1@245V zp=#V&b|1UOHL%K1Z>|$!Brev=3AY$7G3f1tQ146>8Fiw|rcy*$Uq& zOz?Z;)s1ms;rqOBz_$SFh(Yno%Y)|9p$x4~X9@SbZ@SY^;nocdLPCz>5#7OBuIT!|G^6(j{lJ&0w~7vpZP z=VhCEp~mVFeAMdjd~pjL_1?m3nFXHqO_NqF(-1p?HN=tF1gY}iF)#>xOW7AKDATQj z&9?|hdi2C`#|`{>oxa#9RT9;M`bx|vtj4>+sTl6tf%n8TJ~O$A)NAiqfm0}d@!eEB zcl*oP7E3nq`!V7x^1yn?*qk#eMA!elgJ%CRx!ZZXuz<7y!*}Ev2xhM%e5vOu#V-F& zB(2QEeXX5%{Uk-wa9vL5&o&l$w%%Mjtd@P0y^pbbt5HSY#C4|xXr7&pIQxOp{8RnJ zcFOuJx;&WM)(pmr;%C@K45&{VMVad$%$;J!mG%r0%al}v)0n1sy^fg}7oLa> zZfzJ^{g-lI?xD%Nnw1>z;aBz-6i;|-)3Jo zbKZq&ro$y)`M2%In4jVqltvaJh|Yek-4On52y2^D!-p?66-qI|{L!Q|c4T${ z%@_Y*s2b&|c~kz~=oL`Em}h+@y@!z9t1oI?R`Rxr-bnxV2o0O-FnLl7<}QiF^;e_d zZkQvTNL=Ck4${K`lz9wFr()sA2yJm>1lwI#1(oBY{GD*Ms%xxLbEb$ zjBFpqSL*4C*Kw3{@Gm+(d(JGJGEKtB;x=qM_ZJHagV1p04|{juA|Fv@Ec#E95#D>s zC9ZjUuum63CT1B9y$Q57)$S>TroMP+ zw3LsHP)6OSNOYq)Pj;Uce93u3_uU9gp7m48_i2hd0qWv-VWf0wffcO6;$UCef}a~| zF>zBk(yw(x!U+c+RA3<77IzmD)omoB?APJ`nlw};kpKRBIhxkqfK!!}t*|3jf3TUb z$gZIL8pdpwyJOjzZ@5Wp|CT`oc%^z8{>vPhv^1X^(~Nvd#cLjs9mcXQT)~j2QmF6m z#MSMTf9L6dm6}nKqE>maGr~ypT6dC{xU{kjn?qn~L7pDc)Z`WkG(VHTe}IjYQO(y} zp)J;&R^vuD3}Hdu1t-fUB&Ids@~kJgV@Y`-u;32Ubw#oP<==UF$5W$&n5-li$+yGb z{4Z9`4#J;fWlU|kFPD-=lc3khU;nC?`2KLlIw$h#{_KR-!e3agP8w(^X=)xx{Bx_B z=-86UdmK8&wEjDbtI1RYmr)&=n}ehehw1l&SVjc2Pkt<=@r!tVfSK&DcEf4Ym#+j@Z0P>37G0 zqU7iR5xXK-dS>Q$jB$R4Mypor%&fuOcVW<)sfZIfd-#V^17W$Uo2Xm9RI;IAJ@(k9 zQ@&LPTwKaAlIHZs(%-TreI9d}C#ItBqH=ETI)i!a^1x%m?+74&I0Ye~X~8K-)Hk!O zQwsROr)FZH&MU4xJCfP2zlyk?WjMEv>J7@dadh2|E&=x?V`zx&>0uaVn^F6qOiy^K-v-714clSElKRt%5NK0X&dd*9=geLHdLRk#;;7t?P2Vs<00@>mBG;c}{tCsuY! zir2ZIcH~!#qZxx+MlsACE}-hjRrd5!3TMPwAMncHjsv{e=Jn^WZr4w2C$04PnjEO# zcZHqH0Jd^M6W7Z%5xv*l;#0q7lh-K_$7WW-yr~_N_N2gS|6+Jl^tD!a)=ShK)Dw#i z&EkE3_Ct+M6lLSrWBc4@1f6*eH@jiz*w`q&^>3i4QWzkfD%_9;7*9lwd^{}Iwj!Of zjhv&PN!_!Ywrv#pVAfGrkp_wNmI^nTny84@jrF z^cVfiw8e|zJ-AP@3B08*@#$C-wykJ@a!oXzT~&vKP39{G4i-a51640edAIMg9hQ=p zuimX4=Ci91o_PmJPK8YV(KQ|&U?QHBxAK;siY!h009N~a#ajBl?q4s)#@Rlw`0C4w zx_;zSY33U1md>ZFInSQ`Jcol{eqt7Rum@ephIZy5)Q;-M`kFR#>lzbLbIG5VW#%#e z1GlM7)Fa|s6GBPDI1)Dm z2WQLims_+%o-cr_IZFtP;TtBJiEaKReEp!s?1{A}9{&6e=b$vZ*ZTlOb>tKAHbNf#vTKOkPb2IZuImRU++lRFt*%TG!-D5!}!DOzHeg#yo5ZH7jtS6J}138Jwc zuSrweQAnIx7YQHtX0WjMNt&9~*0={J7r^R&UfI{}`0%|F^ZVU_+@XB7`^XKh@qqF` z^;-Do#$GJp#zFj>os9#WveAbWV}{Rpl+3@t>?f!3x$$PA;bAHtYJHI{%RP_I;l-Ft z&vl4WHVPIW#5wOCtlpBi!f4V|WBmB+B|li@qC1fOt;7NH2(Q_i4BhARp=(+hx7DnV z2tPeo{Oe`SP3{kX`NC+NBaYSnLlZt2y+U%aDQvEH<)8DkL{AMhQTOz?G}mSd7CA|w z;NObv!)qvK@&Qs#$zgVx8#m1)&DyG~*spy_Vt#E44t0LQ70SF{Qc?zu&}(@3^$D|{ z_KbhHM7{itpWI5af?fRUi3@l0kwkfgXX}W2Dm;NK^Mx!!yOcY%n~GlnF??m$mn`4= zI_C1p=pok6szDIt^95dy2OBjB zD^z`@MviJCd7YNHzEp-QEEtL~h1aCJ6898RkAjdW^vYMoxc<|5PvX?{w)GY=zQNNt zX=<~`nX5%nra=*Iy6X#!@ z!|r?MShD3OenfkSD2-3yA8anOSKdBYOkD3p%4tZN_!a*Z?}wgpSEl#4jTaDCsQ2$G ze_vO~oRsfEa=i*$iSPEve2)W5?cnO77%vQzMNELMX#O{e&r#JNA6yJ&L6VoysR@s+ zyu=+x6X?13=8G$}g!A0~;(nd8^w0UJn8#@3`-(KsPyevbHxvt^WDsEO&W8;&5;_hF z!Xo*m#PGy6+}M|aQ`0-)zpo6Je_uuLk|-8x{DQx|XC{KX7xBRh*RywTPU6xa(r8GJ z(((I_MZY~T>E;}^pO^9CCQ~ulCyKAid&BC+`k~6S98%taq8sUGG1>^jo(_`hzZJzP zW+*(C?c*cr6mZro3=6_)Fn>iW_I`bb8U7Q{wdSVu{_+7r)^DH~YF96n`#KEC4_+hn zLNneBs)v_s6#hHZ53kJU@RY0n HYF|xM&u^8W_DR9kf$07-xPkRFKenK`|@i36v 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 AL;wH) diff --git a/test/torchaudio_unittest/assets/kaldi/resample-16000-27000.ark b/test/torchaudio_unittest/assets/kaldi/resample-16000-27000.ark deleted file mode 100644 index 7c79b730c8fc563b2c6a986048704d7c250d6794..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 54021 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 diff --git a/test/torchaudio_unittest/assets/kaldi/resample-16000-28000.ark b/test/torchaudio_unittest/assets/kaldi/resample-16000-28000.ark deleted file mode 100644 index 48089fe217f07c4f9b81abe7d4d85e21c8eb4ccf..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 56021 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

fvKkC4JN!zwNPSi=3E0&t78e@}0I`^;B+{c~_ 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 C&1a?n diff --git a/test/torchaudio_unittest/assets/kaldi/resample-16000-17000.ark b/test/torchaudio_unittest/assets/kaldi/resample-16000-17000.ark deleted file mode 100644 index bae29a3bcfab0fe4abd08fb62567ecbae0309fc5..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 34021 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 VV#vm(YtvtYHh4Cy2PbZq;D4RC>yQ8d diff --git a/test/torchaudio_unittest/assets/kaldi/resample-16000-18000.ark b/test/torchaudio_unittest/assets/kaldi/resample-16000-18000.ark deleted file mode 100644 index 347b55972b1cc821796c2dd259f56f93c17dfd22..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 36021 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 >wnL+hCp{S~~<@=?_x-ph=zaf^Fdb<8aR9 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

~GMt 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 X6 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